上周有个朋友问我:「你那个客服 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-15k | 2k-4k |
| 调试效率 | 低,黑盒 | 高,可定位到具体 Agent |
| 新增业务场景 | 改一个巨大 prompt | 新增一个 Agent 配置 |
这个架构跑了一个多月,效果好了很多。但新问题来了——有些任务需要多个 Agent 协作。比如用户说「帮我退款,退完之后发个邮件通知我」,这需要 Refund Agent 处理完之后,把结果传给 Notification Agent。
阶段三:多 Agent 异步协作编排
到这一步就需要一个编排层了。我没有用什么复杂的框架,就是自己写了一个简单的 pipeline。
核心设计原则:
- 每个 Agent 输入输出标准化——统一用 JSON schema
- 编排层控制流程——Agent 之间不直接通信
- 支持条件分支和并行执行
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 的意图分类做准,比什么都重要。