AI Agent 怎么从单体架构演进到多 Agent 协作?3 个阶段的踩坑实录

3 阅读8分钟

上周有个朋友问我:「你那个客服 Agent 是怎么做到同时查订单、算退款、还能写邮件的?」我说这玩意儿迭代了三版,从一个巨大的单 Agent 硬塞所有逻辑,到现在拆成 5 个专职 Agent 协作完成任务。说白了就是三步走:单 Agent 全能模式 → Router + 专职 Agent → 多 Agent 异步协作编排。每个阶段解决的问题不一样,踩的坑也完全不同。这篇文章就是我这半年折腾 Agent 架构的完整复盘。

为什么会出现这个问题

2026 年初我刚开始做 Agent 的时候,思路很简单粗暴——一个 system prompt 写 2000 字,把所有工具(查数据库、调第三方 API、发邮件、生成报表)全塞进一个 Agent 里。

刚开始效果还行,demo 跑得飞起。但一上真实场景就崩了:

  • 上下文爆炸:工具描述 + 对话历史 + 业务规则,一个请求就吃掉 30k token
  • 准确率骤降:工具超过 8 个以后,模型选错工具的概率飙升到 30%+
  • 调试地狱:出了 bug 完全不知道是 prompt 问题、工具调用问题还是模型幻觉
  • 成本失控:每次请求都带着全量上下文,token 费用一天比一天高

我相信很多正在做 Agent 的同学都遇到过类似的问题。所以我把自己踩过的坑整理成三个演进阶段,每个阶段附完整代码。

阶段一:单 Agent 全能模式(能跑,但脆弱)

这是大多数人的起点。一个 Agent,一个大 prompt,所有工具都挂上去。

from openai import OpenAI

client = OpenAI(
 api_key="your-key",
 base_url="https://api.ofox.ai/v1"
)

# 单 Agent 模式:所有工具塞进一个 Agent
tools = [
 {"type": "function", "function": {"name": "query_order", "description": "查询订单信息", "parameters": {"type": "object", "properties": {"order_id": {"type": "string"}}}}},
 {"type": "function", "function": {"name": "calculate_refund", "description": "计算退款金额", "parameters": {"type": "object", "properties": {"order_id": {"type": "string"}, "reason": {"type": "string"}}}}},
 {"type": "function", "function": {"name": "send_email", "description": "发送邮件给用户", "parameters": {"type": "object", "properties": {"to": {"type": "string"}, "subject": {"type": "string"}, "body": {"type": "string"}}}}},
 {"type": "function", "function": {"name": "query_inventory", "description": "查询库存", "parameters": {"type": "object", "properties": {"product_id": {"type": "string"}}}}},
 {"type": "function", "function": {"name": "create_ticket", "description": "创建工单", "parameters": {"type": "object", "properties": {"title": {"type": "string"}, "priority": {"type": "string"}}}}},
]

response = client.chat.completions.create(
 model="gpt-5.5",
 messages=[
 {"role": "system", "content": "你是一个全能客服助手,可以查订单、算退款、发邮件、查库存、建工单...(此处省略1500字的规则描述)"},
 {"role": "user", "content": "我的订单 ORD-12345 有问题,想退款"}
 ],
 tools=tools,
 tool_choice="auto"
)

这个阶段的核心问题:

问题表现根因
工具选择错误该查订单的时候去查了库存工具太多,描述相似度高
上下文溢出多轮对话后开始胡说system prompt + tools + history 超限
不可控的链式调用一个问题触发 5-6 次工具调用没有流程约束
调试困难不知道哪步出了问题所有逻辑耦合在一起

我在这个阶段卡了大概两周,最后是因为一个用户说「帮我查下物流」,Agent 直接去算退款了——我才下定决心重构。

阶段二:Router + 专职 Agent(质变的一步)

核心思路:加一个 Router Agent 做意图识别,然后把请求分发给不同的专职 Agent。

每个专职 Agent 只带 2-3 个工具,prompt 也只写自己领域的规则。

graph TD
 A[用户输入] --> B[Router Agent]
 B -->|意图: 订单查询| C[Order Agent]
 B -->|意图: 退款处理| D[Refund Agent]
 B -->|意图: 库存咨询| E[Inventory Agent]
 B -->|意图: 通用问题| F[FAQ Agent]
 C --> G[统一响应格式化]
 D --> G
 E --> G
 F --> G
 G --> H[返回用户]

代码实现:

from openai import OpenAI

client = OpenAI(
 api_key="your-key",
 base_url="https://api.ofox.ai/v1"
)

# 第一步:Router Agent 做意图分类
def route_request(user_message: str) -> str:
 response = client.chat.completions.create(
 model="gpt-5.5",
 messages=[
 {"role": "system", "content": """你是一个意图路由器。根据用户消息,返回以下类别之一:
- order: 订单查询、物流追踪
- refund: 退款、退货、换货
- inventory: 库存查询、商品咨询
- faq: 其他通用问题
只返回类别名,不要解释。"""},
 {"role": "user", "content": user_message}
 ],
 temperature=0
 )
 return response.choices[0].message.content.strip()

# 第二步:专职 Agent 定义
AGENT_CONFIGS = {
 "order": {
 "system_prompt": "你是订单查询专员。只处理订单状态、物流信息相关问题。",
 "tools": [
 {"type": "function", "function": {"name": "query_order", "description": "查询订单信息", "parameters": {"type": "object", "properties": {"order_id": {"type": "string"}}}}},
 {"type": "function", "function": {"name": "track_shipping", "description": "追踪物流状态", "parameters": {"type": "object", "properties": {"order_id": {"type": "string"}}}}},
 ],
 "model": "gpt-5.5"
 },
 "refund": {
 "system_prompt": "你是退款处理专员。严格按照退款政策处理,超过30天的订单不可退款。",
 "tools": [
 {"type": "function", "function": {"name": "query_order", "description": "查询订单信息", "parameters": {"type": "object", "properties": {"order_id": {"type": "string"}}}}},
 {"type": "function", "function": {"name": "calculate_refund", "description": "计算退款金额", "parameters": {"type": "object", "properties": {"order_id": {"type": "string"}, "reason": {"type": "string"}}}}},
 {"type": "function", "function": {"name": "submit_refund", "description": "提交退款申请", "parameters": {"type": "object", "properties": {"order_id": {"type": "string"}, "amount": {"type": "number"}}}}},
 ],
 "model": "gpt-5.5"
 },
}

# 第三步:执行专职 Agent
def run_agent(intent: str, user_message: str):
 config = AGENT_CONFIGS.get(intent)
 if not config:
 return "抱歉,我暂时无法处理这个问题。"
 
 response = client.chat.completions.create(
 model=config["model"],
 messages=[
 {"role": "system", "content": config["system_prompt"]},
 {"role": "user", "content": user_message}
 ],
 tools=config["tools"],
 tool_choice="auto"
 )
 return response

# 主流程
user_msg = "我的订单 ORD-12345 想退款,买了20天了"
intent = route_request(user_msg)
print(f"识别意图: {intent}")
result = run_agent(intent, user_msg)

阶段二相比阶段一的提升:

指标阶段一(单 Agent)阶段二(Router + 专职)
工具选择准确率~70%~95%
单次请求 token 消耗8k-15k2k-4k
调试效率低,黑盒高,可定位到具体 Agent
新增业务场景改一个巨大 prompt新增一个 Agent 配置

这个架构跑了一个多月,效果好了很多。但新问题来了——有些任务需要多个 Agent 协作。比如用户说「帮我退款,退完之后发个邮件通知我」,这需要 Refund Agent 处理完之后,把结果传给 Notification Agent。

阶段三:多 Agent 异步协作编排

到这一步就需要一个编排层了。我没有用什么复杂的框架,就是自己写了一个简单的 pipeline。

核心设计原则:

  1. 每个 Agent 输入输出标准化——统一用 JSON schema
  2. 编排层控制流程——Agent 之间不直接通信
  3. 支持条件分支和并行执行
import asyncio
import json
from openai import OpenAI

client = OpenAI(
 api_key="your-key",
 base_url="https://api.ofox.ai/v1"
)

# 标准化的 Agent 执行结果
class AgentResult:
 def __init__(self, agent_name: str, status: str, data: dict):
 self.agent_name = agent_name
 self.status = status # "success" | "failed" | "need_human"
 self.data = data

# 编排器
class AgentOrchestrator:
 def __init__(self):
 self.context = {} # 共享上下文
 self.execution_log = [] # 执行日志,方便调试
 
 async def run_pipeline(self, user_message: str):
 # Step 1: 路由
 intent = self._route(user_message)
 self.execution_log.append(f"[Router] 意图: {intent}")
 
 # Step 2: 根据意图选择 pipeline
 if intent == "refund_with_notification":
 # 串行:先退款,再通知
 refund_result = await self._run_agent("refund", user_message)
 if refund_result.status == "success":
 notify_result = await self._run_agent(
 "notification",
 f"退款成功,订单{refund_result.data.get('order_id')},"
 f"金额{refund_result.data.get('amount')}元,请发送确认邮件"
 )
 return notify_result
 else:
 return refund_result
 
 elif intent == "order_detail":
 # 并行:同时查订单和物流
 order_task = self._run_agent("order", user_message)
 shipping_task = self._run_agent("shipping", user_message)
 results = await asyncio.gather(order_task, shipping_task)
 
 # 汇总结果
 summary = await self._run_agent(
 "summarizer",
 f"请汇总以下信息并回复用户:{json.dumps([r.data for r in results], ensure_ascii=False)}"
 )
 return summary
 
 async def _run_agent(self, agent_type: str, message: str) -> AgentResult:
 config = AGENT_CONFIGS[agent_type]
 response = client.chat.completions.create(
 model=config["model"],
 messages=[
 {"role": "system", "content": config["system_prompt"]},
 {"role": "user", "content": message}
 ],
 tools=config.get("tools"),
 tool_choice="auto" if config.get("tools") else None
 )
 
 result = AgentResult(
 agent_name=agent_type,
 status="success",
 data={"response": response.choices[0].message.content}
 )
 self.execution_log.append(f"[{agent_type}] {result.status}")
 return result
 
 def _route(self, message: str) -> str:
 # 路由逻辑(简化版)
 if "退款" in message and ("邮件" in message or "通知" in message):
 return "refund_with_notification"
 elif "订单" in message:
 return "order_detail"
 return "faq"

# 使用
async def main():
 orchestrator = AgentOrchestrator()
 result = await orchestrator.run_pipeline("帮我退款订单ORD-12345,退完发邮件通知我")
 print(f"结果: {result.data}")
 print(f"执行日志: {orchestrator.execution_log}")

asyncio.run(main())
sequenceDiagram
 participant U as 用户
 participant R as Router
 participant O as Orchestrator
 participant RA as Refund Agent
 participant NA as Notification Agent

 U->>R: 帮我退款,退完发邮件
 R->>O: intent=refund_with_notification
 O->>RA: 处理退款
 RA-->>O: {status: success, amount: 299}
 O->>NA: 退款成功,发确认邮件
 NA-->>O: {status: success, email_sent: true}
 O-->>U: 退款 299 元已处理,确认邮件已发送

踩坑记录

这半年踩的坑比写的代码还多,挑几个最痛的说:

坑 1:Router 的意图分类不够细

一开始 Router 只分了 4 个类别,结果「我想换个颜色」被分到了 refund(退货换货)。后来我把意图分类改成了两级——先分大类,再分子意图。Router 的 prompt 也从「返回类别名」改成了「返回 JSON,包含 category 和 sub_intent」。

坑 2:Agent 之间的上下文丢失

Refund Agent 处理完退款后,返回的结果里没带用户的邮箱。Notification Agent 拿到的信息不完整,发不出邮件。解决方案是搞了一个共享的 context store,每个 Agent 执行前后都往里面读写。

坑 3:模型选择也是个学问

Router 不需要很强的推理能力,但需要快和准。我试下来 Router 用轻量模型就够了,专职 Agent 里处理复杂业务逻辑的才需要用 GPT-5.5 或 Claude Opus 4.6 这种重量级模型。这样 token 成本直接降了 40%。

这里有个实际的好处——我用的是 ofox.ai 这个 AI 模型聚合平台,一个 API Key 可以调用 GPT-5.5、Claude Opus 4.6、DeepSeek V3 等 50+ 模型,所以 Router 用便宜模型、专职 Agent 用强模型,切换的时候只改 model 参数就行,不用管各家的鉴权差异。

坑 4:错误处理不能只靠 try-catch

Agent 返回「我不确定」或者幻觉出一个不存在的订单号,这种错误 try-catch 抓不到。后来我在每个 Agent 后面加了一个 validator,用规则校验输出格式和关键字段。

三个阶段怎么选

不是所有场景都需要多 Agent。我的经验:

场景推荐阶段理由
工具 ≤ 5 个,业务简单阶段一够用,别过度设计
工具 5-15 个,多个业务域阶段二性价比最高的架构
需要多步骤协作、有条件分支阶段三复杂度上来了就得编排
原型验证/hackathon阶段一先跑通再说

小结

回过头看,Agent 架构演进的核心逻辑就是分治——把一个大而全的 Agent 拆成多个小而专的 Agent,然后用编排层把它们串起来。

这跟微服务的演进路径其实一模一样。单体应用 → 服务拆分 → 服务编排。

不过有一点不同:Agent 的「接口」是自然语言,不是 REST API。这意味着 Agent 之间的通信天然带有模糊性,所以输入输出的 schema 约束和结果校验比传统微服务更重要。

我现在的生产架构基本稳定在阶段二到阶段三之间,大部分请求走 Router 分发就够了,少数复杂场景才走完整的编排 pipeline。如果你也在做 Agent,建议从阶段二开始,别一上来就搞复杂的多 Agent 框架——先把 Router 的意图分类做准,比什么都重要。