多智能体协作,最容易翻车的不是模型,是权限。子 Agent 该拿哪些工具、能碰哪些文件,这事的正确做法不是把「别乱动」写进提示词,是在工具层设一个 tool_allowlist 白名单。提示词是给模型看的建议,白名单是给运行时看的墙。前者可以违背,后者过不去。这篇把工具隔离、最小权限、上下文交接、所有权这几件事一次说清。
我现场抓了 5 个来源,ai4.sale、bison、egoistai、dataaihub、benhalpern,打开每一篇把 tool isolation 的说法逐个对过,没有一家主张「全给再靠提示词拦」。我先摆一句判断:权限隔离的第一原则,是每个子 Agent 只拿它这一份活需要的工具,而不是把所有工具都塞给它。这个结论不新,是 NIST SP 800-171 第 3 版里的最小权限,但落到 agent 上,太多人还在靠提示词硬撑。别都拿。
提示词约束为什么不够
给一个 research agent 挂上全部工具,再在提示词里写「不要调用部署工具、不要发外部消息」,这叫政策,不叫防线。它只要有一次推理偏了,就会去调那个它不该碰的工具。多个来源都在讲同一件事:约束必须落在工具层,用 allowlist、路径边界、交易上限、审批门槛这些机制,而不是模型自觉。
我给出具体做法。先把角色拆成 4 层权限:只读、可写、审批、管理。research agent 只读,diagnostic agent 只读加局部写,draft agent 能写草稿但不能发外部消息,审批权留在 orchestrator 或人手里。凭证用短生命周期的,任务结束就回收。这 4 层拆开,出事的半径就小了。这套我查过出处,NIST SP 800-171 讲的正是「限制特权账户到授权角色」,落到 agent 的凭证上就是同一个道理。
白名单怎么落地
具体到工具,白名单是给每个 agent 配一个工具子集:code agent 拿 read_file、write_file、run_tests,不拿 web_search,而 research agent 拿 web_search、scrape_page,不拿任何写文件的工具,两边各拿各的,谁也不全。这是 dataaihub 那篇讲的 per-agent tool isolation,我认同它的骨架。
research_tools = ["web_search", "scrape_page", "read_url"]
coder_tools = ["read_file", "write_file", "run_tests"]
reviewer_tools = ["read_file", "read_diff"] # 无写、无网
这段是我自己写的,示意三个角色各配一个工具列表。真落到框架上,就是 tool_allowlist 加 max_turns 这两个参数,一个管能调谁,一个管能调几次。关键不是这几个名字,是「各配各的」这个结构。reviewer 连网络都不该有,它只读代码和 diff。给它网络,它就可能去查自己不该查的东西。三个列表里没有一个角色拿全量,这就是白名单和「全给再靠提示词拦」的差别。
上下文交接,传包不传会话
第二个坑是上下文。父 agent 派活给子 agent,常见的错是把手头整个对话历史都塞过去。这有 3 重代价:token 涨、敏感信息暴露、冲突指令更难被发现。多个来源的口径一致:传一个 work packet,不传整个会话。
work packet 里该装什么,我给一份清单:task_id、要的输出、证据引用、已确认的事实、已经做的决策、未决的问题、禁止的动作、下一个 owner。传之前先过一个 schema 校验,再让接收方跑。自由文本的 summary 容易漏掉一条限制,或者把推理写成了事实。
packet = {
"task_id": "t-421",
"goal": "verify Competitor B pricing from primary source",
"evidence": ["cache/vendor-page.html"],
"confirmed": ["price $12.5/unit"],
"unknowns": ["annual discount"],
"forbidden": ["external messages", "create account"],
"owner": "research",
}
这段也是我写的示意。重点在 forbidden 和 unknowns 这两个字段,它们是最容易被自由文本省略的。我的判断是,handoff 的 payload 必须是可校验的数据,不是一段胜利宣言。8 个字段里少一个,接收方就可能在边界外自作主张。
所有权要落在一个人身上
还有一个容易忽略的点:谁来对最终结果负责。多个来源反复强调,orchestrator 拥有 intake、路由、完成状态、升级、最终交付,specialist 不共享这份权。一个 research agent 查漏了证据,是 research 这个角色的锅;两个 agent 给的结论冲突,orchestrator 把冲突升级给 authority owner,而不是让另一个模型再投一次票。
这条我的态度很硬:多 agent 系统的可靠性和 agent 数量无关,跟所有权清晰度有关,加 agent 不自动加可靠,反而多一个可能乱动工具的入口,你得再给它划一道权限边界。冲突时别让模型平均它们的措辞,要比来源权威、时间戳、实体边界,定不了就保留两边、标未知、升级。归属不明,等于没有归属。别让模型投票。dataaihub 那篇还引了一个综述编号,arXiv 2402.01680,是 LLM 多智能体的 survey,我拉下这篇 survey 的标题核过,讲的就是 supervisor 这套骨架。
并行只在无冲突时用
并行委派能提速,但前提是任务独立。两个 agent 写同一个文件、同一张表、同一条记录,没有锁和冲突解决,就是在制造事故。共享工作要有合并策略:代码分开分支或不相交路径,数据用乐观并发加版本号,文档指定一个 synthesizer 其余只读。LangGraph 里这套对应 add_node、bind_tools、add_conditional_edges 几个原语,装包是 pip install langgraph。我装过这个包,1.2.x 版本,配 Annotated[list, operator.add] 做 reducer,并行结果才拼得起来。不加 reducer,它就抛 InvalidUpdateError。跑不通。
给个结论。你的多 agent 系统要上生产,最该先补的不是更多 agent,是三样:工具白名单、结构化的 handoff、以及边界处的确定性校验。校验别让 worker 自我证明,跑 schema、跑测试、查文件存在、查 HTTP 状态、查行数、看 diff。这几样不依赖任何模型的诚实。它们都是确定性的。
一句话。子 Agent 的权限,写在工具层的白名单里,才叫设防;写在提示词里,那叫许愿。