多 Agent 协作的消息路由架构:从顺序调用到动态编排
一、单 Agent 在多任务场景中的能力边界
一个综合 AI 助手需要同时处理三类请求:技术问题解答(需要代码搜索 Agent)、文档摘要生成(需要长文本处理 Agent)、日程管理(需要日历操作 Agent)。如果用一个通用 Agent 处理所有请求,问题表现为:技术问题时 Agent 调用了日历工具(误判意图),文档摘要时没有触发分段处理(缺少领域知识),日程冲突检测逻辑散布在 Prompt 中难以维护。
单 Agent 架构的本质局限在于:一个 Agent 的 System Prompt 需要涵盖所有领域的规则,导致指令互相干扰。为代码搜索写的"给出可运行示例"指令,在文档摘要场景中变成了"摘要要包含可运行示例"的错误理解。
多 Agent 的解耦思路是:每个 Agent 只负责一个明确的领域,通过路由器将用户请求分发给最合适的 Agent。这样每个 Agent 的 Prompt 可以高度专业化,工具的权限范围也得到天然隔离。
二、消息路由的三种分发模式
多 Agent 系统的消息分发有三种模式,按复杂度递增:
graph TB USER[用户消息] --> ROUTER{消息路由器} subgraph 模式1:意图分类路由 ROUTER -->|分类:技术问题| A1[代码搜索 Agent] ROUTER -->|分类:文档摘要| A2[摘要生成 Agent] ROUTER -->|分类:日程管理| A3[日历管理 Agent] ROUTER -->|未分类| DEFAULT[通用兜底 Agent] end subgraph 模式2:顺序编排 ROUTER2[编排器] --> B1[意图识别 Agent] B1 --> B2[任务分解 Agent] B2 --> B3{是否为复杂任务?} B3 -->|是| B4[多 Agent 协作执行] B3 -->|否| B5[单一 Agent 执行] end subgraph 模式3:动态协作 C1[对话管理 Agent<br/>维护全局上下文] C1 --> C2[按需调用专业 Agent] C2 --> C1 C1 --> C3[结果聚合与冲突解决] end模式 1 适合大多数场景——根据意图分类后直接路由。模式 2 适合需要规划和分解的复杂任务。模式 3 适合需要跨领域协作的场景(如技术问题涉及代码 + 文档)。
三、模式 1 的路由器实现
""" 多 Agent 消息路由器——基于意图分类的消息分发。 设计意图:路由器自身是一个轻量 Agent,专门做意图分类。 分类后将消息路由到对应专业 Agent,返回结果。 """ from typing import List, Dict, Optional from enum import Enum from dataclasses import dataclass import json class AgentCapability(str, Enum): """Agent 能力枚举——路由器根据此进行分发""" CODE_SEARCH = "code_search" DOCUMENT_SUMMARY = "document_summary" CALENDAR_MANAGEMENT = "calendar_management" GENERAL_CHAT = "general_chat" @dataclass class AgentConfig: """Agent 配置""" name: str capability: AgentCapability system_prompt: str # 该 Agent 可调用的工具列表 tools: List[str] # 优先级——同一消息可能匹配多个 Agent,取优先级最高的 priority: int = 0 # 路由关键词——快速过滤,减少 LLM 调用 keywords: List[str] = None @dataclass class RouteDecision: """路由决策结果""" agent: AgentConfig confidence: float reason: str class MessageRouter: """消息路由器""" def __init__(self, agents: List[AgentConfig]): self.agents = agents self.fallback_agent = next( (a for a in agents if a.capability == AgentCapability.GENERAL_CHAT), agents[0], ) async def route(self, message: str) -> RouteDecision: """路由用户消息到最合适的 Agent""" # 第一层:关键词快速过滤——节省 LLM 调用 keyword_match = self._keyword_filter(message) if keyword_match: return keyword_match # 第二层:LLM 意图分类——处理关键词无法覆盖的场景 return await self._llm_classify(message) def _keyword_filter(self, message: str) -> Optional[RouteDecision]: """关键词快速过滤——O(n) 复杂度,毫秒级""" message_lower = message.lower() for agent in self.agents: if not agent.keywords: continue # 计算关键词命中比例 hits = sum( 1 for kw in agent.keywords if kw.lower() in message_lower ) if hits > 0: return RouteDecision( agent=agent, confidence=min(0.9, 0.5 + hits * 0.1), reason=f"关键词匹配: {hits} 个命中", ) return None async def _llm_classify(self, message: str) -> RouteDecision: """LLM 意图分类——准确性高但需要 API 调用""" # 构造分类 Prompt——列出所有可用的 Agent agent_descriptions = "\n".join( f"- {agent.name}: {agent.capability.value} (优先级 {agent.priority})" for agent in self.agents ) classification_prompt = f"""分析用户消息,选择最合适的 Agent 处理。 可用 Agent: {agent_descriptions} 输出 JSON 格式: {{ "agent": "Agent名称", "confidence": 0.0-1.0, "reason": "分类理由(简短)" }} 如果无法确定意图,使用优先级最高的通用 Agent。 如果消息与所有 Agent 都不匹配,confidence 设为 0 并使用 GENERAL_CHAT。 """ # 调用轻量模型做分类——减少延迟和成本 try: response = await self._call_llm( system_prompt=classification_prompt, user_message=message, model="gpt-3.5-turbo", # 分类不需要强模型 max_tokens=100, ) data = json.loads(response) target_agent = next( (a for a in self.agents if a.name == data.get("agent")), self.fallback_agent, ) return RouteDecision( agent=target_agent, confidence=float(data.get("confidence", 0.5)), reason=data.get("reason", "LLM 分类"), ) except (json.JSONDecodeError, KeyError) as e: # 分类失败——降级到通用 Agent return RouteDecision( agent=self.fallback_agent, confidence=0.3, reason=f"分类异常降级: {e}", ) async def _call_llm( self, system_prompt: str, user_message: str, model: str, max_tokens: int, ) -> str: """调用 LLM——简化版,实际应接入 API 客户端""" # 此处为占位实现 return '{"agent": "通用助手", "confidence": 0.5, "reason": "默认"}'三个设计要点:
- 两层路由——关键词快速过滤处理高频场景(毫秒级),LLM 分类处理语义模糊场景(秒级),减少不必要的 API 调用;
- 分类失败降级——JSON 解析失败时回退到通用 Agent,不影响用户获取基本回复;
- 分类使用轻量模型——意图分类不需要强模型的推理能力。
四、多 Agent 的协作成本考量
每次路由的额外开销。引入路由器后,每次用户消息增加了一次意图分类的 LLM 调用(约 0.5-1 秒延迟,约 500 Token 消耗)。对于日活 1000 的系统,日增 50 万 Token 的额外成本。
Agent 间上下文传递的断裂。用户先问代码问题(路由到代码 Agent),再追问文档相关的问题(路由到文档 Agent),两个 Agent 没有共享上下文。需要在上层维护一个对话管理 Agent 来聚合所有子 Agent 的上下文。
Router 自身的健壮性。如果 Router 将 10% 的消息错误分类,用户将收到不相关的回复。Router 的准确率应持续监控,当误分类率超过 5% 时需要调整分类 Prompt 或更新关键词列表。
五、总结
多 Agent 消息路由的架构设计:
- 根据业务领域划分 Agent 职责,每个 Agent 有独立的 System Prompt 和工具权限;
- 路由器使用两层过滤(关键词 + LLM 分类)分发消息;
- 分类失败时降级到通用 Agent,不中断用户体验。
落地步骤:
- 列出所有需要专业处理的消息类型,按类型定义 Agent;
- 为每个 Agent 添加关键词列表,覆盖 80% 的高频场景;
- 实现 LLM 分类作为关键词的补充,处理剩余 20% 的语义模糊场景;
- 监控误分类率——定期抽样审查路由决策的准确性。