Multi-agent 与 Frontend 总入口)
精读 LangChain 官方文档十二Multi-agent 与 Frontend 总入口本篇对应的官方文档Multi-agent多智能体真正解决的问题、主要模式及选择依据。Subagents主 Agent 将专业 Agent 当作工具调用时的集中控制与上下文边界。Handoffs通过 State 和工具调用转移活动角色以及消息配对要求。Frontend overviewcreate_agent后端如何把流式图状态交给useStream。Frontend tool calling工具调用 ID、结果与pending / completed / error生命周期的前端呈现。本篇讲解范围本篇主要是建立 Subagents、Handoffs、Router、Custom workflow 的控制边界并解释后端 messages、tool calls、interrupts 与 thread state 怎样成为前端可操作状态。完整 React/Vue 项目、生成式 UI、部署、鉴权实现和各模式进阶教程留给后续专题。我们在前一篇把外部证据接进了 Agent但现在又有一个问题就是能力越补越多单个 Agent 的压力也会跟着上升。订单查询、政策检索、退款计算、邮件通知、投诉升级和数据分析如果全部塞进同一个入口最初确实省事一个 prompt、一组工具、一份配置。工具和领域知识继续增长以后模型开始在几十个工具之间选错订单规则挤占政策上下文复杂任务只能串行执行。不同团队改自己的能力却都要触碰同一个越来越庞大的 Agent 配置。“拆成多个 Agent”只是起点不是答案。把系统提示词复制几份再分别叫作“专家”并没有解决真正的问题。多智能体设计首先要回答控制权谁接收用户消息谁决定下一步专业组件可以看到什么结果写回哪里失败又由谁恢复。还有一层经常拖到最后才处理这些状态怎样让用户看见退款 Agent 正在查订单、等待人工批准还是已经失败不能让前端从一句自然语言里猜。后端需要提供结构化、可流式更新的执行状态前端再把它变成消息、工具卡片、审批按钮与恢复入口。所以 Multi-agent 与 Frontend 会放在同一篇里讲但两者仍是两层职责。前半篇处理后端协作和上下文边界后半篇处理执行状态怎样进入产品体验。贯穿全文的还是同一个售后任务订单、政策与退款能力怎样协作用户又怎样准确看到每一步发生了什么。单 Agent 把全部工具、规则和历史压进一个模型调用工具选择与上下文噪声都集中在一起拆分后订单、政策和退款能力各有边界再由控制层决定何时调用、传入什么、取回什么。收益来自职责和上下文治理不来自 Agent 数量。一、先判断是否真的需要 Multi-agentLangChain 官方文档先提醒了一件容易被忽略的事任务复杂不一定就要拆成多智能体。一个 Agent 配合合适的工具、动态工具筛选和 Middleware往往已经够用。Multi-agent 的价值主要落在三类问题上。上下文管理让专业组件只拿到当前任务需要的知识与工具不必让一个窗口承受所有领域资料分布式开发让不同团队维护输入输出清楚的能力可以独立的专业任务则有机会并行执行。如果只是工具太多上一篇的 Middleware 动态筛选通常更轻。如果只需要一段专门知识Skills 模式可以按需加载提示和资料不必转移控制。流程完全确定时普通函数或 LangGraph 节点也比多个自主 Agent 更容易测试。真正值得拆分的信号更具体多个领域分别拥有很长的 prompt 和工具任务能够自然分解并独立验收不同团队需要单独发布能力部分子任务可以并行或者对话阶段必须跟随 State 解锁不同能力。决策树先排除单 Agent、动态工具、Skills 和确定性工作流已经足够的情况。只有上下文隔离、专业边界、并行或阶段控制成为主要矛盾时才进入多智能体模式选择避免用更多模型调用掩盖原有的工具、状态或流程问题。验收拆分是否成立可以直接问每个组件的输入、输出、可见上下文和失败责任能不能写清楚如果只能说“订单专家更擅长订单”却讲不清返回结构、验证责任和用户对话归属这种拆分仍然只是角色扮演。二、Subagents主 Agent 集中控制专业 Agent 作为工具在 Subagents 模式中main agent也常称 supervisor继续持有用户对话和总体控制。专业 Agent 被包装成工具主 Agent 决定调用谁、传入什么 query再读取子 Agent 的最终结果。售后场景可以设置order_agent、policy_agent和refund_agent。用户问“这副拆封耳机为什么不能退”主 Agent 先让订单 Agent 核对商品与订单状态再让政策 Agent 查条款最后由自己合并成给用户看的解释。子 Agent 不接管聊天界面也不需要拿到完整会话。这条路径需要观察的是控制权与上下文怎样留在主 Agent而不是系统里有几个“专家”名字。主 Agent 保留会话历史与路由权把精炼后的任务作为 tool input 交给专业 Agent。子 Agent 在自己的上下文中调用专业工具只返回约定结果统一语气和多步编排更容易维持但没有写进最终输出的中间信息也不会自动回到主 Agent。官方文档强调Subagents 默认无状态。每次调用都从干净上下文开始长期对话记忆由主 Agent 维护。这能防止子任务历史不断膨胀也意味着再次调用同一子 Agent 时执行所需的信息要重新传入。工具名和 description 是主 Agent 的路由依据。search_policy只写成“搜索信息”主 Agent 很难判断它和普通 web search 有什么区别。描述需要说明它处理哪类政策问题、需要什么输入以及什么情况下不该调用。子 Agent 的最终 prompt 也要带回关键依据因为主 Agent通常只看得到最后一条输出不会自动获得内部工具轨迹。Subagents 适合集中控制、多领域、多步骤和并行任务。如果专业 Agent 必须持续与用户直接对话就要换一种控制方式。三、Handoffs控制权随 State 转移Handoffs 处理的不是临时咨询而是当前活动角色发生切换。工具调用会更新active_agent、current_step等状态系统据此更换 prompt、工具集合或路由到另一个 Agent 子图。售后流程可以先由资格核验角色确认订单条件满足以后 handoff 给退款角色接下来的几轮都围绕退款方式和账户信息展开高金额场景再进入人工审批。用户看到的仍是一段连续会话后端能力却随着 State 改变。handoff 工具会更新持久 State让下一轮由新的 prompt、工具集或 Agent 节点接管而不只是返回“已经转交”的文字。控制权可以跨用户轮次保持因此每次转移都要定义进入条件、返回路径和恢复责任。官方给出两种实现方向单 Agent 配合 Middleware 动态调整配置或者在多个 Agent 子图之间显式路由。前者共享消息历史适合阶段变化但身份仍连贯的流程后者隔离更强跨子图消息也要自行管理。消息合同在这里很严格。模型产生 handoff tool call 后接收方不能只拿到一条“已经转交”。LLM 期望每个 tool call 都有配对结果所以跨Command.PARENT转移时要同时保留包含 tool call 的AIMessage与确认转交的ToolMessage。少了配对下游收到的就是不完整历史。Handoffs 的风险也很具体。切换条件含糊角色可能来回抖动新角色拿到全部旧消息上下文会继续膨胀只给最后一句又可能丢失已经确认的字段。设计重点依然是上下文工程不是转移工具的名字。四、Router 与 Custom workflow一次分发和显式编排Router 用一个分类步骤把输入分给一个或多个专业 Agent。它适合领域边界明确、每次请求可以独立分类或者需要同时查询多个来源再汇总的场景。Router 通常不承担长期对话编排跨轮次保持上下文时还要增加持久化和选择性历史管理。Custom workflow 使用 LangGraph 显式定义顺序、条件分支、循环与并行节点。节点可以是普通函数、模型调用或完整 Agent。退款流程里“订单校验”可以是确定性节点“政策解释”可以是 Agent 节点“金额超过阈值”则进入审批分支。这类工作流允许确定性逻辑和 Agentic 行为混合哪些步骤能交给模型、哪些约束必须写进图里都可以明确表达。Router 在入口分类后向一个或多个专业域扇出并汇总结果适合清晰垂直领域与并行查询Custom workflow 把节点、分支、循环和恢复路径明确写进图里适合带确定性约束的多阶段流程。前者负责分发后者控制拓扑。四种模式可以按控制权来选需要主 Agent 多轮协调专业能力Subagents需要活动角色直接接管后续对话Handoffs需要对当前输入做一次分类和并行扇出Router需要显式流程、确定性分支和复杂恢复Custom workflow。这些模式能够组合责任却不能因此模糊。例如 custom workflow 的某个节点可以调用 supervisorsupervisor 的工具又执行确定性检索。每增加一层都要说清 State 在哪里、失败回到哪里、追踪 ID 怎样贯穿。五、多智能体的核心仍然是上下文工程官方总览把 context engineering 放在多智能体设计中心。拆分 Agent 只是建立边界真正决定效果的是跨边界传什么。每个专业 Agent 至少要定义三部分。输入包括任务描述、必要事实和允许使用的用户信息工作上下文包括自己的 prompt、工具与知识源输出则要让主 Agent 拿到可以继续处理的结果、来源、状态和错误。输入太少子 Agent 只能猜输入太多隔离就失去意义输出只有一句结论主 Agent也无法验证依据。真正要核对的是每条边界是否只传当前专业能力完成任务所需的信息并带回协调层能够验证的结果。完整会话留在协调层订单 Agent 只接收订单标识与查询目标政策 Agent 只拿商品分类和政策问题退款 Agent 则接收已经验证的资格与金额。组件返回结构化结果和来源不回传无关推理历史从而减少泄露、噪声与 token 膨胀。权限也要跟着上下文收敛。政策 Agent 不需要退款写权限订单 Agent 不应看见其他租户数据退款 Agent 也不能把上游自然语言结论直接当成已经验证的资格。跨边界传递的是结构化字段真正的权限仍由服务端校验。状态归属必须唯一。active_agent属于会话工作流 State用户表达偏好属于长期 Store订单状态属于业务数据库子 Agent 的临时推理只在当前调用有效。相同字段如果在多个 Agent State 中各自更新恢复和冲突合并就会变得不可解释。六、用 supervisor-as-tools 建立最小协作链下面的 Python 示例使用两个专业 Agent订单 Agent 核对订单事实政策 Agent检索规则。两个调用函数包装成主 Agent 的 tools主 Agent 决定调用顺序并合并结果。fromlangchain.agentsimportcreate_agentfromlangchain.toolsimporttoolfromlangchain_openaiimportChatOpenAI modelChatOpenAI(modelqwen3.7-plus,api_keyYOUR_API_KEY,base_urlYOUR_OPENAI_COMPATIBLE_ENDPOINT,)order_agentcreate_agent(modelmodel,tools[],system_prompt只核对订单事实返回商品类型、签收时间和当前售后状态。,)policy_agentcreate_agent(modelmodel,tools[],system_prompt只解释售后政策返回适用条款、版本和必要例外。,)tooldefcheck_order(order_request:str)-str:让订单 Agent 核对指定订单并只返回售后判断需要的事实。resultorder_agent.invoke({messages:[{role:user,content:order_request}]})returnresult[messages][-1].contenttooldefcheck_policy(policy_question:str)-str:让政策 Agent 查询适用条款并返回带版本的判断依据。resultpolicy_agent.invoke({messages:[{role:user,content:policy_question}]})returnresult[messages][-1].content supervisorcreate_agent(modelmodel,tools[check_order,check_policy],system_prompt(你负责售后协调。先取得必要订单事实再核对政策不得把专业 Agent 的推测当成业务系统已确认状态。),)resultsupervisor.invoke({messages:[{role:user,content:订单 A-2048 的耳机拆封了为什么不能退}]})print(result[messages][-1].content)用户消息只进入 supervisor。主 Agent根据工具描述生成check_order或check_policy调用函数把精炼后的任务交给对应子 Agent并只返回最后结果。结果作为工具消息回到 supervisor主 Agent 可以继续调用另一项专业能力也可以生成最终回答。示例没有伪造真实订单 API 和向量检索。生产实现里订单 Agent 要调用业务工具政策 Agent要使用上一篇的 Retrieval主 Agent还要为两类结果定义结构化 schema、超时和部分失败策略。子 Agent 能并行不代表每个任务都应该并行。政策判断依赖商品类型时订单事实必须先完成。代码里的关键也不是创建了两个create_agent而是控制权一直留在 supervisor专业上下文只在调用边界内展开。主 Agent 把专业 Agent 暴露为工具在 tool call 中传递精炼输入子 Agent 独立执行后只返回约定输出。消息轨迹、用户回复和跨步骤决策归 supervisor专业工具与知识留在子 Agent 内从而同时保留集中控制和上下文隔离。后端协作链能够稳定输出执行状态前端才有可能呈现真实进度而不是自己猜 Agent 正在做什么。七、Frontend 不负责编排它消费后端已经存在的状态后端拆成多个 Agent 以后用户关心的并不是内部到底有几个模型而是“系统现在做到哪一步”。Frontend 官方文档的基本架构是create_agent产生编译后的 LangGraph 图与 streaming API前端通过useStream取得响应式的 messages、tool calls、interrupts、history 等状态。这条边界不能反过来。前端不该从“正在为您处理”猜测后端是否在查订单也不应该维护一个和图状态无关的“已完成”布尔值。真实执行状态来自后端流界面只负责用合适的组件表达它。后端图沿同一线程输出 messages、tool calls、interrupts 与 thread history流式 API 持续推送更新useStream再映射成响应式状态。界面负责渲染执行真相仍由图、checkpointer 和事件标识维护。下面的最小 React 轮廓不负责展示完整页面只说明前端怎样订阅指定 Agent并从统一 stream 读取消息与工具调用状态。import { useStream } from langchain/react; type SupportState { messages: Array{ id: string; content: unknown }; }; export function SupportChat() { const stream useStreamSupportState({ apiUrl: http://localhost:2024, assistantId: support_supervisor, }); return ( main {stream.messages.map((message) ( MessageRow key{message.id} message{message} / ))} {stream.toolCalls.map((toolCall) ( ToolCallCard key{toolCall.call.id} toolCall{toolCall} / ))} /main ); }assistantId用来选择后端图messages随流更新toolCalls把调用与结果整理成可以直接渲染的对象。真实项目还要补上 thread ID、鉴权、断线重连、输入提交和错误边界这些都是产品合同不能让组件默认值代替。八、工具卡片与 interrupt 把等待变成可操作状态模型发起工具调用时每个 call 都有name、args和唯一id工具结束后ToolMessage使用同一个 ID 与调用配对。Frontend 的useStream把两者整理成ToolCallWithResult状态至少包含pending、completed与error。于是“查订单中”不再是一句静态文案。pending时显示加载和工具名称completed时在原卡片更新摘要error时提供可重试或升级入口。多个并行工具可以同时 pending 并分别完成不能因为第一个结果返回就把整个任务标记为结束。Human-in-the-loop 还会产生 interrupt。高金额退款在 Middleware 中暂停后前端读取中断内容展示批准、编辑和拒绝操作用户提交决策时恢复同一 thread。只弹本地对话框却没有把决定写回后端界面看起来批准了图仍然会停在原处。同一call.id连接工具请求与结果卡片从 pending 原位更新为 completed 或 error审批在 interrupt 处暂停写回 thread state 并恢复后才继续。并行调用分别完成前端要区分局部状态和整条任务是否结束。前端展示也有信息边界。内部工具参数可能包含用户 ID、查询 SQL 或敏感字段不能把原始 JSON 直接端出来子 Agent 的私有推理也不等于面向用户的“过程透明”。后端或展示适配层应该提供可公开的名称、摘要和错误码让用户知道发生了什么又不泄露实现细节。断线恢复依赖同一线程和持久状态。浏览器刷新以后前端重新加入正在运行的 stream 或读取 thread history应该还原已完成、进行中与等待审批的节点。状态如果只存在组件内存用户刷新就会丢失审批入口后端任务却可能仍在执行产品状态随即错位。九、端到端验收要同时检查控制、状态和体验多智能体系统不能只看最终回答是否“像三个专家合作”。验收至少要覆盖四个层面。路由与控制每类问题为什么进入某个 Agent是否出现循环 handoffRouter 会不会拉起无关领域确定性约束是否可能被模型绕过。上下文与权限子 Agent 的输入是否足够且最小输出有没有主 Agent需要的依据敏感工具是否只对授权组件可见跨租户信息能否进入中间状态。状态与恢复State 归属是否唯一tool call 与 result 是否配对中断能否跨请求恢复并行部分失败是否保留已经完成的结果重放会不会重复真实副作用。前端体验pending、completed、error、interrupt 与任务结束能否分别识别刷新和断线重连是否保持一致用户提交审批后能否看到后端真正继续执行。用户输入进入路由与协作图专业 Agent 在受限上下文里执行State 和事件经持久化与流式接口抵达前端用户的审批或补充信息再写回同一线程。追踪 ID 贯穿模型、工具、Agent 与界面一次失败才有可能被定位到正确层。测试也要对应这些层。子 Agent 用固定输入做合同测试路由器用代表性问题覆盖分类与并行handoff 检查合法消息配对与状态迁移图执行验证中断恢复和幂等前端先用模拟 stream 检查卡片状态再做真实端到端测试确认用户操作确实推进了后端。可观测性需要沿用同一组关联标识。一次用户请求至少要关联 thread、run、agent、tool call 和 interrupt日志记录路由理由、输入输出摘要、耗时与状态变化同时对敏感参数脱敏。前端显示“退款工具失败”时后端才能定位到具体专业 Agent、调用和恢复节点。成本也要按拓扑核算。Subagents 会增加一次结果回到主 Agent 的调用Router 分类也有开销并行能缩短墙钟时间却不会自动减少 token。上线前应拿真实任务比较单 Agent 与拆分方案工具选择正确率提高了多少上下文减少了多少额外模型调用是否值得。Multi-agent 是工程取舍不是只看演示效果的架构标签。十、回到第一模块从单个调用走到完整产品链路Multi-agent 的价值在于把过载的上下文、工具和团队职责拆成可治理边界。Subagents 保留集中控制Handoffs 让活动角色跟随 State 转移Router 负责分类与扇出Custom workflow 显式控制复杂拓扑。具体选择取决于控制权归属、是否跨轮次、是否并行以及流程里有多少确定性约束。Frontend 也不是简单给 Agent 套一个聊天框。它把后端已有的 messages、tool calls、interrupts 与 thread history 转成用户能理解和操作的状态。后端负责真实执行、持久化与权限前端负责呈现、交互和恢复入口两边通过稳定 ID 与状态 schema 对齐。到这里第一模块的对象已经连成完整链路消息进入模型Agent loop 选择工具Runtime Context 与 State 承接运行信息Context Engineering 决定模型所见。Memory 维持跨步骤和跨会话连续Middleware 治理执行边界Retrieval 提供外部证据Multi-agent 在需要时拆分控制Frontend 把状态变成产品体验。这不代表每个主题都已经讲完。第一模块提供的是一张以后反复使用的对象地图。遇到人工审批、复杂 RAG 或长期运行 Agent可以先判断问题落在消息、上下文、状态、工具、检索、控制拓扑还是界面状态再进入对应机制不必重新从一个巨型 prompt 开始。至此第一阶段我们已经全部学完下一阶段我们要学的是运行过程怎样持续抵达用户界面模型生成到哪里工具什么时候开始和结束中断与恢复又该怎样沿事件流被准确呈现。也就是说零件已经装成系统接下来要观察的是系统“运行起来以后”怎样被实时看见。