<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alex Amancio (Candoa)</title>
    <description>The latest articles on DEV Community by Alex Amancio (Candoa) (@alex_amanciocandoa_49c).</description>
    <link>https://dev.to/alex_amanciocandoa_49c</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3232782%2F85e5c8f2-b6f3-4a1b-adef-51aaa4309a0c.png</url>
      <title>DEV Community: Alex Amancio (Candoa)</title>
      <link>https://dev.to/alex_amanciocandoa_49c</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alex_amanciocandoa_49c"/>
    <language>en</language>
    <item>
      <title>The gate for an agent belongs in the environment, not in the agent</title>
      <dc:creator>Alex Amancio (Candoa)</dc:creator>
      <pubDate>Fri, 31 Jul 2026 21:47:25 +0000</pubDate>
      <link>https://dev.to/alex_amanciocandoa_49c/the-gate-for-an-agent-belongs-in-the-environment-not-in-the-agent-1g69</link>
      <guid>https://dev.to/alex_amanciocandoa_49c/the-gate-for-an-agent-belongs-in-the-environment-not-in-the-agent-1g69</guid>
      <description>&lt;p&gt;There's a discussion running on Product Hunt right now about where an AI agent should stop and hand a decision back to a person. The framing that stuck with me: "can this be undone?" is the wrong gate. It over-fires on things nobody cares about, like writing a log line, and under-fires on the ones that actually hurt. A mass email. A migration you can only roll back with downtime.&lt;/p&gt;

&lt;p&gt;The proposed replacement is reach. Not "is this safe" but "how far does this go if I'm wrong." And the sharpest point in that thread is that the agent is the worst possible judge of its own reach, because it doesn't know there are 50,000 people on the list.&lt;/p&gt;

&lt;p&gt;I've been building a browser with an agent in it, and the browser case makes that concrete in a way the terminal case doesn't.&lt;/p&gt;

&lt;p&gt;A coding agent's blast radius is usually one person: you, reading a diff. A browser agent doesn't start there. It inherits every session you're already signed into. The reach of a click isn't a property of the agent's plan, it's a property of the cookie jar it's holding. The same "click the blue button" step is harmless on a docs site and irreversible on a payments dashboard, and nothing in the agent's own summary distinguishes them.&lt;/p&gt;

&lt;p&gt;So I stopped trying to make the agent classify risk. Here's what I do instead, with the caveat that this is alpha and I've been wrong about it before.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Some things never reach the model.&lt;/strong&gt; Credential fields are filtered out of the page snapshot before the agent sees it. That means password inputs, and anything with &lt;code&gt;cc-number&lt;/code&gt;, &lt;code&gt;cc-csc&lt;/code&gt;, &lt;code&gt;cc-exp&lt;/code&gt;, or &lt;code&gt;one-time-code&lt;/code&gt; autocomplete semantics. A fill targeting a password field refuses outright. The agent cannot misjudge the reach of a control it was never shown, and that's a stronger guarantee than any classifier, because it doesn't depend on getting a judgment right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The model's judgment is a floor, never a ceiling.&lt;/strong&gt; For everything that does reach it, the agent can say "this needs approval" and be believed. It cannot say "this is routine" and be believed. A structurally sensitive control still escalates to a native confirmation even when the model called the action ordinary. The agent can raise the gate; it can't lower it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sensitivity is read off the DOM, not off the plan.&lt;/strong&gt; What marks a control sensitive is its type and autocomplete semantics, which is evidence in the page itself, rather than the agent's description of what it means to do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A timeout is a denial, not a wait.&lt;/strong&gt; A stalled job is a silent failure; a denied one is loud, and loud failures get fixed.&lt;/p&gt;

&lt;p&gt;The part I haven't solved is denied-and-resumable. Discarding the work is clean and useless, because people want to come back twenty minutes later and continue. But that means storing the world as it was when the question was asked, and the world moved. In a browser that's especially unkind: the DOM you asked about doesn't exist anymore. I don't have a good answer for it yet.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>I built a headless React chatbot widget for full UI control</title>
      <dc:creator>Alex Amancio (Candoa)</dc:creator>
      <pubDate>Sat, 31 May 2025 18:15:23 +0000</pubDate>
      <link>https://dev.to/alex_amanciocandoa_49c/i-built-a-headless-react-chatbot-widget-for-full-ui-control-5f9n</link>
      <guid>https://dev.to/alex_amanciocandoa_49c/i-built-a-headless-react-chatbot-widget-for-full-ui-control-5f9n</guid>
      <description>&lt;p&gt;🧱 I built a headless React chatbot widget so devs can fully control the UI&lt;br&gt;
Most chatbot widgets come bloated with their own styling and markup. I wanted something I could completely control — so I built my own.&lt;/p&gt;

&lt;p&gt;👉 @candoa/chatbot is a headless React chatbot widget built for devs who love:&lt;/p&gt;

&lt;p&gt;full UI freedom,&lt;/p&gt;

&lt;p&gt;TailwindCSS,&lt;/p&gt;

&lt;p&gt;React Hooks,&lt;/p&gt;

&lt;p&gt;and minimal dependencies.&lt;/p&gt;

&lt;p&gt;⚡ Key Features&lt;br&gt;
Headless architecture (bring your own UI)&lt;/p&gt;

&lt;p&gt;Conversation persistence (localStorage)&lt;/p&gt;

&lt;p&gt;Greeting messages&lt;/p&gt;

&lt;p&gt;Typing indicators&lt;/p&gt;

&lt;p&gt;Error handling&lt;/p&gt;

&lt;p&gt;Demo GIF: &lt;a href="https://candoa-public.s3.us-east-2.amazonaws.com/chatbot-ezgif.com-loop-count.gif" rel="noopener noreferrer"&gt;https://candoa-public.s3.us-east-2.amazonaws.com/chatbot-ezgif.com-loop-count.gif&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🛠️ Install&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @candoa/chatbot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  or
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add @candoa/chatbot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;📦 Example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useChatbot&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@candoa/chatbot&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useChatbot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-project-id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Send&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’m a solo dev working on this. Would love your feedback or ideas!&lt;br&gt;
GitHub: &lt;a href="https://github.com/aamancio/candoa-chatbot" rel="noopener noreferrer"&gt;https://github.com/aamancio/candoa-chatbot&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>opensource</category>
      <category>tailwindcss</category>
    </item>
  </channel>
</rss>
