多 Agent 编程,星状还是网状?
周日晚上,Sunny 在群里问了一句「你现在的多 agent 工作是怎么调度的」。第一轮回答是从工作方式讲的——同时跑几个项目、每类任务配一种 agent。Tim 把问题校准了一下:Sunny 问的其实是技术架构。Sunny 随后把它说清楚了:
「对,就是 Harness 在长程 coding 项目中,如何高效的调动 agent 之间协作的问题。比如跨 PC 组建的 tester、coder、reviewer。」
「我现在是三个电脑(三个账号),四个 session,还没连起来。」目前的做法是「写在提示词里的相互汇报机制:CEO 用 Fable,agent1 Opus、agent2 Codex、agent3 Kimi」。 —— Sunny
接着出现了这场讨论里最有价值的一个分歧:
「子 agent 之间一般不鼓励互相通信吧,context 都是隔离的。只和主编排 agent 汇报。」 —— Arthur G
「需要的,这是最基础的,不然后面 team agent 没法实现。」 —— Tim
一个说不该通信,一个说必须通信。两个人都对——他们说的是两种不同的架构。这篇文章就把这两种架构拆开讲:它们各自怎么工作、为什么会这样设计、代价是什么,以及什么时候该用哪一种。
先搞懂几个词
- Agent
- 一个能自己循环「思考 → 调工具 → 看结果 → 再思考」的模型实例。编码场景里就是 Claude Code、Codex、OpenCode 这类 CLI 开出来的一个会话。
- Harness
- 包在模型外面的那一整套东西:工具、权限、记忆、会话管理、子 agent 机制。同一个模型,harness 不同,能力天差地别。上一篇《模型只是一半——读懂 DeepSeek Harness》讲过。
- Context
- 模型「眼前」能看到的全部内容——对话历史、读过的文件、工具返回的结果。它有上限,而且越接近上限,模型越容易漏东西、忘东西。这是整场讨论的物理约束。
- 编排者 / Orchestrator
- 负责拆任务、派任务、收结果的那个 agent。星状架构里它是中心;网状架构里这个角色可以被一块任务板或一条消息队列取代。
- Session
- 一个 agent 的一次连续会话。Sunny 说的「四个 session 没连起来」,字面意思就是四个独立的 context,彼此看不见。
一、为什么一个 agent 不够用
先回答一个更基础的问题:既然模型这么强,为什么不让一个 agent 从头干到尾?
因为 context 是有限的,而且会变脏。一个长程编码任务——读几十个文件、跑测试、看报错、改、再跑——几个小时下来,context 里塞满了已经过时的中间产物:三版之前的代码、早就修好的报错、跑偏了又拉回来的推理。模型要在这堆东西里找到当前真正相关的部分,准确率是会下降的。人也一样:连轴转八小时之后判断力会变差,只是模型「变差」的方式更隐蔽——它不会说累,只会更自信地漏掉一个条件。
第二个原因是角色冲突。让写代码的那个 agent 顺手 review 自己的代码,效果通常不好——它带着写的时候的全部假设去看,看不出自己的盲点。coder 和 reviewer 分开,本质上是为了让 reviewer 拿到一份干净的、没有先入之见的 context。Sunny 说的 tester / coder / reviewer 三分,就是这个逻辑。
所以多 agent 不是为了「更多算力」,而是为了把 context 切开:每个 agent 只看它该看的那一小片,看得清楚。接下来的问题只剩一个——切开之后,怎么再合起来?这就是星状和网状的分岔口。
二、星状:一个大脑,多双手
这是今天绝大多数 harness 内置的默认方式,Claude Code 的 subagent、DeepSeek Harness 的 Session → Main Agent → Agents 都是这一类。Arthur G 说的「只和主编排 agent 汇报」描述的就是它。
┌──────────────┐
│ Orchestrator │ ← 主编排 agent,唯一持有全局视角
└──────┬───────┘
│ ↓ 派任务 ↑ 只回传结果摘要
┌──────────┼──────────┐
▼ ▼ ▼
Sub-agent Sub-agent Sub-agent
读代码 写测试 查文档
各自独立 context · 互相看不见
它怎么工作
主 agent 拿到任务,拆成几个相对独立的子任务,每个子任务写成一段明确的指令。
为每个子任务开一个全新的子 agent。关键在「全新」:子 agent 的 context 是空白的,只有主 agent 给它的那段指令,看不到主 agent 的对话历史,也看不到兄弟 agent 在干什么。
子 agent 干完,把结果压缩成一段摘要交回。它读过的二十个文件、试错的五轮推理,都留在它自己的 context 里,随会话结束一起丢掉。主 agent 只收到「结论」。
主 agent 拿着几份摘要继续往下走——决定下一步、再派、或者收工。
为什么这样设计是对的
它解决的正是第一节的问题:主 agent 的 context 始终干净。脏活累活在子 agent 里做,垃圾随子 agent 一起销毁,主线只留结论。一个子 agent 跑偏了,重派一个就是,不会把整条主线带进沟里。这就是 Arthur G 说「不鼓励互相通信」的道理——一旦子 agent 之间开始串门,隔离就破了,谁污染了谁就说不清了。
它也好调试。所有决策都在一个地方发生,出了问题回看主 agent 的记录就能定位。子 agent 还可以用更便宜、更快的模型,因为它们只需要执行明确的指令,不需要全局判断。
它的代价
所有信息经过主 agent 一次,而它的 context 同样有限。项目一长,主 agent 自己也会撑爆——这是「长程」两个字真正的难点。摘要压缩还会丢信息:子 agent 发现的一个细微异常,如果没写进摘要,主 agent 永远不知道。
coder 写完,reviewer 要看,信息得先回到主 agent、再由主 agent 转述给 reviewer。多一次压缩,多一次失真。子 agent 之间没有直接的边,「交接」这个动作在结构上是不存在的。
子 agent 是主 agent 在同一进程、同一账号下开出来的。Sunny 的三台电脑、三个账号、三家模型,星状架构在结构上就连不起来——不是 prompt 写得不够好,是这个形状里没有那条线。
子 agent 可以同时跑,但主 agent 要等它们全部回来才能走下一步。最慢的那个决定整体节奏。
三、网状:一群同事,一块白板
Tim 说「team agent 没法实现」的时候,他心里的形状是另一种。这里的关键转变是:不再有唯一的大脑。agent 变成对等的「成员」,它们之间需要一个共享的媒介来协作。
但请注意一个容易误解的地方——「网状」不是让 agent 直接互相聊天。真正能用的网状架构,agent 之间从不直接对话,它们都对着同一个外部系统说话:一条消息队列、一个共享频道、一块任务板、一个共享文件。Sunny 当晚发的那张架构图把这一点画得很清楚:
Raft Server
│
┌────────────┼────────────┐
│ │ │
Human Agent A Agent B
│ │ │
└────── shared channel ───┘
│
Task Board
│
┌────────────┼────────────┐
▼ ▼ ▼
Computer 1 Computer 2 Computer 3
│ │ │
Codex Claude OpenCode
它怎么工作
不管是 Raft、Multica 还是 CCB,第一步都是在你自己的电脑上装一个 daemon。它常驻,负责在这台机器上启动 agent、转发消息。agent 不再随某个终端窗口关掉而消失。
要做的事被写成一个 issue、一条任务卡、或者频道里的一条 @ 消息,带有状态(待领 / 进行中 / 阻塞 / 待审)。这是和「把相互汇报写进提示词」的本质区别:任务是系统里的对象,不是模型记忆里的一句话。
coder 领走一张卡,写完把 PR 链接和状态更新写回板上;reviewer 看到「待审」状态,领走,看完写结论。两者没有直接对话,全靠板上的状态流转衔接。
人可以随时插进来:改优先级、否掉一个方向、回答一个 blocker。人不再是站在系统外面看日志的人,而是网上的一个节点。
当晚群里提到的三个工具,恰好是这个思路的三个抽象层级:
满天星推荐。一个终端 TUI,把 Claude、Codex、Gemini、Kimi 等十几家 CLI 并排放在同一屏,agent 通过 /ask 互相委派,靠一个共享的 memory 文件做团队记忆。解决的是单机上不同厂家 agent 互通。
Sunny 分享。形态像 Slack:channel、DM、thread、task board,人和 agent 都是成员。agent 通过 daemon 跑在你自己的机器上,有持久记忆。解决的是跨机器、跨模型、人机混编的组织问题。
Sunny 随后找到。口号是「agents that show up on the board」——agent 像同事一样领 issue、报进度、提 blocker、交 PR 等人 review。支持二十多家 agent CLI,代码不出本机。抽象层最高,最接近「管理一个团队」而不是「操作一个工具」。
它的好处
星状的四个代价,网状几乎逐条对上:中心不再是瓶颈,因为没有中心;coder 到 reviewer 的交接是直接的状态流转,不经二次压缩;跨机器、跨账号、跨模型天然支持,因为大家连的是同一个 server;真并行——各干各的,板上状态说了算。再加一条星状没有的:持久。daemon 常驻,agent 有自己的记忆,一个项目可以跨天、跨周地推进,而不是每次开终端从零开始。
它的代价
server、daemon、账号、权限、网络。星状是 harness 自带的,网状是你要搭、要维护的。这个成本对一个人的项目来说往往不划算。
两个 agent 同时改同一个文件怎么办?任务板要有锁、有分支策略、有合并规则。这些都是分布式系统里的老问题,一个不落地全会撞上。
星状里子 agent 的幻觉最多污染主 agent 的一次判断;网状里 A 的错误结论写进板上,B 读到当真,C 在 B 的基础上继续——一环套一环,错误被放大而不是被隔离。这正是 Arthur G 担心的事,在网状里它是真实风险。
「谁在什么时候看到了什么,导致它做了什么」——星状里回看一份记录就够,网状里要在多个 agent、多台机器的日志之间拼时间线。
多个 agent 常驻、频繁读板、互相等待,消耗远高于按需开子 agent。
四、「跟 LLM 无关,跟工程架构有关」
Sunny 现在的做法——把「相互汇报」写在提示词里——Tim 的反应很直接:
「爱玛,跟我之前想法完全一样,这么想是个大坑。其实跟 LLM 无关,跟你的工程架构有关。」 —— Tim
这句话值得展开,因为它是这场讨论里最容易被略过、又最重要的一句。
写在 prompt 里的协作规则,是软约束。模型可能照做,也可能在 context 变长之后忘了;可能汇报了,但对方 agent 那一刻根本没在听;汇报的内容可能丢、可能重复、可能顺序错乱。没有投递保证、没有重试、没有状态、没有超时——这些都不是模型能力的问题,是系统里根本没有承担这些职责的部件。你在用一个概率性的东西去模拟一个本该确定性的东西。
Arthur G 随后说的那几句,把这件事彻底祛魅了:
「感觉其实就是用程序手段实现 agent 之间 join、wait、message queue。都是典型微服务和多线程多进程那些东西,本质一样的。区别就是调的 tool。」 —— Arthur G
翻译一下:agent 协作没有新物理学。分布式系统这几十年积累下来的概念,一个不少地适用:
agent 不直接对话,把消息投进队列,对方有空再取。发的时候对方不在线也没关系——这就解决了「汇报了但没人听」。
明确「下一步要等哪几个前置任务全部完成」。reviewer 不是被 prompt 告知「等 coder 好了再看」,而是系统在 coder 的任务状态翻成「完成」之前,根本不会把卡派给 reviewer。
一张任务卡只能在有限的几个状态之间按规则流转:待领 → 进行中 → 待审 → 完成 / 打回。状态在系统里,不在任何一个 agent 的记忆里,所以谁都不会「忘」。
agent 挂了、超时了、答非所问了,系统重派一次,而且重派不会造成重复副作用。这是「可靠」的来源——不是模型更听话,是失败被设计进去了。
所以 Tim 那句话的完整意思是:协作的可靠性应该由系统层保证,而不是由模型的自觉保证。模型负责的是每个节点上的智能,节点之间怎么连,是工程问题。把两者混在一起——指望 prompt 里的一句「记得互相汇报」撑起一个团队——就是那个「大坑」。
五、其实不是二选一
Tim 当晚还补了一层区分:
「你这感觉要分几种情况,一种是同一个 harness 多 agent 之间通信和协同的问题,另一个就更复杂,可能会涉及 Team 版 harness 下的协同问题。」 —— Tim
这正是两位看似对立的观点能同时成立的原因。回到 Sunny 那张图:左边 DeepSeek Harness 是 Session → Main Agent → Agents,解决的是「一个人怎么把活干完」;右边 Raft 是 Server → 共享频道 → 任务板 → 多台机器,解决的是「组织」问题。它们不在同一层,也就不互斥。
真实的系统几乎总是分层套用的:
- 网状架构的每一个节点——Computer 2 上那个 Claude——它自己内部处理任务时,依然是星状:主线派 subagent、收摘要、保持 context 干净。
- 网状不取代星状,它把星状包起来。
- 当任务超出一台机器、一个账号、一家模型能覆盖的范围,星状的中心就需要被一个组织层取代。
- 此时那个「主编排 agent」的职责——拆、派、收、合——被分摊给任务板和人。
所以问题不是「选哪个」,而是「你的任务在哪一层」。几个判断标准:
装得下就一个 agent;装不下但一台机器够,星状;一台机器都不够,才需要网状。
Sunny 的 Fable + Opus + Codex + Kimi 组合,单一 harness 的 subagent 机制做不到,这是硬需求。
如果需要人在中途改方向、答问题、做验收,而不是只在最后看结果——网状的「人是节点」比星状的「人在系统外」自然得多。
一次会话干完的任务用星状;跨天、跨周的项目需要持久的 agent 和外置的状态,那是网状的地盘。
这是最诚实的一条。网状的每一个优点都以运维成本换来。一个人的 side project,星状用好了通常够。
六、回到那个问题
星状还是网状?换个问法就清楚了:你是在管一个人,还是在管一个团队?
管一个人,你要的是它头脑清醒——context 干净、决策集中、出错好查,星状就是为此设计的。管一个团队,你要的是它们之间有制度——任务有归属、状态有记录、交接不靠口头、失败有兜底,这些制度不能写在每个人的脑子里,得写在系统里,这就是网状,以及 Tim 反复强调的「工程架构」。
群里当晚的自我定位也挺准确:有人「刚到浅水区–深水区的交界线」,有人正在「折腾自己的 harness」、刚碰到长程项目的坑,有人三台电脑还没连起来。这个话题没有结论,因为它本来就不是一个有唯一答案的问题——但至少,下一次再问「多 agent 怎么调度」的时候,可以先问一句:你在哪一层?