多智能体框架需要独立的消息通道
作者:Harshal Gajjar
如今所有消息都挤在同一个对话框里。上游、下游、横向、同级、告警,每一类都该有自己的通道。
最近我一直在用平时那套框架把智能体(agent)串起来干活。一个负责规划,几个负责执行,一个负责审查,我则坐在中间随时推一把。跑得通。但很快就乱套了,而且乱的不是模型,是我。
每条消息都落在同一个对话框里:我提的需求、子智能体发来的状态更新、上级智能体问的「请澄清一下」、兄弟智能体留的备注、还有一条 CI 失败——看起来全都一样,就是长长一串滚动文字里的一行。二十分钟后,我已经分不清谁问了什么。智能体能分清,因为它手上有完整上下文,能推断出谁说了什么。可盯着这一切的人是我,最后只能靠手工一点点还原。
一个办法是让智能体帮我画一张图,用工具把谁给谁发了什么画出来。能用,但只是在乱麻上打补丁。更干净的做法是一开始就别把消息混在一起:每类沟通单独开一条通道,我可以单独读、单独查。
一个界面,五种关系
如今的框架默认只有一段对话:一个人跟一个智能体说话。一旦智能体之间开始互相交流,这个前提就不成立了。身处团队中间的一个智能体,其实同时有五股信息流:
-
上游:它的上级。 把任务派给它、定好目标、等着结果的那个智能体(或人)。上游永远在工作之外,不碰代码也不碰文档。它管的是「元工作」——决定这件事是什么、有没有在正轨上、算不算完成。这里传的消息都围绕范围、优先级和汇报。
-
下游:它管着的智能体。 也就是它把任务拆给的那些干活的。指令往下发,进度、结果或阻塞回上来。
-
Sideways(平行):和它并肩干活的人。通常就是 agent 的拥有者,坐在同一份工作里,盯着同样的文件、同样的 diff、同样写了一半的草稿。这里没有上下级关系,是结对协作。Sideways 是唯一一个每条消息都来自人类的通道——是人敲出来的,不是 agent 生成的:「嘿,其实该这么改」「你为什么选那个方案」「停,这样不对」。
-
Peers(同级):同一层级的其他 agent。可以是同一个主管下面的兄弟 agent,也可以是隔壁团队的 agent。这里谁都不管谁。消息是协调性的:「我在改
auth.ts,你先别动」「你的 API 返回什么结构」「那个我已经修了,跳过吧」。 -
Alerts(告警):这些不是谁在说话。构建挂了、测试变红、定时器触发、webhook 打进来、预算快用完了。没人发问,但事情变了,agent 可能得有所反应。
最容易混淆的一对是 Upstream(上游)和 Sideways,因为两者都可能是人在给方向。区别在于他们站在哪里。Upstream 站在工作之外谈工作:目标、截止时间、签字确认。Sideways 站在工作之内谈这件事本身:这一行、这个函数、这一段。主管问的是「登录流程做完了吗?」同事说的是「那个重定向写错了,用回调 URL。」同一个人可以同时扮演两种角色,但任何一条具体消息,要么是上游,要么是平行。
它们携带的权限不同、紧急程度不同、对回复的预期也不同。把这五类全塞进一条消息流,就好比把你的整份工作塞进一个邮件线程里——你的上司、你的下属、你的合伙人、你的队友、还有你的寻呼机全在里面。
混在一起会出什么问题
-
权限丢失。 来自子 agent 或同级 agent 的指令,看起来和来自人类的一模一样。agent 通常能靠上下文分辨「我的下属建议 X」和「我的拥有者要求 X」,但没有任何机制能保证这一点,而且不把消息全部重读一遍,我也没法核对。
-
回复发错地方。 agent 把一个下游的问题回答在了只有人类能看到的地方,或者把本该给下属的消息汇报给了主管。
-
同级之间彼此碰撞。 没有一条直接的横向通道,兄弟姐妹只能通过主管协调,或者干脆不协调。两个智能体编辑同一个文件,或者都去修同一个 bug,主管事后才发现。
-
告警要么被淹没,要么反客为主。 聊天记录里刷过去的一条红色构建失败信息,很容易就被忽略。反过来也可能出问题:智能体把每条通知都当成新指令,丢下手头的任务去追噪声。
-
人没法干净地插进去。 如果我想在任务进行中纠正某个智能体,我的消息会和其它一切挤进同一个队列,也没有标记说明它来自真正该负责的人。
-
审计轨迹是一团糊。 回头看,没人能还原出谁决定了什么、又是什么触发的。出问题的时候,这恰恰是最要命的。
前四个还能凑合打补丁:给每条消息打上发送方标签,加个「来自我主人」的标记,给告警加个 [ALERT] 前缀,智能体基本能分得清。后两个不行,因为它们关乎的是人,不是智能体。消息来得太多太快,想插手或回头查的人都会淹没在滚动条里。就算每条都打了标签,我还要读上千行才找到关键的那条,标签也救不了我。
harness 应该怎么做
换个更聪明的模型解决不了这个问题,harness 需要的是结构:
-
一个上下文,五条通道。 智能体只保留一份工作记忆,但每条消息都打上标记:向下、向上、横向、同级,或者告警。模型看得到这个标记,harness 强制维护它。这不是往 prompt 里粘一句约定就能搞定的。
-
给人单独的视图。 每条通道给一个面板或者过滤器。打开一个智能体,我希望一眼看到:它的上级交代了什么、它的下属在说什么、同级在谈什么、触发了什么、我又说了什么,而不用一次性翻完整条信息流。每条通道就是一份独立日志,我可以一次只审计一层关系。
-
回复要有地址。 智能体响应时,得先选一条通道。「向上汇报」「向下下达」「回复我的人」「告诉同级」,这是不同的动作,不是笼统的一个
send。告警不接收回复,只能被确认、处理,或者升级。 -
权限跟着信道走。上游负责设定目标,并判断目标是否达成。来自负责人的横向消息可以推翻具体做法,细到每一行。下游提供的是输入,不是命令。同级之间可以询问、可以知会,但不能发号施令。告警传递的是事实,不是指令。框架可以强制执行这套优先级,而不是指望模型自己从语气里猜出来。
-
告警有自己的规则。严重程度、去重和路由都由框架负责。部署失败应该打断当前工作,偶发的 lint 警告可以先在队列里等等。智能体决定怎么处理一条告警,但它不该再去分辨一条告警和一个人发的消息有什么区别。
这些做法我们在别的地方早就用上了。组织架构图一直如此。邮件有收件人、抄送,抄送栏里还写着老板的名字。Slack 把私信和频道分开,也没人会把自己 PagerDuty 收到的告警,当成主管发来的消息。可我们却在一个假设「团队只有一个人」的聊天界面上,搭建多智能体系统。
为什么是现在
单智能体框架已经足够好用,于是大家开始把它们串起来。整条链路正在成为工作的基本单位,而聊天框撑不起这个规模。我希望下一个用的框架能清清楚楚地告诉智能体、也告诉我:现在是谁在说话,以及到底有没有人在说话。
上游、下游、横向、同级、告警。五种对话挤在同一份上下文里。光凭这一点,我就愿意换个框架。