做多智能体快两年了,从最早拿 LangChain 写 demo 玩,到后来真刀真枪在公司业务里落地,这中间踩过的坑、推倒重来的设计,估计能写一本小册子。最近刚把一套沉淀下来的工程化方案整理完,正好趁这个机会从需求拆解到上线部署,把完整的思考链路和能直接抄作业的细节都摊开聊聊。这篇文章不聊花哨的概念,只讲怎么把一个模糊的“我们要做个智能体系统”变成线上稳定跑的工程。
1. 接手项目后的第一件事:不是写代码,而是拆需求
很多团队犯的第一个错误,是把“多智能体”当成一个炫技的技术标签,上来就画出一堆 Agent 拓扑图。但工程化的核心永远是:先搞清楚这一个系统到底要解决谁的什么问题。我拿到需求时习惯先问四个问题:这个场景单一模型能不能解决?如果能,为什么非要多智能体架构?任务拆解之后,哪些环节确实需要独立的策略或上下文隔离?整个流程的可失败边界在哪?
以我最近做的模拟项目X为例,业务方最初的需求是“做一个智能客服,能处理售前咨询、售后跟进、投诉安抚和数据分析”。这种描述如果直接丢给大模型,你得到的只是一个自带人设的聊天机器人,而不是一个可靠业务系统。所以第一轮拆解很重要,我把原始需求拆成了三个层面:
- 任务层:接待、问答、解决方案推荐、工单记录、数据汇总,每个任务有独立的输入输出协议。
- 决策层:判断用户意图属于哪条垂直线,需要调取哪些工具,是否需要转人工。
- 执行层:对接订单系统、知识库、CRM 接口,把大模型生成的结论转换成实际业务动作。
这个拆分决定了整个系统的边界。一个多智能体系统最忌讳的就是职责混乱:所有 Agent 共享一套提示词,共享一个上下文窗口,最后表现出来就是每个 Agent 都半吊子,互相干扰。我当时定下的原则是:每个子 Agent 只做一件明确的事,上下文相互隔离,上层统一调度。这种设计可能在一开始看起来不够“聪明”,但对线上系统来说,可维护性和可观测性远比炫技重要。
另一个拆需求的关键是识别出那些本质上不适合智能体去做的环节。比如订单状态的实时查询,这应该是接口调用,而不是让 Agent 自由发挥,因为 Agent 一旦去猜订单状态,错误概率就会拉高。只有在无法调用接口,或者需要综合多源信息做判断的场景,才值得让 Agent 介入。这个边界划分得越清晰,后续开发越省心。
需求拆解的产出不应该只是一堆文档,而是场景-流程-数据-接口四张表。场景表描述每个用户意图对应的完整链路;流程表描述每一步的触发条件、输入输出、超时兜底;数据表定义上下文流转的数据结构;接口表列清楚每个 Agent 可能调用的外部服务。这四张表搭起来,才算是从“模糊需求”跨到了“可实施方案”。
2. 架构选型的取舍:为什么不是每个团队都适合上多智能体
我见过不少团队,在单 Agent 都还跑不稳的情况下,就急吼吼地上 Multi-Agent 框架。结果系统复杂度和错误率跟着一起起飞。这里必须先泼盆冷水:多智能体的本质是把复杂决策拆分成多个可控环节,而不是把简单问题复杂化。如果场景只需要一次大模型调用加一个工具函数,老老实实用单 Agent 加工作流引擎就够,硬拆成三个 Agent 只会徒增延迟和出错的概率。
那什么样的场景真正值得上多智能体?我自己归纳出三个硬指标:第一,任务涉及多个知识域,比如售前问答和售后投诉处理,知识库差异明显,放一个上下文里互相污染;第二,需要不同粒度的策略控制,比如权限、敏感词过滤、对话风格隔离,设计上最好物理隔离;第三,流程有明确的分工结构,比如先规划再执行再审查,这个链路本身就是多角色协作模型。缺了这三条,上多智能体基本是自找麻烦。
选型明确的第二个维度是技术栈选择。去年我做过一轮相对系统的对比,当时市面上主流的候选有成熟的编排框架、基于状态图的建模框架、自研代理解耦方案,以及最原始的通过消息队列自己拼多角色。比较下来的结论是:如果你团队能接受系统复杂度,首选状态图框架,因为它在流程控制上表达力最强,适合业务规则相对确定的场景;如果你更看重快速迭代和生态工具链,编排框架上手快,但对复杂状态的表达能力弱一些;如果是搞研究,怎么都行;如果最终要上生产,建议不要用完全自研的方案,调试成本远超预期。
此外还需要考虑部署形态。多智能体不只是代码问题,还牵扯到算力分配和依赖管理。比如一些 Agent 需要 GPU 推理,另一些只是做文本分类或格式整理,用 CPU 就足够。部署时把它们混在一个服务里,资源会被次线性利用。我后来是拆成独立的服务模块,按调用量分配副本数,吞吐立刻上来了。
架构评审的时候,我习惯画三张图。第一张是链路图,描述从入口到出口的全流程,包括分支、循环和终止条件;第二张是上下文拓扑图,标清每条消息在哪几个 Agent 之间流转,什么字段被读取、什么字段被写入;第三张是容错图,标注每个节点失败后的降级路径和兜底策略。三张图齐了,才说明这个架构是真想清楚了,而不是画个拓扑糊弄人。
3. 核心开发的关键:上下文隔离、工具封装与编排策略
这一节是全文实操含量最高的部分,我会从代码层面把关键的几个设计决策讲透。
3.1 上下文设计:隔离是硬边界,共享要显示声明
多智能体系统最常见的崩溃原因,是上下文串了。A Agent 产出的中间结果被 B Agent 当成了用户输入,或者历史会话里无关的信息干扰了当前决策。解决这个问题的思路并不复杂,我把上下文分成三类:
- 会话原始上下文:用户的每一次原始输入,这个保留给路由层做意图判断。
- 工作上下文:每个子 Agent 执行过程中的输入输出,只对当前执行链路可见。
- 全局状态:需要跨 Agent 共享的业务数据,比如订单 ID、用户等级、处理进度,这些用显式的状态对象存储,不允许 Agent 私自读写。
用代码来表示就是:每个 Agent 的输入是结构化的数据对象,不是一大段聊天文本。比如售前 Agent 收到的内容是“用户在咨询某商品的价格和库存状态”,而不是“请根据以下对话判断用户想干什么”。这样设计之后,模型接收到的是结构化任务描述,跑偏的概率大幅下降,后续的评估和日志排查也有明确的字段可以对齐。
我在项目里定义了一个统一的事件格式,类似后端开发里的消息体:
class AgentMessage: msg_id: str agent_from: str agent_to: str payload: dict context_ref: str # 指向全局状态对象 timeout_ms: int每个 Agent 处理完消息后只输出新的 AgentMessage 或者结束信号,不允许直接修改全局状态。全局状态的变更由一个专门的 StateManager 统一管理,这相当于给系统加了事务性,逻辑越复杂,收益越明显。
3.2 工具/API 封装:别让大模型直接决定一切
很多教程会让大模型自己选工具,然后调函数。这在 demo 里没问题,但生产环境必须做工具准入机制:哪些工具对哪个 Agent 可见,是需要在配置文件里显式声明的。不允许 Agent 调用清单之外的任何函数,尤其涉及订单查询、退款操作这类有真实副作用的能力。
我给模拟项目X 设计了一套工具注册体系,代码大致长这样:
class ToolRegistry: def __init__(self): self._tools = {} def register(self, agent_id, func, schema, critical=False): self._tools.setdefault(agent_id, []).append({ "func": func, "schema": schema, "critical": critical }) def available_tools(self, agent_id): return [t["schema"] for t in self._tools.get(agent_id, [])] def execute(self, agent_id, tool_name, args): for t in self._tools.get(agent_id, []): if t["schema"]["name"] == tool_name: if t["critical"]: return self._execute_with_audit(t["func"], args) return t["func"](**args) raise ToolNotAllowed(...)一个细节值得注意:凡是涉及用户资金、订单状态变更、对外发送消息的工具,必须标记为 critical,调用时要走审计日志,而且关键动作的结果要回传给上层做二次确认,不能由 Agent 自己拍板到底执行不执行。这个设计帮我避免过至少三次线上事故,类似“Agent 自作主张给用户发了错误补偿”这种情况,在开放工具权限的架构里太容易发生了。
3.3 编排策略:固定流程为主,动态规划为辅
多智能体的编排策略,业内常见的就两类:一类是预先定义一个标准作业流程,按图执行;另一类是让一个 Planner Agent 自己拆解步骤,动态规划。每当我看到有人把动态规划作为默认策略时,都会劝他把退路先想好。动态规划的问题在于不可预测:你无法保证 Planner 在每次复杂度变化时都能走出合理的步骤,这在有严格 SLA 的业务里是灾难。
我的建议是混合编排:主链路用固定流程,保证 90% 的常规路径稳定可控;只在少数需要发散的场景里,才允许绘图 Agent 做动态规划。例如模拟项目X 的投诉处理链路,正常情况下走标准工单流程;只有当用户情绪激烈程度超过某个阈值时,才启动安抚引导分支,由专门的 Agent 来动态组织话术。这样既保留灵活性,又控制住失控面。
实现上,我一直用语言化描述来定义状态流转,逻辑清晰且可读性高,有团队成员接手时不用靠猜。核心思路是每个节点是条件映射,而不是硬编码跳转。比如:
ROUTING_RULES = { "start": lambda msg: "attribution_agent" if msg.need_type_check else "qa_agent", "attribution_agent": lambda msg: "after_sales_agent" if msg.intent == "after_sale" else "sales_agent", "after_sales_agent": lambda msg: "refund_agent" if msg.need_refund else "human_service", }这种语言化配置的好处是:第一,不用重新部署整个系统就能调整路由;第二,可以可视化地做流程审查,团队成员能快速理解每一步在干什么;第三,链路执行完之后,每一步的跳转原因都留在了日志里,排查问题时极其有用。
3.4 Prompt 工程要看重边界
多智能体的 Prompt 设计,和单 Agent 是完全不同的思路。单 Agent 的 Prompt 追求上下文融合和信息完备性,而多智能体里的子 Agent Prompt 最在乎的是边界遵守:明确告诉模型你只管什么、什么情况必须上报、哪些缩写和推断是禁止的。我每个子 Agent 的 Prompt 都固定包含四块内容:角色目标、输入数据协议、输出格式约束、红线与上报条件。
红线与上报条件多重要,举个例子就清楚了:售后 Agent 如果发现用户要求赔偿金额超出权限,它不应该自行拒绝或者答应用户,而是直接触发升级流程。这种规则写在 Prompt 里比写在逻辑代码里效率高太多。因为边界本来就有模糊性,硬编码很难覆盖所有表达方式,而模型正好擅长做这种模糊匹配。
另一个经验是,在子 Agent 的 Prompt 里尽量不给历史聊天对话,只给数据提取后的最终结果。比如一个“订单查询 Agent”,输入是 JSON 格式的订单号和查询意图,输出是标准格式的查询结果,不需要知道用户说过什么。这样 Prompt 大大的缩短,模型的响应速度和稳定性都会提升,费用也会低一些。
4. 落地部署与压测调优:不把问题留到夜间上线后
开发侧工作完成之后,真正的考验才开始。我把这个阶段分成四步:模拟环境联调、压测与性能摸底、发布策略设计、监控报警体系建设。
4.1 模拟环境联调:先把接口都 Mock 掉
多智能体系统本身的抽象是模型调用,但它的不确定性来自外部依赖:知识库、订单系统、消息推送。联调的第一步,是把外部系统全部 Mock 成可控行为的数据源,干扰项先剔除掉。Mock 数据要覆盖正常结果、空结果、超时、返回异常等类型,重点验证编排层在外部系统各种表现下的路由决策。
这一步很容易被省略。尤其是多 Agent 本身的日志又比较乱,很多人图省事直接连真实接口测。但真实接口的不稳定会让定位问题的成本翻倍。我们当时模拟项目X 联调时,专门搭了一个 Mock 服务,把十几个接口全部虚拟化,数据源造假造得相当细致,并内置了各个异常分支的开关,测试效率因此高了很多。
4.2 压测与性能摸底:关键指标是 P50 和 P95 延迟
所有单测通过后,就进入压测。多智能体压测有两个天然难点:调用链路长,外部依赖多。我在压测时重点关注三组数据:链路端到端延迟的 P50 和 P95、每个子 Agent 节点的单独耗时、以及各种工具调用的耗时分布。收集这些数据的意义是找出真正的瓶颈所在。
就拿模拟项目X 的排查经历来说:压测结果当时端到端 P95 延迟达标,但 P50 表现异常,后来一查才发现原因是某个知识库接口在部分时段偶发慢查询。如果只看平均延迟,这种人容易漏掉的偶发问题根本发现不了,到线上爆发就被动了。按节点拆解的做法,是快速定位复杂系统性能问题的最有效手段,强烈建议建立指标看板,除了常规观测指标,还要专门盯每个环节的调用耗时。
4.3 发布策略:多智能体不要搞一键全量发布
多智能体的一个隐藏风险是:多个 Agent 之间可能存在隐性的依赖关系,比如 A Agent 的输出格式被 B Agent 的输入协议隐式依赖。这种情况最怕全量发布,一个小改动导致全系统崩掉,类似连锁反应。
我们的发布策略是灰度和链路级开关。每一个 Agent 的新版本先只在 5% 的流量上跑,并对比新旧版本在完成任务率、回退率、延迟指标上的差异。但这里有个关键设计:给每个 Agent 配上独立的版本开关,这样即使整个系统是同一个流程编排,也能做到某一个环节单独灰度,其他环节保持不变。
网关层做流量染色也很重要,按用户 ID、会话 ID 或者其他标签把流量切分到不同版本链路上。观测到新版本超时时可以立刻切回旧版本,而不是慌乱地回滚整个系统。这种精细控制,在多人协作的多智能体系统里几乎可以说必需品。
4.4 监控报警:要留审计日志,别只依赖云厂商自带监控
很多系统上线前不看审计,这点特别要提醒:多智能体系统一定要有独立于模型厂商之外的日志体系。因为模型厂商的日志经常查不到 prompt 里业务字段的明细,比如当时用户选了哪个商品,Agent 调用了哪一步。自建日志要记录三层内容:会话层日志、决策轨迹和审计明细。
决策轨迹指的是记录路由判断、各个子 Agent 的输入输出摘要、工具的调用参数和结果。这个设置既能在线上出问题时做时间旅行回放,又能帮助后续提炼评估集。有一次线上收到用户投诉说系统乱承诺,如果当时没有决策轨迹日志,整个过程就很难追溯还原。后来通过日志逐条回看了决策路径,很快就定位到是某一个配置工具的 prompt 边界写得模糊所致,半天内就修掉了。
报警规则上,这是另一种思路,不要只设置响应时间或错误率的指标。多智能体最容易出问题的是**“任务未完成”**——链路跑了但最终没产出结果,而表面上没有任何错误码。所以一定要设置一个专门报警:链路的完成率,包括成功走到终态的比例以及回退比例,这两个指标能够第一时间暴露系统功能的“软性失败”。
5. 常见问题与避坑实录
挑几个我们上线后反馈最集中的问题整理成表格,后面再展开几个特别有共性的细节。
| 问题 | 典型表现 | 解决办法 |
|---|---|---|
| 上下文污染 | 子 Agent 答非所问,混入上一轮闲聊内容 | 上下文隔离,只传结构化数据 |
| 工具滥用 | Agent 调用不在权限内的操作 | 工具准入清单 + critical 审计 |
| 超时累积 | 外部依赖慢,导致端到端超时 | 每个子 Agent 独立超时,熔断降级 |
| 输出格式漂移 | 模型偶尔输出非 JSON 导致链路断掉 | 强制结构化输出,格式纠错重试 |
| 灰度影响面失控 | 一个 Agent 的 bug 影响全链路 | 链路级开关,按 Agent 独立灰度 |
5.1 为什么明明设置了超时,系统还是全链路卡死
这个坑大概率是子 Agent 的超时时间设置得比外部依赖的调用超时还短。A Agent 调 B Agent 的接口,B 内部又调了外部 API,B 对外部 API 忍耐时间很长,A 对 B 的忍耐时间却很短,结果就是 A 疯狂重试,B 还是慢吞吞地跑,最后 A 被打爆。
解决思路是超时时间必须按照调用链从外到内逐级递减。比如外部 API 设置为 5 秒,内部 Agent 调用设置为 4 秒,上层编排节点设置为 3 秒。同时要限制重试次数,防止请求在 Agent 之间打乒乓球。多智能体系统里,重试风暴的危险程度远高于单机系统,因为一个请求可能触发多个 Agent 连环重试。
5.2 模型输出不规范导致的“幽灵 bug”
我用过好几家不同的大模型,即便各家都声称支持结构化输出,实测也偶尔会跑出格式异常,可能是多了一个字段,也可能是 JSON 截断。这种问题在单 Agent 里修复成本低,在多智能体里会顺着链路散播,做一个 Agent 的显示字段错误,可能因此传染给所有下游节点。
所以我在设计每个子 Agent 节点的时候,都会加一个格式校正层。模型输出先经过一个轻量级校验器,不符合协议就触发一次重试;重试失败就走兜底逻辑,而不是把异常结果发给下游。兜底逻辑的配置很灵活——可以用上一次的正常结果,可以用模板答案,也可以直接把链路标记为失败并转人工。反正原则就一个:不符合协议的数据永远不允许下沉到下一环。
5.3 上线前别疏忽“冷启动测试”
冷启动对于依赖知识库召回的 Agent 来说,是另一个重灾区。特别是知识库索引更新时,如果某个子 Agent 依赖刚写入还未生效的数据,结果就会和线上不一致。做系统设计时一定要明确数据一致性的边界:哪些知识允许最终一致,哪些必须强一致。
还有一种冷启动发生在会话场景里,新用户没有任何历史上下文,所有 Agent 都拿不到必要的字段,这时很容易出现流程空转。我在各个子 Agent 的输入协议里都设置了必填字段检查,缺了关键字段直接触发补全会话流程,而不是让 Agent 硬猜,有效避免了很多没意义的空转。
6. 这套方案后续还能怎么扩展
这套工程化方案目前帮我撑起了模拟项目X 的完整业务流程,包括售前、售后、投诉和数据汇总四条线,全部是独立开发、统一编排、灰度发布。后续如果要继续扩展,我自己的思路是这样的:针对不同业务模块形成标准技能包,包括 Prompt 集合、工具注册、评估集和监控面板,方便新业务快速装配;把链路执行轨迹沉淀成评估数据,定期评测各子 Agent 的效果;最后,把人工审核的流程和 Agent 的自动决策串成一个半自动闭环,尤其在售后赔偿、豁免这类敏感操作上,保留人工兜底。
前面这些经验,本质是从“能跑通的 demo”向“能运营的系统”过渡时会遇到的一系列问题。如果在方案设计之初就开始有意识地做上下文隔离、工具准入、链路开关和审计日志这几件事,后续踩坑的概率会小很多。我自己最大的体会是:多智能体的难点早就不是让 Agent 回答得聪明,而是让整个系统在复杂链路中仍然可预测、可排查、可控制。把这三点想透,再复杂的项目也会有大致的稳妥解法。