一个 agent 干活的时候,你只需要一个 agent。等它开始同时接你的设计讨论、改代码、写文档,你会发现它开始精神分裂:上下文越来越长,说话风格开始漂移,该严格的地方它反而在讨好你。
我最后的解法不是换更大的模型,是拆成四个人:一个主管(贾维斯),加三个下属——无敌码农写代码,无敌测试专门挑毛病,超级编辑管文档。四个 agent 跑在同一个 Gateway 进程里,接的是同一个飞书,但各自有独立的工作区、会话历史和模型配置。我在飞书里只跟主管说话。
先看配置:四个人是怎么排的
配置比描述诚实。下面是我 openclaw.json 的节选,密钥和账号 ID 都脱敏了:
{
"agents": {
"list": [
{ "id": "main",
"identity": { "name": "贾维斯" },
"heartbeat": { "every": "6h" } },
{ "id": "coder",
"identity": { "name": "无敌码农" },
"model": {
"primary": "glm5",
"fallbacks": ["m2.5", "qwen3.5", "k2.5"] } },
{ "id": "tester",
"identity": { "name": "无敌测试" },
"model": {
"primary": "glm5",
"fallbacks": ["m2.5", "qwen3.5", "k2.5"] } },
{ "id": "editor",
"identity": { "name": "超级编辑" },
"model": {
"primary": "k2.5",
"fallbacks": ["qwen3.5", "m2.5", "glm5"] } }
]
},
"bindings": [
{ "agentId": "main",
"match": { "channel": "feishu",
"accountId": "default" } },
{ "agentId": "coder",
"match": { "channel": "feishu",
"accountId": "coder" } },
{ "agentId": "tester",
"match": { "channel": "feishu",
"accountId": "tester" } },
{ "agentId": "editor",
"match": { "channel": "feishu",
"accountId": "editor" } }
]
}
三件事一眼能看出来:模型不是平均分的,路由是按账号走的,主管有定时心跳。
落盘之后长什么样
四个 agent 不是四个虚拟目录,是四份真实存在的工作区:
workspace/ # main 贾维斯:人格 + 记忆 + 团队协调
|-- AGENTS.md
|-- IDENTITY.md
|-- MEMORY.md
|-- ERRORS.md
|-- HEARTBEAT.md # 巡检清单
|-- memory/YYYY-MM-DD.md
|-- skills/
|-- workspace-coder/ # 无敌码农
|-- workspace-tester/ # 无敌测试
+-- workspace-editor/ # 超级编辑
每个子工作区里都有自己的一份 IDENTITY.md 和 memory/。这意味着"谁记住了什么"是可查的:同样是"这个项目用 pnpm 不用 npm"这条结论,只应该出现在 coder 的记忆里,不该出现在 editor 那边。
路由不看内容,只看消息从哪来
官方概念里,agent 是一整套"人格范围":工作区、状态目录(认证、模型注册表、会话历史)、以及它能用的渠道账号。binding 则是"某个渠道账号 → 某个 agent"的映射。
关键点是它不做内容判断。没有关键词匹配,没有"这条像代码所以给码农"。消息从 feishu/coder 这个账号进来,就归 coder,仅此而已。
所以我把设计改成最保守的一种:四个飞书账号,四个入口,一一对应。私聊用 pairing 配对,群聊走 allowlist 加 mention 门槛。陌生人不配对就进不来,群里不 @ 就不触发。
这套东西最容易骗人的地方在于:渠道显示在线,不等于路由正确。账号连上了、消息也进来了,但 binding 指错 agent,你会看到"文档 agent 在回答代码问题",然后怀疑模型。排查其实只有一条命令:
openclaw config get bindings
对着账号 ID 和 agentId 一条条核。我吃过一次这个亏:新加了一个账号,忘了补 binding,消息进了默认 agent,一切看起来都正常。
一个任务在团队里怎么走完
拿"修一个 bug"举例,现在的流程是固定的:
- 主管拆。 判断这是改代码、还是补测试、还是改文档;能并行的拆开,强耦合的自己留着。派活的时候必须写清三样:目标、约束、验收标准。
- 码农实现。 他在自己的
workspace-coder里改,回来只交三样东西:改了哪些文件、为什么这么改、怎么复现。 - 测试独立验。 关键在"独立"两个字:tester 在自己的
workspace-tester里拿复现步骤重跑一遍,不接受"码农说跑通了"。它交的是失败证据或通过证据,不是评价。 - 编辑收尾。 只拿前两步的结论写变更说明,不参与技术判断。
- 主管验收。 检查证据齐不齐,决定发不发布。
这条链里最贵的一条纪律是第 5 步:主管不亲自写业务代码。一开始它图快自己上手,结果既当裁判又当运动员,"测试"那个位置直接废了——它审的是主管写的代码,天然不敢下狠手。
模型为什么不是一个
coder 和 tester 主模型都是 glm5,editor 是 k2.5,三个人的 fallback 链顺序还不一样。理由很朴素:写代码和写测试要的是工具调用稳、长上下文不丢细节;写文档要的是中文语感。同一套主模型在两种任务上总有一头是浪费的。
fallback 链的作用是别让一次限流把整个任务卡死。主模型返回失败,自动往下换一个,任务继续跑。代价是不同模型的输出风格会在同一条任务里打架,所以我在 AGENTS.md 里要求:交付前必须统一一次语气,不允许同一个文档里两种腔调。
技能按角色裁剪,而且它是"替换"
四个人的技能列表长度差得很远:主管 18 个,三个下属各 8 个。主管那边多出来的是设计和协调类(brainstorming、writing-plans、project-manager),下属那边是各自领域的工具。
这里有个文档里写了、但很容易看漏的语义:agents.defaults.skills 是共享基线,agents.entries.*.skills 是逐 agent 的替换,不是合并。你给某个 agent 写 8 条,以为是"在基线上再加 8 条",实际是"只剩这 8 条"。表现不是报错,而是它某天突然不会用某个工具了。
三个真实的坑
不能共用 agentDir。 每个 agent 的状态目录里放着认证、模型注册表和会话历史。共用不会启动报错,症状是登录态串号、或者在别人的历史里接着说话——这种 bug 极难定位,因为每个组件看起来都正常。
workspace 不是沙箱。 官方说得很直白:工作区只是默认工作目录,相对路径落在里面,绝对路径照样能走出去。想让测试 agent"只能看不能改",得靠 sandbox 和工具策略,靠提示词求它别动手是不算数的。
群聊里会抢话。 四个 agent 在一个群里,必须做 mention 门槛和沉默规则:没被点名就保持安静,同一条消息禁止连发三次。这条写进了 SOUL.md 和 AGENTS.md,不是靠它自觉。
成本是真的会翻倍
四个 agent 就是四份会话历史、四份上下文、四次推理。同一件事拆得越细,往返次数越多,token 账单越难看。给主管配 6 小时心跳,一天四次自检,也是钱。
所以并行只在真的能并行时才用:调研、批量修改、独立验证可以;需要频繁往返的调试留在一个人手里。官方那套 sub-agent 的成本控制思路其实一样——按任务价值分配模型,别用一个最强模型去干所有的杂活。
什么时候不该拆
判据不是规模,是边界。如果我说不出某个 agent 明确"拒绝做什么",那它就没有存在的必要——它只是把同一个 agent 复制了一遍,还多付了一份上下文。
任务单一、上下文够用的时候,一个 agent 加一份写好的 AGENTS.md,比团队省心得多。我这套能立住,是因为"实现"和"验收"必须由两个人干,这一点在 agent 身上和在人类团队里一样。
最后
多智能体的价值不在"多",在于你能给每份职责划出一条能被检查的线:谁拆、谁做、谁验、谁交付。
四个人干活的效率不一定比一个人高。但当任务同时需要"写"和"挑错"时,它必须是两个人。