粟风导读
很多人把多智能体做成角色群聊。这篇对照 Codex 与 OpenClaw,拆的是回流工程:隔离怎么开、结果怎么回、谁负责合并。没有通信契约和合并策略,多半只是更贵的群聊。
开篇
一上多智能体,很多人先给角色起名:产品经理、工程师、评审,塞进同一窗口「开会」。Demo 热闹;任务一拉长就翻车——结论对不上、主会话被过程日志灌脏、并行一写互相踩。
隔离只是前半步。真正绕不开的是:
子代理干完活,结果怎么干净地回到主任务?
没有通信契约和结果合并策略的多智能体,多半只是更贵的群聊。
人设写得像不像不重要。工程上更要紧的是回传与合并,不是角色扮演。
一、群聊玩具,还不是可交付的多智能体
角色人设堆叠,不等于多智能体工程。
常见路径是这样:先注册三个角色 Prompt,再让它们互相回复。短问答看起来像协作;任务一变长,窗口里同时堆着方案草稿、试错日志、半截工具输出。合并权其实不在任何人手里,在「谁最后说话」里。
对后端工程师来说,这就像多开几个 @Service,却没有编排、没有请求响应契约、也没有「子流程结束必须回主流程」的约定。服务多了,不等于系统成形。
动手前不妨先问自己三句:
1. 子任务有没有输入输出契约?
2. 结果谁合并?
3. 失败怎么标?
答不清,先别急着上多智能体。
二、结果怎么回到主任务
spawn(拉起 / 派生)在这里很常见:就是主代理按契约新建一个子代理去干活——单独开一条子线程或子会话,不是多开几个角色挤在同一窗口聊天。
靠谱做法不是把子线程原文贴回主会话,而是这条链:
主代理持有目标与验收 → spawn 子代理(输入边界 / 上下文模式) → 子线程独立完成任务(过程留在子侧) → 回传 summary / 结构化结果 → 主代理等齐、合并、给出最终响应
图1 · 主-子回流:spawn → 子侧干活 → summary 回主 → 等齐合并(子间默认无直连)
1. 什么时候该 spawn,边界怎么写
不是随时随地一下子派出很多子代理。先问:这笔活会不会把主决策面弄脏?能不能并行、边界清不清晰?
Codex 常见会拆子代理的场景(更适合读多、可并行的活):
1. 代码库探索、大文件 / 大文档扫读,过程噪声大
2. 分点评审:安全、测试缺口、可维护性各开一个子代理,等齐再汇总
3. 跑测试、啃日志、做 triage(分诊归类)这类脏活
4. 多步功能里彼此独立的子块,适合并行推进
写操作并行要更谨慎——两边同时改同一处,协调成本会把并行收益吃掉。自定义子代理(如 explorer / reviewer)也是按「窄任务」配的,不是按群聊角色配的。
OpenClaw 常见会拆子代理的场景(和 Context Engine 钩子同向):
1. 主会话已经很长,还要再啃日志、核脚本风险——脏过程别继续堆进主会话
2. 需要干净起步:走 isolated 或 lightContext,少带主会话包袱
3. 需要从主会话拷一份上下文再分叉调研:走 fork
4. 子会话结束要清理、结果回父会话——靠生命周期钩子收口,而不是靠聊天自觉
对照一下:Codex 更常为「并行读、分点审」spawn;OpenClaw 更常为「隔离脏活、管住子会话上下文」spawn。 两边都不该为了「多几个角色开会」而拆。
Codex 用 agents.max_threads(最大并发线程)和 agents.max_depth(最大嵌套深度)卡住派出规模。max_depth 默认是 1:根线程可以拉直接子代理,子代理默认不宜再往下派,免得递归一开,token 和机器一起打满。
OpenClaw 把上下文模式写进生命周期:isolated、fork、lightContext 上面已说过。边界写在钩子里,比写在注释里可靠。
先有输入输出契约,再 spawn。 没有契约就派出子代理,后面多半合不拢。
2. 拉起时,主代理传给子代理什么
很多人默认以为:spawn = 把主聊天全文复制一份给子代理。一般不是这样——传的是任务契约 + 必要配置/权限 + 按模式裁剪后的上下文,不是主会话原文整锅端。
Codex 这边,常见是这几类:
1. 任务说明:要干什么、怎么拆、是否等齐、回什么 summary / 输出形态(好的派工 prompt 就该写清这几项)
2. 角色指令:自定义子代理 TOML 里的 developer_instructions(开发者指令);内置如 explorer / worker 也各有窄任务设定
3. 可继承配置:未单独指定时,model、sandbox_mode、mcp_servers、skills.config 等可从父会话继承
4. 权限与沙箱:继承当前 sandbox(沙箱策略)和 composer 下选的 permission mode(权限模式);也可在单个自定义 agent 上覆写(例如强制只读)
5. 工作区能力:仍在同一项目环境里读文件、跑工具,但主线程里的探索过程、试错对话,默认不整段搬进子线程——隔离的意义就在这儿
所以 Codex 的子代理更像「带着任务书和权限上场的新线程」,不是「主聊天的镜像分身」。
OpenClaw 这边,带多少主会话,取决于上下文模式:
1. isolated(隔离):少带主会话包袱;prepareSubagentSpawn 可在启动前准备共享或隔离状态
2. fork(分叉):从主会话拷一份再走——需要主会话背景时用
3. lightContext + isolated:跳过 prepare,从很瘦的 bootstrap(启动引导上下文)起步,刻意干净
4. 钩子能碰到的,是父子 session(会话)标识、可选的 transcript(会话记录)相关材料、TTL 等——用来按策略准备,不是无差别灌全文
对照一下:Codex 偏「任务书 + 继承配置/权限」;OpenClaw 偏「用 isolated / fork / light 决定带多少主会话」。 自研时也该写清:子代理启动上下文白名单是什么,而不是 clone(mainMessages)。
3. Codex:线程隔离,摘要回流
文档写得很清楚:子代理在自己的 agent thread(代理线程)里干活;主线程继续握需求、方案、验收;回流的是 summary(摘要),不是对方读过的全文。
编排也在主侧——拉起子代理、跟进或中断、等待结果、关闭线程。多个子代理跑着时,等齐后再给出 consolidated response(合并后的响应)。
你可以点进子线程看过程,但主决策面默认只吃结论。这和「三个角色挤在同一份聊天记录里」不是一回事。
4. OpenClaw:钩子落生命周期,结果回父会话
OpenClaw 把子代理边界挂在 Context Engine(上下文引擎)的可选钩子上:
1. prepareSubagentSpawn(子代理启动前准备):子会话开始前,准备共享或隔离的上下文
2. onSubagentEnded(子代理结束时清理):结束或被回收时做清理
原生子代理若请求 lightContext 且落到 isolated,还可以跳过 prepare,直接从很瘦的启动上下文起步。结果经回传路径回到父会话——叫 announce 也好,叫别的也好,意思都是:子侧收工,父侧接手。
名字和 Codex 不一样,跑法同类:隔离干活,结论回流,主编排合并。
5. 合并与防污染
回传之后还有半步:怎么合。等齐再汇总,通常最稳;某个子任务失败,要标出来,别假装大家都成功了再编一份漂亮结论。
防污染就一句:主会话只进结论;过程留在子侧,或进旁路日志供人回看。 堆栈、中间文件列表、试错对话,默认不该原样灌回主决策面——否则隔离等于白做。
三、主↔子怎么通信,子之间能不能互聊
回传能成立,是因为通信默认是主编排的星型,不是子代理群聊室。
主和子之间,更像一次带超时的 RPC:下行派任务——目标、约束、输入契约、是否等齐再继续;上行回 summary 或结构化字段。拉起、跟进、等齐、关掉,编排权在主侧。
子和子之间呢?默认更像父中介:子线程并不共享一条 peer 消息总线。Codex 把 max_depth 默认定在 1,本身就在限制「子再拉子」;社区里还有人对 shared workspace / message bus 提诉求,也侧面说明——自由互聊并不是当前默认。
真要协作,三条路通常更稳:
1. 经主代理转发——A 的结论先回主,主再派给 B
2. 共享只读工件——约定好的文件或结论卡,大家读同一份事实
3. 顺序 handoff——A 结束,主合并后再启动 B
一上来就开子↔子自由消息通道,审计难、污染快,合并权也容易从主任务飘走。
四、为什么要这样设计
子代理首先不是为了「多几个会说话的角色」,而是把脏活挪出主决策面。
主线程握需求、方案、验收;子线程去读文件、跑测试、啃日志。回传契约卡的是回流形态:回来的应是结论,不是整段 transcript(对话原文)。
编码代理里,上下文污染和 context rot(上下文腐烂:窗口被不太相关的细节填满,表现变差)很常见。探索笔记、测试日志、堆栈一旦挤进主聊天,有用约束反而被埋住。你花力气做隔离,若回流时又整段灌回去,等于把噪声请回主桌。
工程上更关键的是:隔离、契约回传、显式合并,不是角色扮演。
五、自研 Agent 怎么借鉴
可抄的是回传与合并边界,不是产品命令名。把它当成工作流子流程 / RPC,而不是群聊室。
原则先定这几条:
1. 先有输入输出契约,再 spawn
2. 上行只收结论;过程留子侧或旁路日志
3. 合并策略显式:等齐、超时、失败怎么标
4. 默认星型主编排;没有合并权就别派出子代理
5. 要子协作时,先问:合并权还在不在主代理
6. 启动上下文要有白名单——任务书 + 必要配置/权限 + 按模式裁剪,别默认全量复制主消息
换框架之前,先问清这几句。答不清,多智能体多半还停在群聊 Demo。
真要落到自己系统里,至少先有这几样:
1. 固定派工入口:谁可以 spawn、带哪些字段
2. 回传 schema:至少包括结论、依据引用、状态(成功/失败/超时)
3. 合并点唯一:对外响应只从主任务出口出去
4. 深度与并发上限:防止一下子派出太多打满成本
5. 回放字段:谁派的、回了什么、何时合并——出事能追
反模式清单:
1. 只堆角色人设,无 IO 契约
2. 子过程原文灌回主会话
3. 无等齐、无失败标记就对外答
4. 写操作无协调地并行
5. 无限深度嵌套派出
6. 默认上子↔子互聊总线且无审计
不过也别矫枉过正。短会话 Demo、任务边界本就清楚,单代理加工具往往更省事。真要并行读、要隔离脏活,再上子代理——且先把回传与合并做实。
六、面试怎么讲
这类题考的是隔离、回传和合并,不是框架名清单。常见就这几问:
面试官:多智能体和多角色 Prompt 有什么区别?
答:多角色 Prompt 常常还是同一窗口里换说话人。多智能体工程要有隔离边界、输入输出契约、结果回传和合并权。没有这四样,只是更贵的群聊。
面试官:子代理结果怎么回到主任务?
答:主代理握目标和验收,按契约拉起子代理;子线程独立干活,过程留在子侧;回传 summary 或结构化结果;主代理等齐、标失败、合并后再对外答。Codex 偏线程隔离加摘要回流,OpenClaw 偏生命周期钩子加结果回父会话,两边都是主编排。
面试官:子代理之间能互相通信吗?
答:默认更像父中介,不是 peer 群聊总线。真要协作,优先经主转发、共享只读工件,或顺序 handoff。一上来就开子互聊,审计和污染都会变难,合并权也容易飘。
面试官:怎么防止上下文污染?
答:主决策面只进结论;过程进子线程或旁路日志。隔离的意义,就是别把过程噪声再灌回主会话。
七、收束
先问子任务有没有 IO 契约、结果谁合并,再谈多智能体架构。
从 Codex 和 OpenClaw 能迁走的,不是角色名,而是:隔离干活、结论回流、主编排合并。群聊可以玩 Demo;要交付,得把回传做成工程。
企业自研该抄哪些边界、哪些命令行交互不必搬,主题另说。
你现在的多智能体,合并权在主代理,还是在群聊里?欢迎留言。
参考文档
1. Codex Subagents
https://developers.openai.com/codex/subagents
2. OpenClaw Context engine
https://docs2.openclaw.ai/concepts/context-engine
3. OpenClaw 概念页(仓库)
https://github.com/openclaw/openclaw/blob/main/docs/concepts/context-engine.md
4. Codex CLI 是怎么管理上下文的?从开发一个登录功能说起
5. OpenClaw 是怎么管理上下文的?从下一轮提问发出去之前开始拆
6. Codex CLI 和 OpenClaw,两种上下文管理思路差在哪?
---
我是粟风,5年 Java 开发,3年 AI 应用架构开发。本公众号不做泛 AI 工具推荐,也不贩卖转型焦虑。主要记录和分享后端工程师和团队在 AI 应用落地中真正会遇到的问题,围绕 RAG、企业知识库、智能客服和企业级 Agent 架构,拆解 AI 应用落地中的真实工程问题。
我是粟风,5年 Java 开发,3年 AI 应用架构开发。本公众号不做泛 AI 工具推荐,也不贩卖转型焦虑。主要记录和分享后端工程师和团队在 AI 应用落地中真正会遇到的问题,围绕 RAG、企业知识库、智能客服和企业级 Agent 架构,拆解 AI 应用落地中的真实工程问题。
夜雨聆风