资讯动态

基于LLM的多智能体系统开发实战:从原理到避坑指南

发布时间:2026/10/17 12:17:20 来源:尧图企业网站定制
最近后台一直有人问我同一个问题市面上那些讲大模型多智能体开发的课到底哪些内容是值得反复看的正好我前一阵把一套讲《基于LLM的Multi-Agent系统原理与开发实战》的精华内容完整过了一遍边看边对照自己踩过的坑。这期内容不聊概念就聊怎么从零把一个多Agent系统搭起来、跑起来以及在真实项目里那些文档不会告诉你的细节。如果你已经会用大模型API但面对“多Agent”还是感觉无从下手或者试过之后发现系统动不动死循环、上下文越跑越乱这篇文章应该能把整条链路讲透。我一直有个判断Multi-Agent不是大模型应用的银弹它是一套工程化的任务拆解方法。学它之前你得先搞清楚它到底解决了什么问题又引入了什么新问题。把这点想明白后面所有细节都是顺理成章的事。1. 为什么是Multi-Agent而不是一个超大Prompt1.1 单次模型调用撑不起复杂流程我见过很多团队第一次接触多Agent时的状态手里已经有了一个能跑通的单模型对话系统遇到复杂需求第一反应是“把提示词写得更长一点”把角色、规则、示例全塞进上下文里。结果呢流程稍微复杂一点要么上下文窗口撑不住要么模型在多个任务之间来回跳回答质量直线下降。举个例子你要做一个“文档审阅”系统既要理解合同条款又要核对金额还要生成修改建议最后还要输出一份格式化报告。如果全部塞给一次模型调用模型会频繁在“提取条款”和“生成建议”两个任务之间切换角色感互相干扰最终输出的报告结构和关键信息也极不稳定。这不是模型能力的问题而是单次调用本身就不适合承载多阶段、多职责的任务。上下文窗口永远有限让一个模型同时做十件事就像让一个人同时当前台、财务和法务每件事都做不专业。1.2 Multi-Agent真正解决的是“边界”问题Multi-Agent的核心思路不是“多几个模型一起聊天”而是给每个Agent划定清晰的职责边界让它只处理自己擅长的那一部分。边界体现在几个层面上下文边界每个Agent维护自己的上下文窗口不需要关心其他Agent的全部对话历史只接收和自己相关的消息。工具边界每个Agent只挂载自己需要的工具。审阅Agent不需要调用检索工具检索Agent不需要调用文档修改接口这样能极大减少工具误调用。角色边界每个Agent有独立的System Prompt角色指令互不影响。审查Agent可以严格挑刺改写Agent可以专注润色两个职责不会互相污染。行为边界通过消息协议约束Agent之间互相发送的内容格式避免“自由聊天”导致结构不可控。我在实际项目中体会最深的一点是多Agent系统的稳定性来自边界的清晰程度而不是模型本身多聪明。边界越清楚系统越稳。1.3 不适合硬上的场景我也得泼一盆冷水不是所有需求都适合多Agent。如果你只是做一个“把用户问题转给知识库检索再返回答案”的QA系统单模型调用加一个检索工具就够了强行拆成多个Agent只会增加延迟、成本和故障点。什么样的场景适合多Agent我总结了一个判断标准任务里是否存在多个可以独立验证结果的子任务而且这些子任务之间存在数据流转。比如文档审阅要先解析再审查再改写再归总每一步的输出是下一步的输入每一步都有明确的质量指标。这种流水线式的场景拆成多Agent才能体现价值。1.4 我所理解的“精华版”到底讲了什么这套内容比较务实的部分在于它没有停留在“什么是Agent”这种概念层而是直接讲清楚了一个多Agent系统的完整组成模型、提示词、工具注册、消息协议、调度器、上下文管理这几块。理解了这几个组件你就能自己搭一个最小可用的系统而不是只会套框架。接下来我把这套思路按我自己实战的路径拆开讲一遍。2. 核心原理拆解Agent、协作与编排2.1 单个LLM Agent的四个部件一个能稳定工作的LLM Agent最少要有四个部件缺一个都会在实战里出问题。第一个是大脑也就是大模型本身。它负责理解输入、做决策、生成输出。这里有个实用经验模型选型要和Agent的职责匹配。规划、决策类的Agent用强的模型比如做任务拆解、工具选择提取、改写、总结类的Agent可以用性价比更高的模型因为这类任务对推理要求没那么高但需要稳定遵循格式。第二个是工具。Agent需要通过函数调用、工具调用来执行动作。工具的定义非常关键每个工具要有清晰的名称、描述、参数Schema。描述写不清楚模型就不知道该在什么场景下调用它。我的经验是工具描述要给出“什么时候用、什么时候不要用”的边界说明而不仅仅是“这个工具能做什么”。第三个是记忆。记忆分短期和长期短期是当前任务的上下文会话长期是跨任务可复用的历史信息比如用户偏好、领域知识、向量库里的业务知识。多Agent系统里记忆必须做隔离否则会出现一个Agent“无意中看到”另一个Agent的隐私状态。第四个是输出协议。Agent不能自由发挥输出内容必须遵守结构化的输出协议通常是JSON或者受约束的文本格式。有了协议调度器才能稳定地解析结果并决定下一步动作。你可以把输出协议理解为Agent之间通信的“信封”没有统一信封内容再正确也递不到该去的地方。四个部件合并起来就是一个标准的工作循环接收输入 → 规划动作 → 调用工具 → 观察结果 → 生成输出。这个循环模型通常称为ReAct式的“思考—行动—观察”回路。2.2 多Agent怎么说话消息、黑板、工具链多Agent系统里最核心的机制是Agent之间的通信。我见过的新手最容易犯的错就是把多个Agent的对话历史直接拼在一起喂给模型。这条路基本走不通因为上下文会迅速膨胀而且信息互相干扰。合理的通信方式有几种通常可以混合使用消息传递一个Agent显式向另一个Agent发送消息内容可以是“请你帮我提取这份文档中的金额数据”。这是最接近真实团队协作的方式职责清晰、可追踪。共享黑板所有Agent读写同一个共享状态区类似团队协作时白板上的便签。适合信息需要被多方读取的场景比如任务状态、最终结论。要注意的是黑板上只放“公共信息”不能放某个Agent的私密上下文。工具链路Agent自己不直接通信而是通过调用共同工具完成协作。比如A Agent把解析结果写入存储B Agent读取这个存储继续处理。这种模式优点是解耦缺点是链路不直观。我实际项目里最常用的组合是主流程用消息传递公共状态用黑板批量数据走工具链路。三者的比例根据业务调整但骨架必然是消息传递否则没法做监控和干预。2.3 编排模式调度、流水线、协商有了通信机制还要有编排逻辑。编排是决定“谁在什么时候做什么事”的调度层也是多Agent系统和“多个Agent胡乱聊天”的本质区别。编排模式常见的就几类集中式调度一个主控Agent接收任务把子任务分配给各个专业Agent再汇总结果。好处是可控性最强适合任务边界清晰的场景。坏处是主控Agent自己可能成为瓶颈所以它的职责要尽量轻不要把所有细节都塞给它。流水线Agent按固定顺序处理前一个的输出是后一个的输入。适合处理流程非常确定的业务比如“解析→审查→改写→输出”的文档流水线。这种模式最容易实现也最容易排查问题因为每个环节都是线性的。协商竞争多个Agent针对同一问题分别提出方案再由仲裁Agent选择最佳结果或者投票决定。适合开放式生成、方案评审类任务。缺点是成本和延迟都会明显上升我通常只在结果质量要求很高时才用。选哪种模式不依赖模型能力而依赖业务确定性。业务路径越确定越应该用流水线和集中式调度业务路径越开放才需要引入协商。2.4 上下文隔离与记忆分配这是多Agent系统里最容易被低估的环节。多个Agent共用一套全局上下文看起来省事实际上是灾难的开始。我建议的分配方案是每个Agent有一个“私有上下文”只包含自身的System Prompt、最近几轮与自身相关的消息和工具执行结果同时系统维护一个“全局状态区”存放任务元信息、中间结果索引、最终结论。Agent读取全局状态时只读取自己权限范围内的键值这一点要在工具设计上强制限制而非指望Agent自觉。当某个Agent的上下文接近窗口上限时要考虑压缩。压缩方式有两种一是把早期消息摘要成几条要点二是把对话历史里的工具输出剥离只保留结论。我强烈建议优先剥离工具输出因为工具输出的原始内容往往很长但真正有用的就一两句结论。实测下来这一步能把上下文占用降低一半以上。3. 开发实战搭一个多Agent文档审阅系统3.1 场景与角色拆解为了不空谈我以“智能文档审阅系统”为例从头到尾讲一遍实现过程。这是一个典型的流水线式多Agent场景任务环节清晰非常适合理解原理。假设场景是这样的某公司内部每天有大量方案文书需要审阅要求系统自动完成“检查格式合规、核查事实一致性、提出修改建议、输出审阅报告”四件事。如果靠单个模型调用你会发现四项任务相互干扰输出报告经常漏项。我设计的角色是四个解析Agent负责把上传的文档文本分块、提取结构信息比如标题层级、段落、表格、关键人名和日期。审查Agent基于业务规则库检查文档中是否存在格式不合规、数据矛盾、表述含糊等问题。它只做判断不负责修改。改写Agent接收审查Agent的问题清单逐个生成修改建议。汇总Agent把审查和改写的结果整理成标准审阅报告输出结构化的JSON。四个角色各司其职任何单一Agent的上下文里都不会混入其他环节的庞杂信息。3.2 Agent定义角色提示词、工具注册、输出解析先看Agent的定义方式。我习惯用一个结构化的配置对象来描述每个Agent包含角色名、职责描述、System Prompt、可用工具列表、输入输出格式。from dataclasses import dataclass, field dataclass class AgentConfig: name: str role: str system_prompt: str tools: list[str] field(default_factorylist) output_format: str json model: str default这四个Agent的System Prompt我写得很具体不是泛泛的“你是一个审阅专家”而是把职责边界和输出要求写清楚。以审查Agent为例你是一名文档审查专员。你的任务是基于给定的业务规则检查文档内容中的问题。你只负责检查不负责修改。 检查范围包括格式合规性、事实一致性、表述清晰度。 输出要求 1. 如实列出你发现的问题每条问题包含所在章节、问题类型、严重程度、问题描述、建议方向。 2. 如果没有发现问题输出一个空的问题列表。 3. 不要输出与检查结果无关的内容。工具注册是整个系统里最需要耐心做的事。每个工具都要有明确的“名称”“描述”“参数Schema”“返回结果格式”。以审查Agent的“规则检索工具”为例{ tool_name: query_business_rules, description: 根据问题关键词查询对应业务规则。当遇到不确定的合规性问题时调用不要用于查询文档正文内容。, parameters: { type: object, properties: { keywords: { type: array, items: {type: string}, description: 关键词列表尽量提取文档中的原始表述 } }, required: [keywords] } }这里有个关键细节工具描述里要写清楚“什么时候不该调用”。模型对工具的理解完全依赖描述文本描述越精确误调用越少。我早期写工具描述只写“能做什么”结果模型在不需要查规则的时候也去查一遍既拖慢速度又把规则库里的无关内容带进上下文。3.3 消息协议与调度核心Agent之间通信我使用统一的消息结构。消息字段固定为发送者、接收者、消息类型、消息内容、时间戳。类型固定为task、result、error、notice四种不允许自由发挥。{ from: agent_reviewer, to: agent_formatter, type: task, payload: { doc_id: doc_20250101, issue_list: [ { section: 第三章 预算说明, issue_type: data_conflict, severity: high, description: 预算总额与细项合计不一致, suggested_action: 核对各分项金额 } ] }, timestamp: 2025-01-01T10:23:00Z }调度器的核心逻辑是一个消息队列加状态机。每个Agent处理完一个任务后把结果消息发送给下一个环节的Agent调度器负责转发、超时判断和失败重试。class Scheduler: def __init__(self, agents: dict): self.agents agents self.queue [] self.status {} def dispatch(self, msg: dict): target msg[to] receiver self.agents.get(target) if not receiver: return self._handle_error(msg) result receiver.process(msg[payload]) self._enqueue_result(target, result)施工时有一件事务必做就是给每个Agent设置最大的执行轮次防止进入死循环。比如审查Agent处理同一文档最多执行3次如果3次后仍无法生成有效问题列表就直接把问题标记为“处理失败”交给人为介入。这个保护机制在开发初期尤其重要因为提示词和工具定义还没调稳模型行为波动很大。3.4 跑通后的效果与迭代方向把四个Agent按“解析→审查→改写→汇总”串起来之后一个最小可用的智能文档审阅系统就成型了。实测效果会比单模型调用稳定很多主要原因是审查环节不再被解析和汇总等任务干扰能专心做规则判断。跑通之后我会建议往三个方向迭代给审查Agent增加规则库自动更新机制把已经确认的问题样本沉淀成新规则。增加“人工复核”环节汇总Agent生成的报告先由审核人员抽查抽查结果反馈到提示词中做批量修正。把文档解析Agent替换成按文档类型分发的子Agent比如合同解析和方案解析分开每个子Agent用更专业的提示词。这套架构的好处是新增一个业务场景不需要重写系统只需要新增Agent和调整调度链路。4. 把细节抠到位提示词、上下文与成本4.1 系统提示词模板与禁忌多Agent的提示词和普通ChatBot提示词很不一样它有硬性的工程约束。我自己总结了一套相对稳定的模板你是{角色名}负责{核心职责}。 工作范围 - 你负责 - 你不负责 输入说明 {约定的输入格式} 输出要求 1. 必须使用JSON格式输出。 2. 必须包含字段{字段列表} 3. 如无相关信息填入null不要编造。 4. 禁止输出与任务无关的说明文字。 执行步骤 1. 先判断输入是否完整。 2. 如需调用工具先调用工具再组织输出。 3. 输出前检查JSON格式是否合法。 当你不确定时 - 宁可不做判断也不要强行给出结论。 - 把不确定项写入“uncertain_items”字段。这套模板的关键作用是把Agent的“自由发挥空间”压缩到最小。Agent本质上是概率模型唯一的控制手段就是约束输出空间。约束越多行为越可控代价是需要花时间调试提示词。我特别想说一个禁忌不要在System Prompt里让Agent“扮演性格”比如“你是一个热情周到的助手”。在多Agent系统里性格化描述只会让模型输出更多冗余话术增加解析成本还会稀释指令的权重。这里不是做聊天产品Agent是流程里的一个工序不是一个人设。4.2 结构化输出解析、校验、重试多Agent系统的输出百分之百要做结构化校验不能信任模型的“格式化承诺”。我遇到最多的情况是模型输出了合法JSON但缺少关键字段或者字段值是错误类型。比如审查Agent应该输出severity字段结果写成了level。处理方式是在调度器层面加一个“输出校验器”。所有Agent的输出都先过校验器校验内容包括JSON合法性、必需字段是否齐全、字段类型是否正确、枚举值是否在允许范围内。校验不过的返回给原Agent重试一次并附上具体报错原因。重试时只需要修改提示词里的“上次错误”不需要清空上下文。def validate_output(raw: str, schema: dict) - tuple[bool, dict]: try: data json.loads(raw) except json.JSONDecodeError: return False, {error: invalid_json} missing [f for f in schema[required] if f not in data] if missing: return False, {error: fmissing_fields: {missing}} return True, data这套校验机制一定要在写业务逻辑之前先搭好因为它决定了下游Agent拿到的数据质量。我见过不少项目因为跳过校验导致错误数据在整个链路里被层层放大最后生成一份看起来正常但处处错误的报告。4.3 上下文预算与记忆压缩多Agent系统的上下文管理比单Agent复杂得多。每个Agent的上下文来源有三个System Prompt、接收到的任务消息、工具返回结果。其中工具返回结果是最容易撑爆窗口的部分。我常用的做法是给每个Agent设定一个“上下文预算分配表”。以审查Agent为例如果模型上下文窗口是8K token预算是System Prompt占1.5K任务消息占2K规则检索结果占2.5K输出缓冲预留2K。超出预算时优先压缩工具返回结果将原始文本替换为摘要。摘要是怎么生成的最省事的方式是让同一个模型在工具返回后做一次“只保留关键信息”的抽取并把抽取结果作为观测内容。这一步看似多花一次调用但能显著降低后续成本因为不需要反复搬运完整长文。实测下来上下文占用的减少比例通常在60%以上。还有一个容易被忽视的点Agent完成当前任务后要把自己的历史上下文状态清空或归档不要让它在下一个任务里继续累积。否则跑了几十轮之后每个Agent的上下文里都堆满了无关历史模型行为会越来越“散”。4.4 成本与延迟模型分层与并行多Agent系统的成本不是“一次模型调用”的成本而是“整条链路所有调用”的成本之和。所以必须做模型分层。我的分层原则是需要推理、规划、决策的环节用强模型纯执行、提取、格式化的环节用轻量模型。还是以文档审阅为例审查Agent需要理解规则并做判断用强模型。解析Agent做文本结构化用轻量模型。汇总Agent只需要把已有结果按模板组装用轻量模型甚至可以用非大模型的代码模板直接完成不需要模型参与。这一点很反直觉但很实用很多Agent的存在是为了“流程接口统一”并不需要每次都真的调用大模型。如果输入满足某种模板条件直接命中规则分支返回结果省掉一次模型调用。我建议大家画一张“调用成本表”记录每个Agent平均消耗的输入输出token数并按照实际占比优化最贵的那两个环节。延迟方面如果多个Agent之间没有依赖关系可以并行执行。比如解析Agent处理不同章节的文本可以拆成多个并行子任务等所有子任务都完成后再交给审查Agent。并行度需要考虑上游API限流建议在调度器里做并发控制别把所有Agent同时间全部铺开跑。5. 高频问题与排查技巧实录5.1 Agent死循环目标没有收敛项多Agent系统最常见的故障就是死循环。现象是Agent A给Agent B发消息B处理完又给A回消息两头来回拉扯始终没有明确的“结束信号”。根因通常是缺少目标收敛判定。解决的方案有三个我会同时用每个任务设置“最大轮数”到达上限直接终止并标记失败。定义“终态消息类型”当汇总Agent判断所有问题已处理完时发送final_result类型消息调度器收到后终止链路。加一个“监督Agent”它的唯一职责是判断任务是否可以结束。它不参与具体业务处理只监控状态避免陷入拉锯。5.2 上下文串扰A看到B不该看的记忆这个问题的表现是审查Agent回答问题时引用了改写Agent的上一步思路导致结论看起来“太超前”。根因是多个Agent共享了同一份上下文副本。排查步骤也很简单翻开每个Agent收到的实际消息内容看看里面是否混入了其他Agent的内部推理。修复方式是在消息协议里增加visibility字段只有公共状态区的内容才能被所有Agent读取私有内容必须显式标记。5.3 工具调用格式抖动模型返回的工具调用参数偶尔会不合法比如漏传必填字段、字段名拼接错误、数组写成字符串。这是概率模型的固有问题无法彻底消除只能降低频率和兜底。兜底方案在工具调用层之前加一个“参数修正器”。它是一个轻量逻辑模块专门负责检查工具参数的合法性遇到缺字段就尝试从原消息里补全补不了就把错误发回给Agent要求重新组织输出。这个模块不需要模型参与纯代码实现但能显著提升工具调用成功率。5.4 角色退化成聊天室多Agent系统用着用着Agent之间的对话会越来越像闲聊输出大量无关内容比如“好的那我来处理下一个部分”。根因是角色指令在长链路里被稀释Agent的“身份感”逐渐丢失。我的对策有两条。一是定期给Agent“重新灌注”System Prompt比如每处理5条消息后在上下文里重新插入一次角色指令。二是让调度器过滤低价值消息如果某条消息文本长度过短且不含结构化字段就直接丢弃不进入Agent上下文。5.5 高频问题速查表现象可能原因处理手段Agent反复调用同一工具工具描述缺少使用边界在描述中补充“不要用于”场景输出JSON格式合法但字段缺失输出协议约束不够增加必需字段校验和重试机制多个Agent互相推诿无结论缺少终止判定增加最大轮数与终态消息回复内容越来越空洞上下文被无关历史填满定期清空历史或做摘要压缩强模型成本过高所有环节都用同一模型按职责拆分轻量模型这张表基本覆盖了多Agent开发初期遇到的绝大多数问题。系统的稳定性不是一次调好的而是通过持续“发现问题→定位根因→修改提示词/调度逻辑”滚出来的。我在实际项目里最大的体会是多Agent系统的核心挑战从来不是“让模型开会”而是“让流程收敛”。Agent越多协作红利越大崩溃点也越多。所以每加一个Agent之前先问自己一个问题这一环能不能用工具、模板或规则来代替如果答案是可以那就不要引入Agent。少一个Agent就少一份失控的可能。另一个很有用的经验是日志里一定要记录每个Agent的输入和输出完整快照。多Agent系统的bug非常难复现问题出现时如果没有日志基本只能靠猜。有了快照排查效率会高出一个数量级。如果你正准备上手这类系统我的建议是先用最简单的三个Agent把一个业务场景跑通不要一开始就铺十个角色。先把通信协议、消息格式、上下文隔离这些底层骨架打磨稳再往上面加复杂度。骨架稳了加角色就是复制粘贴的事骨架不稳角色越多崩得越快。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑