多智能体不是越多越强:我用100行Python,拆穿AI Agent协作的真相

发布时间:2026/7/22 10:36:19
多智能体不是越多越强:我用100行Python,拆穿AI Agent协作的真相 现实是什么现实是我见过太多人把一个本来单智能体能干好的活硬拆成五个角色然后花两周时间调试“为什么产品经理说的话程序员理解错了”。最后系统跑通了效果还不如原来那个单智能体token 消耗翻了四倍。00、开场白先泼一盆冷水去魅优先代码说话打开任何一个 AI 框架的官网你都会看到类似的宣传图五六个圆圈每个圆圈里画个小机器人箭头连来连去配文“多智能体协作模拟人类团队”。看起来特别高级仿佛你只要把智能体拆成“产品经理”“程序员”“测试员”它们就能像一家创业公司一样自动运转你躺着收钱。现实是什么现实是我见过太多人把一个本来单智能体能干好的活硬拆成五个角色然后花两周时间调试“为什么产品经理说的话程序员理解错了”。最后系统跑通了效果还不如原来那个单智能体token 消耗翻了四倍。所以这篇文章要讲三件事1.单智能体的能力边界到底在哪什么时候真的需要拆2.手写一个最小多智能体系统不用任何框架让你看清里面到底是什么3.通信协议怎么设计才能避免“传话游戏”式的信息损耗。老规矩去魅优先代码说话。01、单智能体的能力边界大部分时候你不需要拆BOUNDARY · 什么时候该拆1.1 先想清楚拆分的成本是什么很多人以为多智能体是“免费的午餐”多几个角色能力更强有什么不好但每多一个智能体你就多付出三样东西第一token 成本翻倍每个智能体都要带上自己的系统提示词、历史消息、工具定义。原来一次调用能解决的事现在要三五次调用每次还都拖着一坨上下文。第二信息损耗智能体 A 把结果传给智能体 B中间必然经过一次“总结—转述”的过程。就像你让同事帮你带话给老板带三层之后“周五前完成初稿”就变成了“尽快交终稿”。这个问题严重到我们要用整个第三节来讲它。第三调试地狱单智能体出错你看一条对话记录就知道哪句话没写好。多智能体出错你要在五份对话记录里找“到底是谁先理解错的”而且错误会传染A 理解错了B 基于错误结论继续推理到 C 那里已经面目全非。1.2 那单智能体到底卡在哪既然拆分这么贵为什么还有人拆因为单智能体确实有几堵墙撞上了就是撞上了 墙一上下文污染想象你让一个智能体既写代码又审代码。它刚写完一段代码你让它审它会审出什么大概率是“写得不错逻辑清晰”。因为审核所需的“挑刺视角”和写作时的“辩护视角”在同一个上下文里打架而模型天然倾向于跟自己已经生成的内容保持一致这是心理学上的承诺一致性在语言模型上的翻版。这时候把“审核”拆成一个独立智能体它看不到写作过程只看到成品挑刺就狠得多。 墙二注意力稀释系统提示词写到三千字以上你会发现模型开始“选择性失忆”。你在第 47 条规则里写了“输出金额必须保留两位小数”它偏偏就忘这条。因为一个上下文里塞的指令越多每条指令分到的“注意力”就越少。拆分之后每个智能体只带自己那一小份规则谁也不用背全套家规。 墙三角色冲突有些任务天然要求“两种互相矛盾的性格”。比如营销文案生成你既要一个“敢吹”的创意角色又要一个“较真”的合规角色。让一个智能体同时“放飞”和“收敛”结果往往是两头不到岸文案平庸合规也马虎。1.3 一条实用的判断标准我自己用的标准很简单一句话当你在系统提示词里写“先扮演 A 做 X然后切换到 B 做 Y”的时候就该拆了如果你的提示词是“你是一个数据分析助手请分析用户上传的表格”不用拆这就是一个角色干一件事。如果写成了“你先作为规划师拆解任务再作为工程师执行最后作为质检员用批判性眼光审查自己刚才的输出”恭喜你已经在一个上下文里硬塞三个人格了拆吧。反过来说以下情况不要拆任务本身很短一两轮就能完成拆分的通信开销比任务本身还大各“角色”之间需要共享大量细节拆开后传递成本极高你只是觉得“多智能体听起来更酷”。02、手写一个最小多智能体系统HANDS-ON · 三角色·裸Python好假设你确认自己真的需要拆。现在我们不用 AutoGen不用 LangGraph不用 CrewAI就用裸 Python 一个 OpenAI 兼容接口手写一个三角色系统规划者Planner接到用户需求拆成步骤执行者Executor按步骤逐个执行审核者Reviewer检查执行结果不合格打回重做。为什么要手写因为框架把“消息怎么传、状态怎么存、循环怎么控制”全藏起来了你只看到几个装饰器出了问题两眼一抹黑。手写一遍之后你再去用框架就知道那些装饰器背后是什么了。2.1 基础设施一个函数搞定模型调用Pythonfrom openai import OpenAI client OpenAI( api_keysk-xxxx, base_urlhttps://api.deepseek.com, ) def call_llm(system_prompt: str, user_content: str) - str: 所有智能体共用的底层调用。注意:每次调用都是全新上下文。 resp client.chat.completions.create( modeldeepseek-v4-flash, messages[ {role: system, content: system_prompt}, {role: user, content: user_content}, ], temperature0.3, ) return resp.choices[0].message.content看到没有所谓“智能体”在最底层就是同一个模型 不同的系统提示词。规划者和执行者用的是同一个 deepseek-v4-flash区别只是开场白不一样。这是第一层去魅多智能体不是多个大脑是一个大脑反复“入戏”扮演不同角色。2.2 定义消息格式先立规矩再开工在写角色之前先定义智能体之间传什么。这一步很多人跳过直接传自然语言字符串这就是后面“传话游戏”的祸根。我们用结构化消息Pythonfrom dataclasses import dataclass, field dataclass class Task: step_id: int instruction: str # 这一步要做什么 context: str # 做这一步需要知道的背景(原始信息,不是转述) result: str # 执行结果 review_passed: bool False review_comment: str dataclass class Blackboard: 共享黑板:所有智能体都能读,避免层层转述 user_request: str # 用户原始需求,一字不改 tasks: list[Task] field(default_factorylist) max_retries: int 2注意 Blackboard 里的 user_request用户的原始需求会原封不动地传给每一个智能体而不是让规划者“转述”给执行者。这是本文最重要的设计决策之一第三节细讲。2.3 规划者只负责拆不负责干PythonPLANNER_PROMPT 你是任务规划者。把用户需求拆解成 2-4 个可独立执行的步骤。 只输出 JSON 数组,每个元素形如: {step_id: 1, instruction: 具体做什么, context: 这一步需要的背景信息} 不要输出任何其他内容,不要 markdown 代码块。 import json def plan(board: Blackboard) - None: raw call_llm(PLANNER_PROMPT, board.user_request) steps json.loads(raw) board.tasks [Task(**s) for s in steps]规划者的系统提示词就五行。它不知道怎么写代码不知道怎么审核它这辈子只干一件事拆任务。这就是“注意力不稀释”的具体体现。2.4 执行者拿到什么干什么PythonEXECUTOR_PROMPT 你是任务执行者。根据给定的步骤指令完成任务。 直接输出结果,不要解释你在做什么,不要客套。 def execute(board: Blackboard, task: Task) - None: # 关键:把用户原始需求 本步骤指令一起给它,而不是只给转述后的指令 content f## 用户原始需求 {board.user_request} ## 你当前要完成的步骤 {task.instruction} ## 相关背景 {task.context} ## 之前步骤的成果 {format_previous_results(board, task.step_id)} if task.review_comment: # 如果是被打回重做,带上审核意见 content f\n\n## 上次被打回的原因(请修正)\n{task.review_comment} task.result call_llm(EXECUTOR_PROMPT, content) def format_previous_results(board: Blackboard, current_id: int) - str: done [t for t in board.tasks if t.step_id current_id and t.review_passed] if not done: return (无) return \n.join(f步骤{t.step_id}:{t.result} for t in done)2.5 审核者铁面无私因为它没有包袱PythonREVIEWER_PROMPT 你是质量审核员。判断执行结果是否满足步骤要求和用户原始需求。 只输出 JSON:{passed: true/false, comment: 不通过时给出具体、可操作的修改意见} 审核标准:宁可错杀,不可放过。 def review(board: Blackboard, task: Task) - None: content f## 用户原始需求 {board.user_request} ## 步骤要求 {task.instruction} ## 执行结果 {task.result} raw call_llm(REVIEWER_PROMPT, content) verdict json.loads(raw) task.review_passed verdict[passed] task.review_comment verdict.get(comment, )审核者最大的优势是什么它没看过执行者的“心路历程”。它不知道执行者纠结了什么、妥协了什么它只看到需求和结果像一个刚进门的客户一样冷酷。这就是第一节说的“上下文隔离带来的批判性”。2.6 调度循环把三个角色串起来Pythondef run(user_request: str) - Blackboard: board Blackboard(user_requestuser_request) plan(board) print(f规划完成,共 {len(board.tasks)} 步) for task in board.tasks: for attempt in range(board.max_retries 1): execute(board, task) review(board, task) if task.review_passed: print(f步骤{task.step_id} 通过(第{attempt1}次尝试)) break print(f步骤{task.step_id} 被打回:{task.review_comment}) else: print(f步骤{task.step_id} 重试耗尽,带病放行) task.review_passed True # 实际项目里这里应该上报人工 return board # 跑起来 board run(帮我写一份介绍AI Agent的 300 字文章,要求提到Loop和Multi-Agent,风格严谨)不到一百行一个带“规划—执行—审核—打回重做”完整闭环的多智能体系统就跑起来了。没有魔法没有黑箱所谓“协作”就是一个 for 循环所谓“角色”就是不同的系统提示词所谓“记忆”就是那个 Blackboard 数据类所谓“反思重做”就是把审核意见拼进下一次调用的提示词里。框架帮你做的无非是把这些封装得更优雅、加上并发和容错。理解了这一百行你看任何多智能体框架的文档都不会再头晕。03、通信协议如何避免“传话游戏”PROTOCOL · 全文最值钱的部分现在讲全文最值钱的部分。多智能体系统翻车九成翻在通信上。3.1 什么是“传话游戏”式损耗小时候玩过传话游戏吧第一个人说“小明明天早上八点在东门集合记得带伞”传到第五个人变成“小明带伞”。每一次转述都是一次有损压缩。多智能体系统里这个游戏每时每刻都在上演用户“帮我分析这份销售数据重点看华东区 Q3 环比下滑的原因如果是渠道问题就单独列出来。”规划者转述给执行者“分析销售数据中华东区的下滑情况。”看到了吗“Q3”“环比”“渠道问题单独列出”三个关键约束全丢了。执行者拿着残缺的指令认认真真干活产出一份“华东区全年销售概览”——每个智能体都没犯错但系统整体答非所问。更阴险的是这种损耗不报错。代码写错了会抛异常信息传丢了系统照常运行只是结果越来越歪。你 debug 半天发现每个环节的模型输出“看起来都挺合理”。3.2 对策一原始需求直通车这就是为什么第二节的代码里user_request 被原封不动塞进了每个智能体的输入。原则一句话转述可以有原文不能丢。任何下游智能体都必须能看到用户的原始需求规划者拆解出的 instruction 是导航用户原文是地图。导航可能算错路线但只要地图在手执行者还能自己校正。成本呢多几百个 token 而已比起返工重跑便宜到可以忽略。3.3 对策二结构化消息别传自由文本智能体之间用 JSON或 dataclass传消息而不是一段自然语言好处有三字段是强制的定义了 {step_id, instruction, context}规划者就必须为每个步骤填 context想偷懒都不行。自由文本呢模型今天心情好写得详细明天就给你省略。丢失是可检测的结构化字段缺了json.loads 直接报错或者你可以用一行断言拦住。自由文本丢了信息鬼知道。下游解析零歧义“先做 A 再做 B不过如果 C 的话也可以先做 B”——这种话让下游模型再理解一遍又是一轮损耗。结构化之后没有“理解”环节只有“读取”环节。3.4 对策三黑板模式 vs 接力模式多智能体通信有两种基本拓扑接力模式A 的输出作为 B 的输入像流水线。优点是简单、隔离性好缺点就是传话游戏——链条越长损耗越大。黑板模式所有智能体读写同一块“黑板”每个人都能看到全局状态。优点是没有转述损耗缺点是黑板越写越大且“谁都能写”需要规矩。实战建议小系统用黑板大系统黑板 接力混合——原始需求和关键结论上黑板过程性的中间产物走接力用完即弃。我们第二节的代码就是这个混合结构user_request 常驻黑板而“之前步骤的成果”只挑审核通过的传给下一步。3.5 对策四审核者要对齐“原始需求”一个隐蔽的坑审核者如果只对照“步骤指令”检查那规划者拆错了审核者会把错误的执行结果判为“通过”因为它确实完美符合那个错误的指令。所以第二节代码里review 的输入同时包含“用户原始需求”和“步骤要求”。审核者不只是流水线上的质检员还是用户在系统内部的“代言人”。这一个设计能拦住大量“每步都对、整体全错”的诡异翻车。3.6 一个反直觉的结论最后说一个很多人不愿意接受的事实多智能体系统的上限取决于通信协议的设计而不是智能体的数量三个角色 严谨的消息协议吊打十个角色 自由文本乱传。就像公司里五个人加一套清晰的文档规范干得过二十个人在微信群里吼。加智能体是加法修通信是乘法。结语三件事总结SUMMARY · 写在最后总结一下这篇讲的三件事1.别为了拆而拆。单智能体撞上“上下文污染、注意力稀释、角色冲突”这三堵墙时才值得拆。判断标准提示词里出现“先扮演 A 再扮演 B”就是拆分信号。2.多智能体没有魔法。一个模型 几段系统提示词 一个调度循环 一个共享数据结构一百行裸 Python 就能写出完整的“规划—执行—审核”闭环。框架只是把这一百行封装得漂亮些。3.通信协议决定上限。原始需求直通车、结构化消息、黑板与接力的混合拓扑、审核者对齐原始需求——四条对策专治“传话游戏”。