在今年的 PL 第一公里大会上,林博讲解了一个自己基于多智能体的团队管理经验。一开始我不以为意,过了几个月之后,自己细细品味,才恍然大悟其中精髓。
当时我的第一反应很朴素:模型已经足够强了,把需要的工具都接上,一个 Agent 不就能把事情做完吗?为什么还要分主控、专家、协作流程,弄得像一个真正的团队?
后来我真的把 OpenClaw 用进投资研究、无线技术、服务器运维、写作、旅行和日常事务里,问题慢慢暴露出来。一个“全能助手”当然什么都能碰,但它也因此什么都混在一起:专业判断、工具权限、长期记忆、对外回复,全部挤在同一个上下文里。能力越多,噪声越多;工具越全,权限边界越模糊。
这时我才明白,林博那次分享的重点根本不是“多开几个 Agent”,而是像管理团队一样管理智能体:谁是统一入口,谁负责专业判断,谁有权使用什么工具,工作怎么交接,出了问题由谁兜底。
于是我把原来的 OpenClaw 改造成了一套 1 + 10 的多智能体系统。
单体助手用久了,问题开始出现
我最初的思路,是不断给主 Agent 增加能力:股票数据、天气、地图、服务器诊断、写作、图片生成、知识整理……看上去越来越强,实际使用却越来越像让一个人同时做前台、研究员、运维工程师、设计师和秘书。
这种模式有三个明显问题。
第一,职责会漂。它上一秒还在分析股票,下一秒就去改文案,同一个上下文里的语气、判断标准和记忆很容易互相污染。
第二,权限会膨胀。投资研究需要行情数据,旅行需要航班和地图,运维需要主机状态。但如果这些工具都挂在一个 Agent 身上,那么每次普通聊天都背着一整套不必要的能力。
第三,出了问题很难说清责任。是模型判断错了,工具数据错了,路由错了,还是权限配置错了?单体 Agent 往往只能给出一句笼统的“调用失败”。
所以这次我先画组织架构图,再决定每个 Agent 应该保留什么能力。
一位 Chief,十位专家
整套系统只有一个正式入口:main。我在微信里发出的所有任务,先到 main;最终能直接回复我的,也只有 main。
它下面有十个专家:
| Agent | 职责 |
|---|---|
investment | A 股研究、市场复盘、风险分析 |
work | 无线通信、系统仿真、版本研发,只处理公开或已脱敏材料 |
ops | OpenClaw、VPS、代码和 DevOps 只读诊断 |
image | 封面、结构图、视觉资产 |
writer | 博客、汇报、演讲和中文表达 |
consultant | 战略、职业、管理和复杂决策 |
knowledge | Markdown、知识分类和长期沉淀 |
life | 天气、待办、提醒和本地生活 |
travel | 航班、地图、路线和旅行计划 |
shopping | 商品研究、比价和购买建议 |
main 的工作不是假装精通所有领域。它负责识别意图、判断敏感级别、选择专家、删掉不该外传的信息、检查专家证据,再把结果整理成一条最终答复。
专家也不是“小号 main”。它们没有微信入口,不能主动给我发消息,不能继续生成下一层 Agent,更不能跑任意 Shell。每个专家做完后,只能按统一的 Handoff 格式把结论交还给 main。
这套关系其实很像真实团队:负责人不必把所有活都抢过来做,专家也不该绕过负责人各说各话。我最后给它定下的规则很简单——入口统一、职责清楚、交付格式一致。
模型之间没有上下级,Agent 之间才有
很多人看到多智能体,第一反应是“是不是用了十一个不同模型”。其实不是。
我的配置里主要用了两类模型:
GPT-5.6 Luna:负责主控、写作、知识、生活、旅行、购物和视觉类岗位;GPT-5.6 Sol:负责投资、无线技术、运维分析和复杂咨询这些需要更深推理的岗位;- 图片生成单独使用
gpt-image-2。
模型只是能力底座,真正的上下级关系来自 OpenClaw 里的路由、工具权限和消息边界。main 用 Luna,并不代表它“比 Sol 更强”;它更像一个懂得分派任务、校验结果和承担最终责任的 Chief。
所有 Agent 都固定自己的主模型,并把自动 fallback 设为空:
model: {
primary: "openai/gpt-5.6-luna",
fallbacks: [],
},
models: {
"openai/gpt-5.6-luna": {
agentRuntime: { id: "openclaw" },
},
},我以前会觉得“有 fallback 总比没有好”。真正做审计时我才发现,模型一旦静默切换,输出风格、推理行为和兼容性也会随之变化,出了问题很难还原当时到底用了哪套能力。现在如果主模型不可用,我宁愿让失败被看见,再由 main 决定重试或降级。
一条消息在系统里怎么走
不是每个问题都需要专家。寒暄、系统介绍、简单解释和已有结果的短总结,main 直接回答。只有当任务需要实时数据、专业判断、专属工具、独立记忆或长篇产物时,它才委派。
比如我说:“帮我分析一只股票最近的走势,再写成一段适合发给朋友看的说明。”
这条任务会被拆成两段:
用户
→ main 判断敏感级别并删去无关信息
→ investment 查询数据、给出证据和风险
→ main 校验 Handoff
→ writer 只接收经过整理的事实
→ main 终审
→ 用户只收到一条最终回复这里有两个我刻意坚持的约束:一轮最多两个专家;专家之间不直接互相调用。需要更多角色时,由 main 分阶段串联。这样做没有“十个 Agent 一起开会”那么热闹,但资源可控,责任链也更清楚。
专家的返回不是随意写一段话,而是遵守同一个交接协议:
{
"task_id": "task-001",
"task": "分析某公司的公开财务数据",
"agent": "investment",
"status": "complete",
"conclusion": "收入增长,但现金流质量仍需观察",
"confidence": "medium",
"key_findings": [],
"evidence": [
{
"source": "公司公告,2026-08-11",
"fact": "报告期营业收入同比增长"
}
],
"risks": [],
"unknowns": [],
"recommended_action": [],
"needs_other_agent": {
"required": false,
"suggested_agent": null,
"reason": null
},
"artifacts": [],
"sensitivity": "public"
}这份 Schema 很像工作中的交付模板。它不保证结论永远正确,却能强迫系统把“结论、证据、风险、未知项”分开,避免一句很自信的话掩盖事实缺口。
我后来才分清 Skill、MCP 和 Memory
搭建过程中,我花了不少时间才真正分清三件容易混在一起的东西。
Skill 是做事方法。 它告诉 Agent 应该遵循什么流程、注意什么边界,但不代表 Agent 自动获得了某项权限。
MCP 是把外部工具和数据服务接进来的协议层。 股票行情、地图、航班和商品搜索通过这一层提供给相应专家,但不会因此变成所有 Agent 的公共能力。
Memory 是长期仍然成立的事实和偏好。 它不该变成聊天流水仓库,更不能存 Token、邮件正文、实时价格或工作秘密。
最初,我把 MCP 服务都放在全局配置里,以为再用工具白名单限制可见性就够了。后来通过运行时检查发现,“Agent 看不到工具”不等于底层服务没有被初始化。某些运行路径会先加载全局 MCP,再做工具过滤。这不仅扩大了权限面,也会在小型服务器上制造额外进程和内存压力。
最终我把七个 MCP 服务移出全局配置,按需要分装到五个专家的 workspace:
investment → 股票研究数据
ops → 固定只读诊断
life → 最小天气/地点能力
travel → 地图、航班、地理检索
shopping → 商品检索
main → 不加载业务 MCP每套服务只放进获授权专家的工作区,普通运行账号不能修改启动定义。测试时,我不只看工具列表,还会新开一个 main 会话,确认它没有启动业务 MCP;专家任务结束后,再检查相关子进程是否已经回收。
我实际怎么配
整个过程不是直接改一份大配置,而是按“先盘点、再备份、后变更”的顺序推进。
第一步:盘点现状
我先把当前 Agent、入口绑定、Cron、Skill、MCP、模型认证、Memory 目录和主机资源都列出来。尤其要确认原来的 main workspace 在哪里,因为直接换目录会让已有身份、记忆和会话脱链。
openclaw config validate --json
openclaw agents list --json
openclaw agents bindings --json
openclaw mcp status --json
openclaw gateway status --json第二步:先建回滚锚点
配置文件、主工作区、Agent 目录、定时任务和 systemd 单元分别备份,目录权限收紧,并生成校验和。任何一步出问题,都要能恢复到变更前,而不是靠记忆手工改回去。
第三步:建立独立身份和目录
十个专家分别拥有独立 workspace 和 agentDir。这里不能共用 agentDir,否则认证、会话和状态可能互相覆盖。
state/
├── workspace/ # 原 main,保留
├── workspaces/
│ ├── investment/
│ ├── work/
│ ├── ops/
│ └── ...
├── agents/<id>/agent/
└── shared/ # 仅非敏感协作规则第四步:固定模型、权限和并发
main 可以调用十个白名单专家,专家的 allowAgents 为空。所有 Agent 禁止任意 Shell、进程和 elevated 权限,文件工具限制在自己的 workspace。
agents: {
defaults: {
maxConcurrent: 2,
subagents: {
maxConcurrent: 2,
maxSpawnDepth: 1,
maxChildrenPerAgent: 2,
requireAgentId: true,
},
},
},
cron: { maxConcurrentRuns: 1 },
tools: {
elevated: { enabled: false },
exec: { host: "gateway", mode: "deny" },
fs: { workspaceOnly: true },
},这段只是全局底线;每个 Agent 还有自己单独的工具白名单和拒绝表,完整配置放在仓库里。
第五步:让 main 保持“薄”
main 只做路由、脱敏、串联和终审,不直接拥有股票、航班、商品或运维 MCP。专业能力越少,入口越容易守住。
它的委派规则也写得很死:每次 sessions_spawn 必须显式传入专家 agentId;只要最终答案依赖专家,就先 sessions_yield 等待;同一个用户请求只产生一条最终答复。
第六步:先 dry-run,再逐项上线
OpenClaw 的 Agent 列表是数组,合并补丁时可能整段替换,所以我每次都先做 dry-run,并检查配置引用和 Schema:
openclaw config patch \
--file ./config/openclaw.multi-agent.example.json5 \
--dry-run --json
openclaw config validate --json上线后也不一次并发探测全部 MCP。小机器上最稳妥的做法,是逐个服务串行检查:
openclaw mcp probe <server-name> --json每次探测前后都看内存和残留进程,确认回收后再测下一个。
几个真正让我长记性的坑
1. “回答了两次”,其实不是两个 Agent 在抢话
我在微信里问了一句系统介绍,先收到 main 的正常回答,紧接着又出现一个带 Sub-agent 字样的灰色气泡。第一眼看上去,就是主控回答一次,子 Agent 又回答一次。
审计会话后才发现,那一轮根本没有成功创建子会话。main 调用 sessions_spawn 时漏了必填的 agentId,工具返回 forbidden,微信又把失败的工具进度卡显示给了用户。卡片里的 cleanup delete failed 也不是删除失败,只是参数 cleanup=delete 和状态 failed 被界面拼在了一起。
最后我做了四件事:关闭微信工具进度卡外显、抑制原始工具错误、把 delegationMode 从容易主动委派的 prefer 调成更克制的 suggest,并强化 main 的显式 agentId + yield + 单次汇总 规则。
这件事提醒我:所谓“多智能体重复回复”,不一定是路由问题,也可能只是内部工具状态泄漏到了用户界面。诊断时必须看真实会话和投递事件,不能凭截图猜。
2. Tushare 不是“积分不够”这么简单
投资 Agent 原计划接入 Tushare。审计后发现,问题远不止账户积分:所用 Skill 来自第三方,旧版 SDK 会通过明文 HTTP 发送凭据,而且凭据曾被放进全局环境,扩大到了不相关的 Agent 和进程。
我没有为了“功能列表好看”强行把它修到能跑,而是把状态明确标成 DORMANT:禁用 Skill、撤掉全局凭据、按已暴露处理并要求服务端轮换。投资研究先走已经验收通过的 mx-ds 数据路径。
这可能是整个项目里最重要的一次取舍:能用,不等于应该用。
3. 十一个 Agent,不等于十一份并发
这是一台资源有限的小型 VPS。验收时我曾把多个模型测试、远程检查和 MCP 探测叠在一起,结果直接触发了主机 OOM。
最后的配置非常克制:Agent 总并发 2、子 Agent 并发 2、最大深度 1、单任务最多两个子 Agent、Cron 并发 1。需要更多专家就排队,MCP 验收全部串行。
从那以后,我宁可让任务排队慢一点,也不再拿整台机器的稳定性赌并发。
4. Sandbox 不能为了打勾而提权
Docker 镜像已经准备好,但 OpenClaw 的服务账号不能安全访问 Docker socket。最省事的办法,是把它加入 Docker 管理组;可这几乎等于给了接近 root 的主机控制权。
我最终选择承认 Docker Sandbox 仍然是 DEGRADED,继续用 exec deny、workspaceOnly、独立目录、窄工具和 MCP 分域做逻辑隔离。标签不好看没关系,边界不能自欺欺人。
5. 运维 Agent 不能拿到“看起来只读”的通用命令
命令白名单如果只限制可执行文件路径,并不能限制参数。允许 systemctl status 的同时,很可能也等于放开 systemctl restart。
因此 ops 最后没有任意 Shell,只拿到五个固定、无参数、只读的诊断动作。需要修改、重启、发布时,仍然走独立授权和回滚流程。
我怎么证明它真的能用
我不再把“配置校验通过”当作上线完成。最终验收至少包括:
- 11/11 Agent 启动与固定模型检查;
- 20/20 路由用例;
- 十类越权负向测试;
- Prompt Injection 代表测试;
- 七个 MCP 的协议和实际业务调用;
main无业务 MCP、无任意 Shell;- 原有 15 条 Cron 完整保留;
- 双专家协作后只由
main输出一条最终消息; - 微信单次投递事件的
resultCount=1; - 回滚备份、权限和校验和验证。
我也保留了三个不那么好看的状态:Docker Sandbox 是 DEGRADED,Tushare 是 DORMANT,真人微信完整入站在最终复测前是 PENDING-HUMAN。
以前做个人项目,我很容易把“差不多能跑”写成“已经完成”。这次反而是这些明确的状态,让整套系统更可信。
做完以后,我重新理解了“管理”
回头看,这次最有价值的不是多了十个 Agent,而是我给这支团队留下了几条很朴素的规矩:负责人保留必要控制权,专家只做职责内的事;信息只传完成任务所需的部分;交付要说明证据、风险和不知道的地方;能力不等于授权;出问题先留现场,上线前先想好怎么退回去。
我原来以为,多智能体的重点是“多”。现在我更愿意说,它的重点是“组织”。
做到这些以后,我才敢把它接进每天都用的微信入口,而不只是留在测试窗口里演示。
完整的脱敏配置、Prompt、Handoff Schema、命令和验收清单,我整理在独立仓库:openclaw-multi-agent-team。
本文著作权归作者所有;未经许可请勿全文转载。