提出树形结构协调多个AI Agent的新框架设计,解决多Agent系统的扩展性和可靠性问题。
AI Agent 很擅长一次做好一件事。给 Claude 一个目标明确的任务,它就能出色完成。但真实工作并不是单一任务,而是一棵任务树,其中包含依赖关系、并行执行,以及需要在任务之间流转的上下文。
多 Agent 框架正变得越来越多,但它们解决的都是错误的问题。
LangGraph 将协调建模为状态机。你需要使用 Python 定义节点和边,由开发者预先决定 Agent 如何交接工作。它对固定工作流非常强大,但图结构是静态的。如果某个 Agent 在任务进行到一半时意识到,应该用另一种方式拆分工作,那也无能为力。开发者必须提前预判所有可能的任务分解模式。
CrewAI 以角色为基础。你通过 persona 定义 Agent——比如“研究员”“分析师”“撰稿人”——然后为它们分配任务。这种方式很直观,但角色是由开发者决定的,而不是由 Agent 自行发现的。一个由三名成员组成的 crew 无法自行判断它实际上需要五个人,也不能决定把“研究员”拆成两条并行工作线。
AutoGen 把 Agent 放进一个群聊,让它们通过相互对话进行协调。这种方式很灵活,但缺乏结构:没有依赖追踪,没有权限范围控制,也没有类型化结果。协调从对话中自然涌现,这意味着它不可预测,也很难检查。
OpenAI Swarm 是其中最精简的方案——让 Agent 之间进行轻量级交接。Agent A 判断该轮到 Agent B 时,就把控制权转交过去。它很简单,但只能线性运行:没有并行能力,没有树状结构,也无法让一个 Agent 创建三个子任务并等待它们全部完成。
Claude 的 tool-use 循环——Anthropic 自己采用的模式——让单个 Agent 在循环中调用工具。它能够很好地处理顺序执行的复杂任务,但面对大型任务时会撞上 context window 限制,而且无法并行化。一个 Agent、一条线程、一份上下文。
这些框架的共同点是:开发者都必须预先定义协调结构。你需要决定工作流图、Agent 角色和交接模式,而 Agent 只能在你划定的边界内执行任务。
当 Agent 还不可靠时,这种设计合情合理。你绝不会让 GPT-3 自己决定如何拆解一个项目。但如今的模型已经很擅长规划了。它们会自然地把问题拆成多个子问题,能够理解依赖关系,也知道什么时候一轮处理不足以完成任务。
既然如此,我们为什么还在硬编码任务分解方式?
我开发了 Cord。你只需要给它一个目标:
cord run "Should we migrate our API from REST to GraphQL? Evaluate and recommend."
一个 Agent 随即启动。它读取目标,判断自己需要先进行研究才能给出答案,然后创建子任务:
● #1 [active] GOAL Should we migrate our API from REST to GraphQL?
● #2 [active] SPAWN Audit current REST API surface
● #3 [active] SPAWN Research GraphQL trade-offs for our stack
○ #4 [pending] ASK How many concurrent users do you serve?
blocked-by: #2
○ #5 [pending] FORK Comparative analysis
blocked-by: #3, #4
○ #6 [pending] SPAWN Write migration recommendation
blocked-by: #5
这里没有任何硬编码的工作流。这个结构是 Agent 在运行时自行决定的。
它并行执行 API 审计(#2)和 GraphQL 研究(#3)。它还创建了一个 ask 节点(#4)——向人类提出问题——因为它意识到,最终建议取决于系统规模,而这一信息无法由它自行研究得出。它让 #4 依赖于 #2,因为结合审计结果作为上下文后,这个问题会更有意义。它把 #5 设为 fork,使分析任务能够继承目前为止获得的全部信息。最后,它把最终建议安排在分析完成之后执行。
接下来,你可以看着它运行:
✓ #2 [complete] SPAWN Audit current REST API surface
result: 47 endpoints. 12 heavily nested resources...
✓ #3 [complete] SPAWN Research GraphQL trade-offs
result: Key advantages: reduced over-fetching...
? How many concurrent users do you serve?
Options: <1K, 1K-10K, 10K-100K, >100K
> 10K-100K
● #5 [active] FORK Comparative analysis
blocked-by: #3, #4
两项研究会并行执行。当它们都完成,并且你回答问题之后,分析任务就会启动,其上下文中包含这三项结果。它最终给出的建议会针对你的实际系统规模和 API 情况,而不是一篇泛泛而谈 GraphQL 的博客文章。
这里有一个我认为真正具有新意的想法:将 spawn 和 fork 区分开来,把这种区别作为一种上下文流转原语。
通过 spawn 创建的 Agent 会从一张白纸开始。它只会得到自己的 prompt,以及它明确依赖的节点所产生的结果。这就像雇用一名承包商——这是需求说明,开始工作吧。这样的 Agent 重启成本低,也很容易理解其行为。
通过 fork 创建的 Agent,则会把所有已经完成的同级节点结果注入自己的上下文。这就像向团队成员进行情况说明——他们知道团队目前为止了解到的一切。它的成本更高,但对于需要建立在前期成果之上的分析任务而言,这种方式必不可少。
这与并发无关。spawn 和 fork 创建的任务都可以并行执行,也可以顺序执行。真正的区别在于子 Agent 知道什么。在上面的例子中,Agent 为相互独立的研究任务选择了 spawn,为需要掌握全部信息的分析任务选择了 fork。它正确地做出了选择——因为工具描述清楚解释了二者的区别。这正是关键所在:仅凭接口本身,Agent 就能学会使用这套协议。
顺理成章的下一步,是把上下文流转变成一等原语——在 spawn/fork 上增加一个 context_query 参数,接收自然语言指令,例如 "summary"、"relevant details from a web designer's perspective" 或 "bullet points about error handling"。一个负责压缩上下文的 subagent 会读取父 Agent 的完整上下文,按照 query 的要求进行提炼,然后只把结果传给子 Agent。这项能力必须内置在客户端本身——一个隔离的 MCP tool 无法访问父 Agent 的上下文,除非把完整上下文序列化后作为工具输入,而这恰恰违背了设计目的。
每个 Agent 都是一个 Claude Code CLI 进程,通过由共享 SQLite 数据库支撑的 MCP tools 工作:
spawn(goal, prompt, blocked_by)——创建一个子任务fork(goal, prompt, blocked_by)——创建一个继承上下文的子任务ask(question, options)——向人类提问complete(result)——将自身标记为已完成read_tree()——查看完整的协调树Agent 知道自己是协调树中的一个节点——system prompt 会告诉它——但它们并不负责管理这棵树。它们看到工具,并在需要时使用。依赖解析、权限范围控制和结果注入等协议规则,都由 MCP server 强制执行。
当一个 ask 节点准备就绪时,引擎会暂停运行,并在终端中提示人类回答。答案会被保存为结果,随后下游节点解除阻塞。人类是任务树中的参与者,而不是旁观者。
约 500 行 Python 代码。SQLite + MCP。
在编写 runtime 之前,我需要确认,仅凭接口本身是否足以让 Agent 学会这套协议。因此,我构建了一个一次性的 MCP server,其中包含这五个工具,然后让 Claude Code 连接到它,并运行了 15 项测试。没有 runtime,也没有引擎——只有 Claude、工具和一项任务。
真正有意思的并不是那些正确的工具调用,而是自然涌现出来的行为。一个被要求拆解项目的 Agent 在行动前调用了 read_tree(),行动后又调用了一次进行验证——读取、行动、验证,全程没有任何额外提示。另一个 Agent 尝试停止同级节点时遭到拒绝,于是通过 ask 向父节点升级处理——这正是正确的模式,但我从未描述过这种做法。还有一个 Agent 遇到错误后,停止了失败的子节点,并使用调整后的 prompt 重新 spawn 了一个新节点。
15 项测试全部通过。通过率本身并不是关键发现——真正重要的是,清晰的工具描述加上依赖语义,已经足以让 Agent 正确使用这套协议。这让我确认,值得继续构建 runtime。
这个实现使用了 Claude Code CLI 和 SQLite。但这套协议——五种原语、依赖解析、权限范围控制和两阶段生命周期——并不依赖于这些具体技术。
你可以基于 Postgres 实现 Cord,用于多机协调;也可以直接基于 Claude API 实现,省去 CLI 带来的额外开销;还可以同时接入多个 LLM provider——让 GPT 处理低成本任务,让 Claude 处理复杂任务;甚至可以让人类工作者负责其中一部分节点。
这套协议才是真正的贡献。这个 repo 只是一个概念验证。
git clone https://github.com/kimjune01/cord.git
cd cord
uv sync
cord run "your goal here" --budget 2.0
你也可以让它读取一份规划文档:
cord run plan.md --budget 5.0
根 Agent 会读取这份 Markdown,并将其分解成一棵协调树。你可以用任何方式编写计划——项目符号、章节或连续的正文都可以——Agent 会自行推断任务结构、依赖关系和并行方式。
需要安装 Claude Code CLI,并拥有包含其使用权限的订阅。
GitHub|RFC|HN 讨论