
多智能体协作系统听着很宏大但真正在在线环境里跑过一遍就会发现最难的从来不是让模型“聪明”而是让多个智能体在同一个复杂流程里不出乱子。我之前匆匆把带工具的Agent暴露成API结果一个看似简单的对话任务模型自己把重试逻辑玩成了死循环同一份数据被写入多次最后连日志都要靠猜。那次之后我把重点从“提示词工程”挪到了“工作流工程”。把“在线部署多智能体协作系统管理复杂工作流打造下一代对话式AI”落地成可运行的系统关键改变只有一条多智能体做决策工作流管执行。决策层负责理解用户意图、拆解子任务、判断调用哪个工具执行层则用一份显式的工作流定义把每一步的输入输出、超时、重试、分支都固定下来。我的目标是让一个对话式AI入口能够承担简历筛选、工单分派、通知触达这类真实业务而不只是停留在“聊得起来”的层面。这篇文章没有什么学术论证只有我最近从零搭建、部署、排坑的完整记录适合正在做Agent应用、又担心模型失控的朋友参考。1. 多智能体协作系统从“单机对话”到“流水线大脑”1.1 为什么单个大模型搞不定复杂任务早期我做POC一个Agent配一个长提示词看起来什么都能聊。可真让它处理“先搜索简历库、再按岗位要求筛选、最后把结果通知给HR”这种多步骤任务时问题立刻暴露要么漏掉中间环节要么自作主张把未确认的信息直接写进库要么在一个错误答案上反复兜圈子。原因是单模型本质上在做“下一个词预测”它对记忆、外部工具调用和分支状态的把握都非常有限。你把十步操作全塞进一个上下文里它一定会丢三落四。生活里很好理解再厉害的全能选手也扛不住同时当好几个人用。一个写文案的人又要查数据、又要做校对、又要管排版多半会翻车。多智能体协作系统把任务拆分给不同角色一个智能体负责拆解意图一个智能体负责搜索一个智能体负责审核一个智能体负责输出。每个智能体只干一件事配合一个外部工作流引擎把环节串起来整个系统的可靠程度会立刻上一个台阶。在线部署场景下还有个更现实的问题单个大模型的回答不幂等。如果你让模型“自己去执行整个流程”下次同样的输入可能会走完全不同的路径。而多智能体加工作流的方式能把大多数路径固定下来模型只在几个关键决策点做选择其他环节都是确定性逻辑。这样一来业务链路的完整性就不再依赖模型的临场发挥而是依赖流程定义本身。1.2 多智能体的核心组成与协作模式一套完整的多智能体协作系统被我拆成五块编排器决定当前轮到哪个智能体执行收集执行结果判断是否继续还是结束。执行智能体真正干活的角色各自有独立提示词、工具白名单和输出格式。共享状态库存放中间结果通常是一个JSON结构或者数据库记录所有节点都能读取和写入。工具适配层封装对搜索、数据库、消息通知等外部系统的调用让智能体只和统一接口对话。守卫模块负责校验输出、检查超时、判断是否需要人工介入。协作模式我也试过两种。一种是“自由讨论式”多个智能体互相发消息谁有问题谁就抛出来看起来灵活但在线环境一乱起来就非常难查。另一种是“集中编排式”所有子智能体都向编排器汇报编排器严格按照工作流推进。我现在只用集中编排式因为生产环境里你需要知道每一步是谁干的、花了多少钱、产出了什么。自由讨论适合研究论文不适合需要稳定交付的业务系统。这里有个容易忽略的点编排器本身不要放太多聪明逻辑。它只负责按图索骥不在执行中途临时发明新节点。如果某个分支需要复杂的判断把判断下沉到一个专门的LLM节点里输出固定格式的结果再由编排器读取这个结果做路由。看似多了一段实际上让错误范围小了很多。1.3 与工作流引擎的关系用流程管控代替模型自由发挥多智能体和传统工作流引擎听起来像两个世界其实是一对搭档。工作流引擎负责“确定性流程”例如状态机、人工审批、条件分支、超时控制多智能体负责“非确定性决策”例如理解自然语言、抽取信息、判断意图。两者结合正好把AI能做的事和不能做的事切得清清楚楚。我接触过的Camunda、Flowable这类开源工作流引擎擅长处理审批流和状态流转但在AI节点上要自己写扩展。Coze、Dify这类AI工作流平台则把LLM调用、工具调用、条件判断做成了可视化节点上手很快适合MVP。n8n更偏通用连接器适合把多个外部系统串起来。它们的共同点都是让你不要把整个流程的走向全部交给模型自行发挥。我的经验是只要流程中有一个环节必须调用外部API、必须写数据库、必须走人工审核都值得把这部分画进工作流而不是写在模型提示词里。模型擅长的是“生成内容”和“做出选择”不擅长的是“保证每次操作都准确执行”。在线部署时工作流就是你的安全网它能把一次失误造成的损失限制在单个节点内而不是让模型连错一整套链路。2. 工作流设计让复杂业务可编排、可复用2.1 工作流中的节点类型与数据流转把工作流想成一条生产线每个节点就是一个工位。工位和工位之间传递的是一张流转单在这个场景里叫上下文对象。我通常要求所有节点只读取自己声明的输入字段也只写入自己负责的输出字段不允许乱改别的节点数据。这种约束一开始多花十分钟后面排查问题能省十个小时。常见的节点类型就几种掌握了它们就能应付绝大多数业务节点类型主要作用我常用的关键参数LLM节点处理自然语言、生成结构化输出model、prompt、输出schema工具节点调用外部API、数据库、搜索引擎endpoint、超时、鉴权方式条件节点按结果分流source_key、cases、default循环节点对列表逐项处理max_iter、break_key并行节点同时执行多条分支branch_map、merge_mode人工审批节点暂停流程等待确认timeout、callback接口数据流转的核心是上下文对象。我倾向用一个带命名空间的状态字段比如context[intent]、context[resume][skills]。这样做的好处是即使并行节点同时执行也不会互相覆盖数据。很多在线部署翻车都是因为多个Agent同时往同一个字段写内容最后谁先谁后根本说不清。分配字段就是把各自的“抽屉”隔离好。2.2 把业务需求拆成可编排节点的四个步骤把一段业务需求变成可执行的工作流我习惯按四个步骤拆。第一步切分职责。把所有动作列出来区分“需要模型理解的”和“不需要模型理解的”。比如简历筛选里“读取附件内容”是纯程序动作“判断候选人是否匹配岗位”是模型动作。切分越干净后续越不容易出错。第二步画出依赖图。先做哪些、能不能并行。简历解析必须在技能提取之前这是顺序依赖技能提取和学校评分可以并行因为互不依赖。依赖图画清楚后工作流的结构基本就定了。第三步定失败策略。每个节点都要回答失败后重试几次、超时多久、失败后走兜底流程还是直接终止。比如外部简历解析API经常超时我就设置两次重试、单次超时10秒失败后走人工上传渠道。第四步加守卫。所有LLM输出必须做格式校验不满足就重新生成一次总步骤数设置上限防止死循环关键写库操作前加人工确认节点。这套守卫加完后系统才敢从本地测试环境搬到公网部署。2.3 可视化编排 vs 代码定义怎么选在线部署多智能体你首先会遇到一个选择用可视化平台点鼠标搭流程还是直接用代码定义工作流。两者我都用过各有各的适用场景。方案代表工具优点局限可视化编排Coze、Dify、n8n上手快、协作直观、内置大量连接器复杂分支容易乱版本管理较难自托管扩展受限代码定义LangGraph、CrewAI、自定义引擎逻辑可控、可调试、可写单测学习成本高上手周期长我的建议很简单先画图再决定。业务逻辑不复杂你可以直接选Coze或Dify这类平台几十个节点就能上线很适合快速验证一个对话式AI项目。等业务复杂度上来需要细粒度控制重试、并发、字段权限时再用代码定义迁移一次。实际上我曾经把一个Coze上的动画工作流拆到自研引擎就是因为平台里密密麻麻的连线已经没人能看懂了。代码定义看起来费劲但对在线部署其实更友好。你可以把工作流定义成YAML文件放进Git仓库每次改动都有评审记录可以写单测来验证分支逻辑还能方便地导出成API服务。相比在可视化平台里小心翼翼拖拽连线代码方案在生产环境里的可维护性高出不少。3. 在线部署实操把多智能体系统真正跑起来3.1 部署架构与服务拆分在线部署不等于把脚本扔到云服务器上。我跑通后的架构大致分四层用户请求先到API网关网关把消息写入队列编排器从队列拉取请求解析出工作流定义并开始调度执行智能体从编排器接收节点任务调用外部工具把结果写回状态库整个过程的状态和日志落入数据库。这四层分开部署避免一个节点卡死拖垮整个服务。为什么要把编排器从同步请求链路里摘出来因为一个长时间工作流很可能要好几分钟才能跑完用户不可能一直挂着一个HTTP连接等待。你把请求先收下来返回一个task_id让用户通过轮询或前端页面看进度体验会好很多。这就跟点外卖一样订单先受理后厨做完再通知你取餐而不是让你盯着一口锅。实际部署时API网关后面我再挂了两个独立的WorkPod一个跑轻量模型节点处理意图识别和分类一个跑重模型节点处理长文书生成和复杂推理。两个服务可以独立扩容成本也能分开统计。Redis用来做队列和状态缓存Postgres存最终结果和审计日志。这样的结构看起来多花了几台机器但后续加并发、加节点都非常容易。3.2 容器化启动与基础配置我这次部署选择了容器化方案原因很简单本地一套配置线上另一套配置这中间的坑能用容器抹平大部分。以下是简化的docker-compose配置你可以直接参考version: 3.8 services: api: build: ./api ports: - 8080:8080 environment: DATABASE_URL: postgresql://workflow:workflowpostgres:5432/workflow REDIS_URL: redis://redis:6379/0 LLM_BASE_URL: ${LLM_BASE_URL} LLM_API_KEY: ${LLM_API_KEY} WORKFLOW_PATH: /config/workflows/resume_review.yaml depends_on: - redis - postgres orchestrator: build: ./orchestrator environment: DATABASE_URL: postgresql://workflow:workflowpostgres:5432/workflow REDIS_URL: redis://redis:6379/0 CONFIG_PATH: /config/config.yaml depends_on: - redis - postgres worker_light: build: ./worker environment: MODEL_PROFILE: light LLM_BASE_URL: ${LLM_BASE_URL} LLM_API_KEY: ${LLM_API_KEY} depends_on: - orchestrator worker_heavy: build: ./worker environment: MODEL_PROFILE: heavy LLM_BASE_URL: ${LLM_BASE_URL} LLM_API_KEY: ${LLM_API_KEY} depends_on: - orchestrator redis: image: redis:7-alpine volumes: - redis_data:/data postgres: image: postgres:15-alpine environment: POSTGRES_USER: workflow POSTGRES_PASSWORD: workflow POSTGRES_DB: workflow volumes: - pg_data:/var/lib/postgresql/data volumes: redis_data: pg_data:启动就三步。先把环境变量填好把模型服务地址和密钥放进.env文件然后执行docker compose build最后执行docker compose up -d并检查健康接口curl http://localhost:8080/health。到这里一个最基本的在线部署骨架就起来了。这里要特别提醒环境变量里的密钥不要写进镜像也不要提交到Git仓库。你可以用.env文件也可以在容器编排平台里单独配置Secret。我见过有人把密钥直接写在docker-compose里推到公开仓库十分钟后就被人扫出来薅走了额度这个坑踩一次就够长了。3.3 一个最小可用的对话式AI工作流实例空谈架构没法落地我拿一个“对话式简历筛选”工作流做例子。这个工作流经常被大家复制因为它链条短、又完整覆盖了意图识别、路由、抽取、判断、通知五个核心环节。我的工作流定义大致长这样name: resume_review timeout: 120 nodes: - id: intent type: llm model: gpt-4o-mini prompt: | 判断用户消息意图只输出 JSON {intent: resume_review | order_query | chitchat} output_schema: intent: string output_key: intent - id: route type: switch source_key: intent.intent cases: resume_review: - resume_extract order_query: - order_query_reply chitchat: - chitchat_reply - id: resume_extract type: llm model: gpt-4o-mini prompt: | 从用户提供的简历文本中提取信息输出 JSON {name: string, skills: list, years: number} output_schema: name: string skills: list years: number output_key: resume_info - id: resume_score type: llm model: gpt-4o prompt: | 根据 resume_info 中的内容判断是否匹配“Python 5年以上经验” 输出 JSON{match: true|false, reason: string} output_key: resume_score - id: notify type: tool tool: http.post url: https://your-system/api/notify request: message: 匹配结果{{ resume_score.match }}理由{{ resume_score.reason }} condition: resume_score.match true这个流程在线上跑的路径是用户发一段文字到对话式AI入口意图识别节点先把意图拆出来如果识别成“简历筛选”工作流自动进入提取和评分环节评分符合要求才会调通知API。整个流程中模型只负责判断和抽取路由、失败重试、条件触发都是由工作流引擎控制的推理过程完成的。调用入口也很简单一个POST请求就完成了curl -X POST http://localhost:8080/api/v1/chat \ -H Content-Type: application/json \ -d {message: 请帮我筛选一份简历候选人要求有五年以上Python经验}返回里会带着task_id前端拿着task_id轮询进度工作流结束后再拉取完整结果。从部署角度看这个结构让我可以在不修改业务代码的情况下随时调整某个节点的模型型号或提示词改完重启编排器就能生效。对在线系统来说这种可配置性极其重要因为你不可能每次调整都发一次版。3.4 从 MVP 到生产扩容、监控和成本控制MVP跑通后紧接着要面对三个问题并发涨了怎么办、出问题怎么看、账单怎么控。我逐一处理。并发方面我把编排器和执行Worker都做成了无状态服务状态全部放Redis和数据库所以扩容就是多加几个副本前面加一层负载均衡。实际生产里我用Redis Streams做任务队列多个Worker同时消费同一个队列天然就能水平扩展。这里有个细节必须注意每个节点都要设计成至少一次执行所以下游接口必须支持幂等。否则同一份简历通知发两次HR那边就要抓狂了。监控方面我把所有日志按request_id和node_id两个维度打标每个节点开始和结束时都写一条结构化日志。这样一来在日志系统里按request_id一搜整条工作流从头到尾每个节点干了什么一目了然。除了日志我还会上报节点耗时、token消耗、失败次数三个指标到监控面板。没有这套监控在线排障基本就是瞎猜。成本控制是我踩过最疼的坑。在线部署后每天都有真实流量进来token消耗很快。我现在用的策略是意图识别和字段抽取全部走轻量模型只有生成最终判断和长文回复时才上调到重量模型。再加上LLM节点的结果缓存——相同输入直接返回历史结果不重复调用模型。这几招下来月成本能砍掉一半以上。4. 常见问题与排查技巧4.1 模型自由发挥导致的状态丢失最常见的问题是模型输出不稳定导致后续节点拿不到正确字段。比如我把意图识别节点的输出定义成一个JSON对象但模型偶尔会把JSON包在Markdown代码块里导致解析失败。后来我给所有LLM节点都加了输出校验解析失败就重试一次再不行就转人工兜底。还有个更隐蔽的状态丢失多个执行智能体并行工作时同时往上下文里写同一个key造成互相覆盖。我解决的方案是强制每个节点声明输出key并且放在独立命名空间下并行分支只允许往各自的子对象里写数据。配合状态版本记录即使在问题发生之后我还能从历史快照里把当时的数据结构找出来。总的来说排查状态问题有一个固定套路先看共享状态库里的快照确认哪一步数据就变了再看日志里对应的节点输出确认是不是模型生成的内容有偏差最后看工作流定义确认是不是路由配错了。按这个顺序查大部分问题都能定位到具体节点而不是在整条流程里大海捞针。4.2 工具调用失败与节点超时在线部署后外部API不可能一直可用。搜索接口偶尔500数据库偶尔连接超时消息推送偶尔丢包。这些失败如果做得不够好整个工作流都会被卡住。我给每个外部工具调用都设置了超时和重试超时默认10秒重试两次重试之间用指数退避。连续失败就进入兜底分支或者直接通知管理员介入。另一个常见问题是模型把工具参数生成错了。比如它调用了不存在的接口方法或者把必要字段漏了。所以工具适配层在把请求发出去之前我会用一份JSON Schema校验工具入参格式不对就把它返回给模型重新生成。不要小看这一层校验它能拦截掉大量无效请求节省很多成本。排查工具故障时先把request_id对应的工具调用日志单独拎出来看。日志里记录了调用参数、返回码、耗时、重试次数。如果连续调用都失败先确认是那个外部服务本身挂了还是我们的入参有问题。这个区分非常关键因为前者需要做故障转移后者需要改提示词或工具定义。4.3 令牌成本失控与响应变慢多智能体系统比单个对话模型费钱得多因为每个节点都会调用一次模型。上线第一周我盯着账单发现很大一部分花费在重复调用上同一个用户的重复请求、同一份简历被反复提取、同一个提示词的多次重试。优化方向就是减少浪费。第一条路是缓存。对纯分类、提取类节点如果输入相同且模型参数一致直接命中缓存不再调用底层模型。第二条路是模型分级。小任务用小模型大任务用大模型不要让一个超强模型去做“识别意图”这种简单活。第三条路是剪枝。工作流里加更多确定性工具节点能不用LLM判断的就不让LLM参与比如“是否匹配”这种逻辑可以先用规则筛掉一批再交给模型复核。响应变慢通常和长上下文有关。如果每个节点都把全部历史记录塞给模型token越长生成越慢。我的做法是只传当前节点需要的字段不回传完整上下文。比如意图节点只需要最近一条用户消息评分节点只需要结构化提取结果。这个优化既能提速也让成本直线下降。4.4 避坑清单在线部署多智能体的几条经验最后整理几条硬经验每一条都是用真金白银换来的。第一别把易变业务逻辑写进提示词。判断条件、规则开关、费率标准这类东西应该放在工作流配置或者规则引擎里。写在提示词里改一次发一次版还容易让模型自由发挥。第二别让Agent直接访问所有工具。给每个执行智能体一个工具白名单只开放它能用的减少破坏半径。我之前让一个客服Agent直接连了后台删除接口幸好是内网环境不然后果很严重。第三每个节点都记录输入和输出快照。刚开始我觉得这样太浪费存储后来排查问题时才发现这是最快的定位手段。你可以只保留最近一周的快照但一定要有。第四关键写库操作前加人工确认节点。自动流程跑得再顺涉及资金、权限、客户信息时也要留一道人工闸门。第五把工作流定义和代码一样管理。用Git管理YAML文件任何改动必须走评审。我见过有人在可视化平台直接改线上流程结果一个分支配错整条业务停了两小时。说白了做在线部署多智能体重点不在“多智能体”在“在线部署”。在线意味着你要用工程标准对待这套系统流程可配置、状态可查询、故障可定位、数据可回滚。做到这几点下一代对话式AI才有机会从有趣的Demo变成真正扛业务的生产系统。