# Agents 201: The Unit Shrank
**作者**: Rohit Ghumare
**日期**: 2026-04-23T19:46:45.000Z
**来源**: [https://x.com/ghumare64/status/2047401813364683007](https://x.com/ghumare64/status/2047401813364683007)
---

Three months ago, I wrote an article that went viral: Agents 201 about orchestrating multiple agents without burning your token budget or turning coordination into chaos.
That's still true. What I missed is that the unit itself was about to change.
## What changed since January
Then, the agent was the atomic unit. Supervisor pattern. Swarm pattern. Hierarchical pattern. Every node in every diagram was "an agent."
r/claude, April 19, 866 upvotes: "Try Haiku 4.5 agents. Just as good as Sonnet if Opus is orchestrating."

- r/ClaudeCode, April 4: 138 sessions. 61.8M tokens. $11.55 per session. 15x the Max plan cost.

Nobody is shipping a better agent. They're shipping parts of one. Tier model allocation. Dependent handoffs. Blackboards. Verifier gates. Observability dashboards.
The agent got disassembled.
## Why monolithic agents are failing
A monolithic agent is a generalist. It plans, retrieves, reasons, writes, verifies, and answers in one context window. All on one model. All billed per token.
Three things break at production.
Token economics. One agent coordinating four sub-agents on the most expensive model turns a 15K-token task into 60K. The $1,593-a-month Claude Code story is what "one smart agent doing everything" actually costs.
Specialization loss. When one model plays router, coder, reviewer, summarizer, and verifier, it's good at none of them. We keep relearning this. It's the ML lesson at a new layer.
Debugging by vibes. When a supervisor holds the plan and four workers write to shared state and something is wrong at the end, you don't debug. You re-run and hope. Exactly the problem tailclaude is trying to fix with a Kubernetes-style dashboard.
## The unit is a worker

A worker does one thing. Clear identity. Defined input. Defined output. One job it gets good at.
A retriever worker retrieves. One model. One prompt. One schema. Benchmarkable. Swappable.
A verifier worker verifies. Runs after other workers. Fails loud. Has a test.
A summarizer worker summarizes. That's it. Boring. Boring is the feature.
An agent is a composition of workers. Not the other way around.
This is the shift. In January I was writing about how to orchestrate agents. The question was wrong. The question is how to compose workers into something that looks like an agent from the outside.
## Three primitives
iii ships three primitives. Worker, Function, Trigger. That's the vocabulary.

A Worker is any process that connects. Rust daemon, TypeScript service, Python script, browser tab, microVM, or an LLM itself. Long-lived WebSocket client on websockets.
A Function is a named unit of work a Worker registers. memory::recall. retrieve::web. verify::code. Called by ID plus a JSON payload.
A Trigger is what causes a Function to run. HTTP. Cron. Queue. State change. Stream event. User-defined.
That's it. No separate mental model for agents, queues, workflows, or observability.
React shipped with four concepts. Unix shipped with three. SQL shipped with three. Every paradigm that compounded over decades did it on a vocabulary small enough to hold in one head.
The smallness is the bet.
The smallest real worker
That's a complete worker. One function. One trigger. Any other worker on the engine can now call retrieve::web. Any HTTP client can POST /retrieve.
## Orchestration patterns are triggers, not architectures
Three months ago I drew supervisor, swarm, and hierarchical as three distinct architectures. They're not. They're patterns that reduce to the same primitives.
Supervisor as workers

Supervisor + specialized sub-agents (retriever, coder, analyst, summarizer) + shared memory bus. In iii the bus is the engine.
Swarm via state triggers
No supervisor. Workers subscribe to shared state. Each reacts to changes others wrote.

Swarm is not an architecture. It's a state trigger. When destination changes, flights react. When flights resolve, hotels react. No central coordinator. No framework.
Hierarchical is supervisor, recursive

Each mid-level is itself a function that triggers leaf functions. Same primitive. Different shape. You're not picking an architecture. You're picking which Functions subscribe to which Triggers.
Narrow-worker decomposition
A domain with multiple concerns is not one worker. It's several.
Memory is the canonical example. Not one memory worker. Five of them:

Each is iii worker add-able. Minimal app installs memory. Research assistant installs four. Same pattern for auth, routing, observability, anything with multiple concerns.
That's the rule. One scope per worker. No cross-scope reads. Split on complexity, not on speculation.
## What you actually build
Start with one worker. One function. Measure it.
Find the bottleneck. Usually specialization or token cost.
Extract one concern. Make it a second worker with its own function.
Wire them with iii.trigger(). The call site doesn't change when the callee moves to another machine, another language, another process.
Now memory::compress is swappable. Benchmarkable. You can downgrade its model independent of the store path. You can install a community version. The call site didn't change.
## The categories that collapse
A partial list of things you stop buying once workers are the unit:

Not because iii has equivalents. Because once work is triggered Functions on Workers, the conditions that made these separate categories are gone.
## Where it gets interesting
A worker can create workers. An agent hits a task outside its current capabilities, installs a sandbox worker from the registry, runs the task, tears it down. The agent extended itself at runtime. No human in the loop for the capability. No fixed tool set prepared in advance.
A browser tab is a worker. Cron on the backend calls a function on your open tab. Long-running workflows pause, invoke a human-in-the-loop function in an admin's browser, wait for the return. One trace across backend, agent, browser.
## Sandbox is a worker
Running untrusted code is the hard part of autonomy. Agent writes code. Agent wants to run it. You don't want it touching your filesystem, your network, your process tree, or your production DB.
Every agent framework today wires this separately. Docker container here. Firecracker there. A custom RPC shim on top. Two different RBAC models. Two different logging paths.
In iii, a sandbox is a worker. Same shape as everything else.

A sandbox worker registers three functions. sandbox::create opens a hardware-isolated microVM. sandbox::exec runs a command in it. sandbox::destroy tears it down. The worker implementation is Firecracker or Docker or Wasm or anything else. The contract is the same.
The agent doesn't know what's under sandbox::create. It could be sandbox-firecracker, sandbox-docker, sandbox-wasm, or a fake one in tests. Swap by iii worker add-ing a different sandbox worker. No agent code changes.
Three things fall out of this shape.
CLI and agent are peers. When you run iii worker add <name>, the CLI calls sandbox::create to install in isolation. When an agent runs generated Python, it calls the same sandbox::create. Same function. Same engine. Same auth path.
RBAC is just a function. An allow::check function (its own worker) sits in front of sandbox::create via a condition trigger. Same gate governs the CLI and the agent. You don't maintain two policy systems.
The spawned microVM is itself a worker. It connects to the engine as an ephemeral peer, runs its task, disconnects. While alive it can register its own functions and be invoked like any other worker. The recursion is the point: a worker that creates workers that register functions that other workers can trigger.
sandbox-docker or sandbox-firecracker can be written in Rust and can be used anytime, anywhere. Swap at will.
Isolation stopped being platform infrastructure. It's a function on the same engine as your queue.
## The quadratic problem

New capability is n+1, not n². Every worker joins by connecting. No consumer services to update. No gateway config. No registry entries. No restarts. The coordination cost of shipping a capability goes to zero.
For a multi-agent system this is the difference between a tree you hand-maintain and a graph that self-assembles.
## Bottom line
Stop building agents. Start building workers.
One worker at a time. Narrow scope. Clear identity. Defined tools. Let the composition emerge from Triggers and Functions.
An agent isn't a thing you build. It's what you call the composition when it's working.
Pick the smallest real task your current agent struggles with. Extract it into a worker. Give it one function. Measure it. Ship.
That's how you move.
Don't forget to check out iii.dev, It's open-source.
https://github.com/iii-hq/iii (⭐️)
Follow @ghumare64 for more lessons on AI Agentic Engineering.

## 相关链接
- [Rohit Ghumare](https://x.com/ghumare64)
- [@ghumare64](https://x.com/ghumare64)
- [10K](https://x.com/ghumare64/status/2047401813364683007/analytics)
- [Agents 201](https://x.com/ghumare64/status/2012136491133145364)
- [relearning this](https://x.com/doppenhe/status/2046997971812884640)
- [tailclaude](https://github.com/rohitg00/tailclaude)
- [iii](https://iii.dev/)
- [iii.dev](https://iii.dev/)
- [https://github.com/iii-hq/iii](https://github.com/iii-hq/iii)
- [@ghumare64](https://x.com/@ghumare64)
- [Upgrade to Premium](https://x.com/i/premium_sign_up)
- [3:46 AM · Apr 24, 2026](https://x.com/ghumare64/status/2047401813364683007)
- [10.5K Views](https://x.com/ghumare64/status/2047401813364683007/analytics)
---
*导出时间: 2026/4/24 22:51:44*
---
## 中文翻译
# Agents 201:单元缩小了
**作者**:Rohit Ghumare
**日期**:2026-04-23T19:46:45.000Z
**来源**:[https://x.com/ghumare64/status/2047401813364683007](https://x.com/ghumare64/status/2047401813364683007)
---

三个月前,我写过一篇爆火的文章:Agents 201,讲的是如何编排多个 agent,同时不烧光你的 token 预算,也不让协作变成一团乱麻。
那些观点依然成立。但我遗漏的是:单元本身即将发生变化。
## 自一月份以来发生了什么变化
那时,agent 是原子单元。监督者模式。蜂群模式。层级模式。每张图里的每个节点都是“一个 agent”。
r/claude,4 月 19 日,866 个赞:“试试 Haiku 4.5 agents。只要由 Opus 来编排,效果不输 Sonnet。”

- r/ClaudeCode,4 月 4 日:138 个会话。6180 万 token。每会话 11.55 美元。是 Max 套餐成本的 15 倍。

没有人发布更好的 agent。他们发布的是 agent 的部件。分层模型分配。依赖式任务交接。黑板。验证器门控。可观测性仪表盘。
agent 被拆解了。
## 为什么单体 agent 正在走向失败
单体 agent 是一个通才。它在一个上下文窗口里完成规划、检索、推理、撰写、验证和回答。全部跑在一个模型上。全部按 token 计费。
在生产环境中,有三样东西会出问题。
Token 经济性。一个 agent 用最贵的模型协调四个子 agent,会把一个 1.5 万 token 的任务变成 6 万。那个“每月 1593 美元的 Claude Code”的故事,就是“一个聪明 agent 包揽一切”的真实成本。
专业化损失。当一个模型同时扮演路由器、编码员、审查员、摘要员和验证员时,它哪个都做不好。我们一直在重新学习这个道理。这是 ML 教训在新层面的重演。
靠感觉调试。当监督者持有计划、四个 worker 写入共享状态、最后结果不对时,你没法调试。你只能重新运行并祈祷。这正是 tailclaude 试图用 Kubernetes 风格的仪表盘解决的问题。
## 单元是 worker

一个 worker 只做一件事。身份清晰。输入明确。输出明确。一项它能做好的工作。
一个检索器 worker 就做检索。一个模型。一个提示词。一个 schema。可基准测试。可替换。
一个验证器 worker 就做验证。在其他 worker 之后运行。出错时大声报错。有测试。
一个摘要器 worker 就做摘要。仅此而已。枯燥。枯燥就是它的特性。
一个 agent 是若干 worker 的组合。而不是相反。
这就是转变所在。一月份我写的是如何编排 agent。这个问题问错了。真正的问题是:如何把 worker 组合成一个从外部看起来像 agent 的东西。
## 三个原语
iii 提供三个原语:Worker、Function、Trigger。这就是全部词汇。

Worker 是任何能连接的进程。Rust 守护进程、TypeScript 服务、Python 脚本、浏览器标签页、微型虚拟机(microVM),或者 LLM 本身。基于 websockets 的长连接 WebSocket 客户端。
Function 是 Worker 注册的具名工作单元。memory::recall。retrieve::web。verify::code。通过 ID 加一个 JSON 载荷来调用。
Trigger 是触发 Function 运行的东西。HTTP。Cron。队列。状态变更。流事件。用户自定义。
就这么简单。不需要为 agent、队列、工作流或可观测性建立单独的心智模型。
React 发布时只有四个概念。Unix 发布时只有三个。SQL 发布时只有三个。每一个在数十年间不断复利增长的范式,都是建立在一套小到能装进一个脑袋的词汇之上的。
“小”就是这场押注。
最小的真实 worker
这就是一个完整的 worker。一个函数。一个触发器。引擎上的任何其他 worker 现在都可以调用 retrieve::web。任何 HTTP 客户端都可以 POST /retrieve。
## 编排模式是触发器,不是架构
三个月前,我把监督者、蜂群和层级画成三种截然不同的架构。其实不是。它们都可以化归为相同的原语。
用 worker 实现监督者

监督者 + 专门的子 agent(检索器、编码员、分析师、摘要器)+ 共享内存总线。在 iii 中,总线就是引擎。
通过状态触发器实现蜂群
没有监督者。Worker 订阅共享状态。每个 worker 对其他 worker 写入的变更做出反应。

蜂群不是一种架构。它是一个状态触发器。目的地变了,航班做出反应。航班确定了,酒店做出反应。没有中央协调者。没有框架。
层级就是递归的监督者

每个中间层本身就是一个触发叶子函数的函数。相同的原语。不同的形状。你并不是在挑选一种架构。你是在挑选哪些 Function 订阅哪些 Trigger。
窄 worker 分解
一个涉及多种关注点的领域,不是一个 worker。而是好几个。
内存就是最典型的例子。不是一个内存 worker。而是五个:

每一个都可以作为 iii worker 添加。极简应用只装一个内存 worker。研究助手装四个。auth、路由、可观测性,以及任何涉及多种关注点的领域,都遵循同样的模式。
规则就是:每个 worker 一个职责范围。不跨范围读取。按复杂度拆分,而不是凭猜测拆分。
## 你实际构建的东西
从一个 worker 开始。一个函数。对它进行测量。
找到瓶颈。通常是专业化程度或 token 成本。
抽离出一个关注点。把它变成第二个 worker,拥有自己的函数。
用 iii.trigger() 把它们连接起来。当被调用方迁移到另一台机器、另一种语言、另一个进程时,调用处不需要改变。
现在 memory::compress 是可替换的。可基准测试的。你可以独立于存储路径对它的模型降级。你可以安装社区版本。调用处没有变。
## 那些将会消亡的品类
一旦 worker 成为单元,你就不再需要购买的东西(部分清单):

并不是因为 iii 有对应物。而是因为一旦工作在 Workers 上的 Functions 中被触发,划分这些独立类别的前提条件就不复存在了。
## 有趣之处
一个 worker 可以创建 worker。一个 agent 遇到超出其当前能力的任务时,从注册表中安装一个沙箱 worker,运行任务,然后将其拆除。agent 在运行时扩展了自身。无需人工介入来添加能力,也无需提前准备固定的工具集。
一个浏览器标签页就是一个 worker。后端的 Cron 调用你打开的标签页上的一个函数。长时间运行的工作流可以暂停,在管理员的浏览器中调用一个需要人工介入的函数,然后等待返回。一条调用链贯穿后端、agent 和浏览器。
## 沙箱就是一个 worker
运行不受信任的代码是自主性的难点所在。Agent 编写代码。Agent 想要运行它。但你不希望它接触你的文件系统、你的网络、你的进程树,或你的生产数据库。
今天,每个 agent 框架都需要单独处理这个问题。这里一个 Docker 容器,那里一个 Firecracker,上面再套一个自定义的 RPC 垫片。两套不同的 RBAC 模型,两条不同的日志路径。
在 iii 中,沙箱就是一个 worker。与其他一切东西形态相同。

一个沙箱 worker 注册三个函数。sandbox::create 打开一个硬件隔离的 microVM。sandbox::exec 在其中运行一个命令。sandbox::destroy 将其拆除。worker 的实现可以是 Firecracker、Docker、Wasm 或任何其他东西。契约是相同的。
Agent 不知道 sandbox::create 底下是什么。它可能是 sandbox-firecracker、sandbox-docker、sandbox-wasm,或者测试中的假实现。通过 iii worker add 添加不同的沙箱 worker 即可替换。无需更改任何 agent 代码。
这种结构带来了三点好处。
CLI 和 agent 是对等的。当你运行 iii worker add <name> 时,CLI 调用 sandbox::create 在隔离环境中进行安装。当 agent 运行生成的 Python 代码时,它调用的是同一个 sandbox::create。相同的函数。相同的引擎。相同的认证路径。
RBAC 只是一个函数。一个 allow::check 函数(它自己就是一个 worker)通过条件触发器位于 sandbox::create 之前。同一个门禁同时管控 CLI 和 agent。你不需要维护两套策略系统。
派生出来的 microVM 本身也是一个 worker。它作为一个临时节点连接到引擎,运行其任务,然后断开连接。在存续期间,它可以注册自己的函数,并像其他任何 worker 一样被调用。这种递归正是关键所在:一个 worker 创建 worker,注册函数,而这些函数又可被其他 worker 触发。
sandbox-docker 或 sandbox-firecracker 可以用 Rust 编写,并且可以在任何时候、任何地方使用。随意替换。
隔离不再是平台基础设施。它是与你队列位于同一引擎上的一个函数。
## 平方问题

新增能力是 n+1,而不是 n²。每个 worker 只需连接即可加入。无需更新消费者服务,无需网关配置,无需注册表条目,无需重启。交付一项能力的协调成本降为零。
对于多 agent 系统来说,这就是手工维护的树与自组装的图之间的区别。
## 底线
别再构建 agent 了。开始构建 worker 吧。
一次一个 worker。范围狭窄。身份清晰。工具明确。让组合从 Triggers 和 Functions 中自然涌现。
Agent 不是你构建出来的东西。它是当组合正常运作时,你对这个组合的称呼。
选一个你当前 agent 搞不定的最小的真实任务。把它提取成一个 worker。给它一个函数。度量它。交付它。
这就是你前进的方式。
别忘了看看 iii.dev,它是开源的。
https://github.com/iii-hq/iii (⭐️)
关注 @ghumare64,获取更多关于 AI 智能体工程的经验分享。

## 相关链接
- [Rohit Ghumare](https://x.com/ghumare64)
- [@ghumare64](https://x.com/ghumare64)
- [10K](https://x.com/ghumare64/status/2047401813364683007/analytics)
- [Agents 201](https://x.com/ghumare64/status/2012136491133145364)
- [relearning this](https://x.com/doppenhe/status/2046997971812884640)
- [tailclaude](https://github.com/rohitg00/tailclaude)
- [iii](https://iii.dev/)
- [iii.dev](https://iii.dev/)
- [https://github.com/iii-hq/iii](https://github.com/iii-hq/iii)
- [@ghumare64](https://x.com/@ghumare64)
- [升级到 Premium](https://x.com/i/premium_sign_up)
- [3:46 AM · Apr 24, 2026](https://x.com/ghumare64/status/2047401813364683007)
- [10.5K 次浏览](https://x.com/ghumare64/status/2047401813364683007/analytics)
---
*导出时间: 2026/4/24 22:51:44*