<?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: Sabith KS</title>
    <description>The latest articles on DEV Community by Sabith KS (@sks).</description>
    <link>https://dev.to/sks</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%2F180380%2F5047aa95-dce9-4b00-9d75-5f59434b5059.jpeg</url>
      <title>DEV Community: Sabith KS</title>
      <link>https://dev.to/sks</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sks"/>
    <language>en</language>
    <item>
      <title>Just realized the JSON pain has been already solved thanks to github.com/kaptinlin/jsonrepair 

Shout out to @kaptinlin</title>
      <dc:creator>Sabith KS</dc:creator>
      <pubDate>Fri, 03 Jul 2026 18:41:46 +0000</pubDate>
      <link>https://dev.to/sks/just-realized-the-json-pain-has-been-already-solved-thanks-to-githubcomkaptinlinjsonrepair-eo6</link>
      <guid>https://dev.to/sks/just-realized-the-json-pain-has-been-already-solved-thanks-to-githubcomkaptinlinjsonrepair-eo6</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/sks/why-we-chose-go-for-our-ai-agent-platform-when-everyone-else-picked-python-4ok2" class="crayons-story__hidden-navigation-link"&gt;Why We Chose Go for Our AI Agent Platform (When Everyone Else Picked Python)&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/sks" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F180380%2F5047aa95-dce9-4b00-9d75-5f59434b5059.jpeg" alt="sks profile" class="crayons-avatar__image" width="233" height="233"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/sks" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Sabith KS
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Sabith KS
                
              
              &lt;div id="story-author-preview-content-4045427" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/sks" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F180380%2F5047aa95-dce9-4b00-9d75-5f59434b5059.jpeg" class="crayons-avatar__image" alt="" width="233" height="233"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Sabith KS&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/sks/why-we-chose-go-for-our-ai-agent-platform-when-everyone-else-picked-python-4ok2" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 1&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/sks/why-we-chose-go-for-our-ai-agent-platform-when-everyone-else-picked-python-4ok2" id="article-link-4045427"&gt;
          Why We Chose Go for Our AI Agent Platform (When Everyone Else Picked Python)
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/go"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;go&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/aiagents"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;aiagents&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/architecture"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;architecture&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/llm"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;llm&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/sks/why-we-chose-go-for-our-ai-agent-platform-when-everyone-else-picked-python-4ok2#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            1 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success crayons-icon c-btn__icon"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>github</category>
      <category>go</category>
      <category>opensource</category>
      <category>tooling</category>
    </item>
    <item>
      <title>The HITL Paradox — When Human Approval Makes Agents Worse</title>
      <dc:creator>Sabith KS</dc:creator>
      <pubDate>Wed, 01 Jul 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/sks/the-hitl-paradox-when-human-approval-makes-agents-worse-1095</link>
      <guid>https://dev.to/sks/the-hitl-paradox-when-human-approval-makes-agents-worse-1095</guid>
      <description>&lt;p&gt;Human-in-the-loop (HITL) is supposed to make agents safer. Put a human between the agent and the dangerous action. Simple.&lt;/p&gt;

&lt;p&gt;In practice, HITL has a paradox: &lt;strong&gt;too much approval kills productivity, too little kills safety, and the wrong amount creates a false sense of security.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We deployed HITL for our agent runtime and watched three failure modes emerge. Here’s what happened and how we fixed each one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure Mode 1: Approval Fatigue
&lt;/h2&gt;

&lt;p&gt;Our first HITL deployment required approval for every tool call. Shell commands, web searches, memory reads — everything needed a human click.&lt;/p&gt;

&lt;p&gt;Within two days, operators were auto-approving everything without reading the details. The approval popup became muscle memory: see popup → click approve → continue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The data:&lt;/strong&gt; We tracked approval latency. In week 1, operators spent an average of 8 seconds reviewing each request. By week 2, it was under 2 seconds. They weren’t reviewing — they were dismissing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this is worse than no HITL:&lt;/strong&gt; Operators now believe they have a safety net. They don’t. The safety net is a rubber stamp. But everyone — operators, managers, auditors — thinks the system is reviewed because “human approval is required.”&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix: Risk-Based Classification
&lt;/h3&gt;

&lt;p&gt;We classified tools into three tiers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[hitl]&lt;/span&gt;
&lt;span class="c"&gt;# Never needs approval — safe, read-only, or internal&lt;/span&gt;
&lt;span class="py"&gt;always_allowed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"web_search"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"memory_*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"read_*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"discover_skills"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"note"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c"&gt;# Needs approval — can modify external state&lt;/span&gt;
&lt;span class="c"&gt;# (This is the default for any tool not in always_allowed)&lt;/span&gt;

&lt;span class="c"&gt;# Never allowed — blocked entirely, regardless of approval&lt;/span&gt;
&lt;span class="py"&gt;denied_tools&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"bash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"shell_*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An important subtlety: &lt;strong&gt;these lists match tool names, not shell command strings.&lt;/strong&gt; &lt;code&gt;denied_tools = ["bash"]&lt;/code&gt; blocks the tool named &lt;code&gt;bash&lt;/code&gt; from being invoked at all — it doesn’t do regex matching against command arguments passed to &lt;code&gt;run_shell&lt;/code&gt;. String-level blocklisting on shell primitives (e.g., blocking “rm” as a substring) is fundamentally unsafe — any sufficiently creative LLM can bypass it via base64 encoding, variable interpolation, or aliasing. Instead, the HITL gate operates at the &lt;strong&gt;tool invocation boundary&lt;/strong&gt; : &lt;code&gt;run_shell&lt;/code&gt; as a whole requires human approval, and the human sees the full command in the approval request. If you need granular command-level control, the right approach is typed Go API clients (e.g., a Kubernetes Go client with RBAC) instead of raw shell access.&lt;/p&gt;

&lt;p&gt;Only state-modifying tools require approval. Read-only operations auto-approve. Destructive tool names hard-block regardless of approval.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Approval requests dropped by 70%. Operators now see 3-5 requests per task instead of 20+. Each request is meaningful — they actually read them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure Mode 2: The &lt;code&gt;always_allowed = ["*"]&lt;/code&gt; Escape Hatch
&lt;/h2&gt;

&lt;p&gt;Some teams set &lt;code&gt;always_allowed = ["*"]&lt;/code&gt; to skip all approvals. They’d been burned by approval fatigue and decided HITL wasn’t worth the friction.&lt;/p&gt;

&lt;p&gt;This defeats the entire purpose of governance. An agent with &lt;code&gt;always_allowed = ["*"]&lt;/code&gt; can execute any tool without review — including shell commands on production servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix: Guardrails on the Guardrails
&lt;/h3&gt;

&lt;p&gt;We added warnings when &lt;code&gt;always_allowed&lt;/code&gt; contains wildcards:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;⚠️ Warning: always_allowed contains "*" — all tools will bypass 
HITL approval. This includes run_shell, kubectl, and other 
state-modifying tools. Are you sure?

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real safeguard is the &lt;code&gt;denied_tools&lt;/code&gt; list — even when &lt;code&gt;always_allowed = ["*"]&lt;/code&gt;, any tool in &lt;code&gt;denied_tools&lt;/code&gt; is hard-blocked. So teams that want minimal friction can set &lt;code&gt;always_allowed = ["*"]&lt;/code&gt; while keeping the most dangerous tool names denied:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[hitl]&lt;/span&gt;
&lt;span class="py"&gt;always_allowed&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;denied_tools&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"bash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"shell_*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives teams the fast workflow they want while maintaining hard gates on the most dangerous operations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure Mode 3: Blocking on Approval Halts Everything
&lt;/h2&gt;

&lt;p&gt;Early HITL was synchronous — the agent stopped working and waited for approval. If the operator was in a meeting, the agent sat idle for 45 minutes waiting for a click.&lt;/p&gt;

&lt;p&gt;For a single approval, this is annoying. For a task requiring 5 approvals across different tools, the total wait time could exceed the task’s useful lifetime.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix: Asynchronous Approval
&lt;/h3&gt;

&lt;p&gt;HITL approval is now asynchronous:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Agent encounters a tool that requires approval&lt;/li&gt;
&lt;li&gt;Stores the pending request in the database with a TTL (default: 30 minutes)&lt;/li&gt;
&lt;li&gt;Sends a notification via the event bus (Slack, web UI, AG-UI protocol)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Continues working on other parts of the task&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;When approved, the tool executes and results flow back&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The agent doesn’t block. If it has parallel sub-tasks, it works on those while waiting. If there’s nothing else to do, it waits — but the user sees a clear “waiting for approval” status, not a mysteriously silent agent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A note on state drift:&lt;/strong&gt; Asynchronous approval introduces a classic distributed systems risk — the environment state may change between when the agent formulated the tool call and when a human approves it 20 minutes later. We mitigate this with short approval TTLs (stale approvals auto-expire via a background reaper) and session-scoped approval caching that expires entries after 10 minutes, ensuring that long-deferred approvals don’t execute against a drifted environment without the agent re-evaluating.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Batch operations:&lt;/strong&gt; Operators can view multiple pending requests at once via the &lt;code&gt;ListPending&lt;/code&gt; API, grouped by tool name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pending approvals (3):
  [✅ Approve All] [❌ Reject All]

  🔧 run_shell: kubectl get pods -n production
  🔧 run_shell: kubectl describe pod api-server-7d8f
  🔧 run_shell: kubectl logs api-server-7d8f --tail=50

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One important guardrail: the “Approve All” pattern works well for &lt;strong&gt;read-only investigation commands&lt;/strong&gt; like the above. For state-modifying operations, each approval should be reviewed individually — otherwise you recreate the rubber-stamp problem at a higher abstraction level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens on rejection?&lt;/strong&gt; When a human rejects a tool call (with or without feedback), the middleware returns an &lt;code&gt;ErrToolCallRejected&lt;/code&gt; error to the agent’s context. This isn’t a hard cancellation — the LLM receives the rejection as a tool error and can replan. If the human provided feedback (e.g., “use the staging cluster instead”), the agent sees it and can adjust its approach. This gives operators a conversational override, not just a binary approve/deny gate.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hidden Bug: HITL Bypass on Sub-Agents
&lt;/h2&gt;

&lt;p&gt;This was a real security issue. When our agent delegated to sub-agents via ReAcTree, the sub-agent’s tools were bound directly from the registry — &lt;strong&gt;without the HITL middleware wrapper&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A sub-agent could run &lt;code&gt;run_shell&lt;/code&gt; without approval, even though the parent agent required it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it happened:&lt;/strong&gt; The sub-agent tool binding was written before HITL existed. When we added HITL, we wrapped the parent’s tools but forgot the sub-agent delegation path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; All tool binding — parent, sub-agent, plan-step, fallback — goes through the same &lt;code&gt;ToolWrapSvc&lt;/code&gt; middleware chain. One path. One governance stack. No exceptions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The lesson:&lt;/strong&gt; When you add a governance layer, you must audit every tool execution path. The path you forget is the one that gets exploited.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Good HITL Looks Like
&lt;/h2&gt;

&lt;p&gt;After three iterations, here’s our current model:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool Type&lt;/th&gt;
&lt;th&gt;Behavior&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Read-only&lt;/td&gt;
&lt;td&gt;Auto-approve&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;web_search&lt;/code&gt;, &lt;code&gt;memory_search&lt;/code&gt;, &lt;code&gt;read_file&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Informational&lt;/td&gt;
&lt;td&gt;Auto-approve&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;discover_skills&lt;/code&gt;, &lt;code&gt;list_pods&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State-modifying&lt;/td&gt;
&lt;td&gt;Require approval&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;run_shell&lt;/code&gt;, &lt;code&gt;commit_code&lt;/code&gt;, &lt;code&gt;create_pr&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Destructive&lt;/td&gt;
&lt;td&gt;Hard deny&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;rm -rf&lt;/code&gt;, &lt;code&gt;kubectl delete namespace&lt;/code&gt;, &lt;code&gt;DROP TABLE&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory writes&lt;/td&gt;
&lt;td&gt;Exempt (not state)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;memory_manage&lt;/code&gt;, &lt;code&gt;note&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The exemption for memory writes&lt;/strong&gt; is important. Memory tools modify the agent’s internal state, not external systems. Requiring approval for every &lt;code&gt;memory_manage&lt;/code&gt; call would trigger approval fatigue without adding safety — the agent is only modifying its own notes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Metrics That Matter
&lt;/h2&gt;

&lt;p&gt;Track these to know if your HITL system is working:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Approval latency&lt;/strong&gt; — If it drops below 3 seconds, operators aren’t reading requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approval rate&lt;/strong&gt; — If it’s above 95%, you’re probably approving too aggressively&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rejection rate&lt;/strong&gt; — If it’s below 1%, either your agent is perfect or nobody is paying attention&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time-to-abandon&lt;/strong&gt; — How long before operators set &lt;code&gt;always_allowed = ["*"]&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our current numbers: ~6 second average approval latency, 88% approval rate, 7% rejection rate, 5% auto-expired (operator didn’t respond in time).&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Less approval is more safety.&lt;/strong&gt; Fewer, higher-signal approval requests get more attention than constant popups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Classify tools by risk, not by category.&lt;/strong&gt; Not all shell commands are dangerous. &lt;code&gt;kubectl get pods&lt;/code&gt; is read-only; &lt;code&gt;kubectl delete pod&lt;/code&gt; is not.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Make approval asynchronous.&lt;/strong&gt; Synchronous blocking kills agent productivity and operator patience.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Audit every tool path.&lt;/strong&gt; HITL that applies to 90% of tool calls creates a false sense of security. The 10% that bypasses it is where the risk lives.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Memory tools are not external state.&lt;/strong&gt; Don’t require approval for internal memory operations — it’s noise that drowns out real signals.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;How does your team handle the approval fatigue problem? I’d love to hear about alternative approaches. Find me on &lt;a href="https://github.com/sks" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; or &lt;a href="https://linkedin.com/in/sabithks" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;🚀 &lt;strong&gt;We’re building AI-powered SRE at StackGen.&lt;/strong&gt; If you’re tired of 3 AM pages and want AI agents that triage incidents, run diagnostics, and draft RCA reports — check out &lt;a href="https://ai.stackgen.com" rel="noopener noreferrer"&gt;ai.stackgen.com&lt;/a&gt; and try our new SRE offering.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>hitl</category>
      <category>aiagents</category>
      <category>ux</category>
      <category>governance</category>
    </item>
    <item>
      <title>Why We Chose Go for Our AI Agent Platform (When Everyone Else Picked Python)</title>
      <dc:creator>Sabith KS</dc:creator>
      <pubDate>Sat, 20 Jun 2026 17:00:00 +0000</pubDate>
      <link>https://dev.to/sks/why-we-chose-go-for-our-ai-agent-platform-when-everyone-else-picked-python-4ok2</link>
      <guid>https://dev.to/sks/why-we-chose-go-for-our-ai-agent-platform-when-everyone-else-picked-python-4ok2</guid>
      <description>&lt;p&gt;Every AI framework is in Python. We built ours in Go. Here's why we'd do it again — and when you shouldn't.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://sks.github.io/blog/why-go/" rel="noopener noreferrer"&gt;Production Notes&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv53in0x6pv79n3isdsuw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv53in0x6pv79n3isdsuw.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>aiagents</category>
      <category>architecture</category>
      <category>llm</category>
    </item>
  </channel>
</rss>
