Stage 3: Multi-Agent 编排
你要学什么
单 Agent 再强,也有局限——一个模型既要懂风控、又要懂路由、还要懂跨境,专业度不够。Multi-Agent 的核心思想是分工专业化:每个 Agent 专注一个领域,通过协作完成复杂任务。
支付场景下的 Multi-Agent 分工:
用户请求 → 主控Agent (Orchestrator)
│
┌────────┼────────┐
▼ ▼ ▼
风控Agent 路由Agent 跨境Agent
(专家) (专家) (专家)
│ │ │
└────────┼────────┘
▼
综合决策输出
为什么要拆分:
- 专业度:每个 Agent 只专注一个领域,Prompt 更聚焦,效果更好
- 并行处理:风控和路由可以同时查,速度更快
- 可维护性:改风控逻辑不影响路由逻辑
- 扩展性:新增一个支付场景,加一个 Agent 就行
运行代码
cd /Users/salar/agentic-payment
cat > stage3_multi_agent.py << 'PYEOF'
"""
Stage 3: Multi-Agent 编排
学习:多智能体协作、角色分工、主控Agent调度
核心模式:主控Agent + 专家Agent(风控/路由/跨境)
PM思考:
- 单Agent为什么不够?因为一个模型什么都懂,但什么都不精
- Multi-Agent的关键是分工:每个Agent只做自己最擅长的
- 主控Agent负责调度和整合,专家Agent负责深度处理
"""
from zhipuai import ZhipuAI
import os
import json
import concurrent.futures
# ====== 0. 配置 ======
client = ZhipuAI(api_key=os.environ.get("ZHIPUAI_API_KEY"))
MODEL = "glm-4-flash"
# ====== 1. Mock数据(复用前两阶段) ======
MOCK_DATA = {
"accounts": {
"ACC001": {"holder": "何静", "balance_cny": 125680.50, "balance_usd": 3200.00, "level": "A"},
"ACC002": {"holder": "优品超市", "balance_cny": 890000.00, "balance_usd": 0, "level": "A"},
"ACC003": {"holder": "环球数码", "balance_cny": 45000.00, "balance_usd": 15000.00, "level": "C"},
},
"merchants": {
"M001": {"name": "优品超市", "level": "A", "category": "零售", "daily_limit": 500000, "refund_rate": 0.02},
"M002": {"name": "环球数码", "level": "C", "category": "跨境电商", "daily_limit": 200000, "refund_rate": 0.18},
"M003": {"name": "速达贸易", "level": "D", "category": "贸易", "daily_limit": 0, "refund_rate": 0.35},
},
"blacklist": ["M003", "ACC999"],
"transactions": {
"M001": [
{"id": "T001", "amount": 320, "time": "2026-06-22 10:15", "card": "debit", "status": "success"},
{"id": "T002", "amount": 1580, "time": "2026-06-22 11:30", "card": "credit", "status": "success"},
],
"M002": [
{"id": "T003", "amount": 28000, "time": "2026-06-22 03:20", "card": "credit", "status": "success"},
{"id": "T004", "amount": 27500, "time": "2026-06-22 03:25", "card": "credit", "status": "success"},
{"id": "T005", "amount": 29800, "time": "2026-06-22 03:30", "card": "credit", "status": "success"},
],
},
"channels": {
"alipay": {"name": "支付宝", "fee_rate": 0.006, "success_rate": 0.995, "limit": 50000},
"wechat": {"name": "微信支付", "fee_rate": 0.006, "success_rate": 0.993, "limit": 50000},
"unionpay": {"name": "银联快捷", "fee_rate": 0.005, "success_rate": 0.998, "limit": 200000},
"cross_border": {"name": "跨境电汇", "fee_rate": 0.01, "success_rate": 0.99, "limit": 350000},
},
"exchange_rates": {
"USD_CNY": 7.24, "EUR_CNY": 7.85, "HKD_CNY": 0.92,
}
}
# ====== 2. 三个专家 Agent ======
def risk_agent(merchant_id: str, amount: float) -> dict:
"""
风控专家 Agent
专注:风险评估、黑名单检查、交易异常检测
"""
merchant = MOCK_DATA["merchants"].get(merchant_id, {})
in_blacklist = merchant_id in MOCK_DATA["blacklist"]
transactions = MOCK_DATA["transactions"].get(merchant_id, [])
risk_factors = []
risk_score = 0
# 黑名单检查
if in_blacklist:
risk_factors.append("商户在黑名单中")
risk_score += 100
# 商户等级
level = merchant.get("level", "C")
if level == "D":
risk_factors.append("商户为D级(高风险)")
risk_score += 50
elif level == "C":
risk_factors.append("商户为C级(较高风险)")
risk_score += 30
# 金额风险
if amount > 100000:
risk_factors.append(f"超大额交易{amount}元")
risk_score += 30
elif amount > 50000:
risk_factors.append(f"大额交易{amount}元")
risk_score += 15
# 退款率
refund_rate = merchant.get("refund_rate", 0)
if refund_rate > 0.15:
risk_factors.append(f"退款率{refund_rate*100:.1f}%,超过15%阈值")
risk_score += 25
# 交易异常检测(短时间多笔大额)
if len(transactions) >= 3:
recent_amounts = [t["amount"] for t in transactions[-3:]]
if all(a > 20000 for a in recent_amounts):
risk_factors.append("短时间内多笔大额交易,疑似拆单")
risk_score += 20
# 风险等级
if risk_score >= 80:
risk_level = "极高"
action = "立即拦截,转人工审核"
elif risk_score >= 60:
risk_level = "高"
action = "暂停交易,人工复核"
elif risk_score >= 30:
risk_level = "中"
action = "放行但标记,事后复核"
else:
risk_level = "低"
action = "正常放行"
return {
"agent": "风控专家",
"merchant": merchant.get("name", "未知"),
"merchant_level": level,
"risk_score": risk_score,
"risk_level": risk_level,
"risk_factors": risk_factors if risk_factors else ["无风险因素"],
"recommended_action": action
}
def routing_agent(merchant_id: str, amount: float, is_cross_border: bool = False) -> dict:
"""
路由专家 Agent
专注:支付通道选择、成本优化、成功率保障
"""
merchant = MOCK_DATA["merchants"].get(merchant_id, {})
merchant_level = merchant.get("level", "B")
channels = MOCK_DATA["channels"]
candidates = []
for key, ch in channels.items():
# 跨境通道只在跨境场景考虑
if key == "cross_border" and not is_cross_border:
continue
if key != "cross_border" and is_cross_border:
continue
# 金额超限排除
if amount > ch["limit"]:
continue
# D级商户排除低成功率通道
if merchant_level == "D" and ch["success_rate"] < 0.99:
continue
fee = round(amount * ch["fee_rate"], 2)
# 综合评分:成功率*0.6 - 费率*0.4(归一化后)
score = ch["success_rate"] * 60 - ch["fee_rate"] * 100 * 40 + merchant.get("daily_limit", 0) / 10000
candidates.append({
"channel": ch["name"],
"fee": fee,
"success_rate": ch["success_rate"],
"limit": ch["limit"],
"score": round(score, 2)
})
# 按综合评分排序
candidates.sort(key=lambda x: x["score"], reverse=True)
if not candidates:
return {
"agent": "路由专家",
"recommended_channel": None,
"reason": "没有可用通道",
"candidates": []
}
best = candidates[0]
return {
"agent": "路由专家",
"recommended_channel": best["channel"],
"estimated_fee": best["fee"],
"estimated_success_rate": best["success_rate"],
"reason": f"综合考虑成功率、费率、限额,推荐{best['channel']}",
"all_candidates": candidates
}
def cross_border_agent(merchant_id: str, amount: float, currency: str = "USD") -> dict:
"""
跨境支付专家 Agent
专注:汇率计算、跨境合规、外汇额度
"""
exchange_key = f"{currency}_CNY"
rate = MOCK_DATA["exchange_rates"].get(exchange_key, 0)
amount_cny = round(amount * rate, 2) if rate else 0
merchant = MOCK_DATA["merchants"].get(merchant_id, {})
merchant_level = merchant.get("level", "C")
# 跨境合规检查
compliance_issues = []
if merchant_level == "D":
compliance_issues.append("D级商户不支持跨境业务")
if amount_cny > 200000:
compliance_issues.append("单笔超过20万人民币,需额外申报")
# 外汇额度检查
daily_limit = merchant.get("daily_limit", 200000)
limit_ok = amount_cny <= daily_limit
if not limit_ok:
compliance_issues.append(f"金额超过商户日限额{daily_limit}元")
return {
"agent": "跨境支付专家",
"original_amount": amount,
"original_currency": currency,
"exchange_rate": rate,
"amount_cny": amount_cny,
"compliance_check": "通过" if not compliance_issues else "需关注",
"compliance_issues": compliance_issues,
"recommended_channel": "跨境电汇",
"estimated_fee": round(amount_cny * 0.01, 2)
}
# ====== 3. 主控 Agent (Orchestrator) ======
def orchestrator_agent(user_query: str) -> dict:
"""
主控Agent:理解用户意图,调度专家Agent,整合结果
"""
# 简化版:用关键词匹配判断需要哪些专家
# 生产环境可以用LLM做意图识别
query_lower = user_query.lower()
needed_agents = []
params = {}
# 提取商户ID(简单正则)
import re
merchant_match = re.search(r'(M\d{3})', user_query)
merchant_id = merchant_match.group(1) if merchant_match else "M001"
# 提取金额
amount_match = re.search(r'(\d+(?:\.\d+)?)\s*(?:万|元|块|USD|usd)', user_query)
if amount_match:
amount_str = amount_match.group(1)
amount = float(amount_str)
if "万" in user_query[amount_match.start():amount_match.end()+1]:
amount *= 10000
else:
amount = 50000 # 默认金额
# 判断是否跨境
is_cross_border = "跨境" in user_query or "USD" in user_query or "usd" in user_query or "外汇" in user_query
# 判断需要哪些专家
if "风险" in user_query or "评估" in user_query or "能通过吗" in user_query or "安全" in user_query:
needed_agents.append("risk")
if "通道" in user_query or "路由" in user_query or "推荐" in user_query or "手续费" in user_query:
needed_agents.append("routing")
if is_cross_border or "跨境" in user_query or "汇率" in user_query:
needed_agents.append("cross_border")
# 如果一个都没匹配到,默认全部调用(综合判断)
if not needed_agents:
needed_agents = ["risk", "routing"]
if is_cross_border:
needed_agents.append("cross_border")
# 并行调用专家 Agent
results = {}
def call_agent(agent_name):
if agent_name == "risk":
return "risk", risk_agent(merchant_id, amount)
elif agent_name == "routing":
return "routing", routing_agent(merchant_id, amount, is_cross_border)
elif agent_name == "cross_border":
currency = "USD" if "USD" in user_query or "美元" in user_query else "USD"
return "cross_border", cross_border_agent(merchant_id, amount, currency)
with concurrent.futures.ThreadPoolExecutor() as executor:
futures = [executor.submit(call_agent, name) for name in needed_agents]
for future in concurrent.futures.as_completed(futures):
name, result = future.result()
results[name] = result
# 整合结果,生成最终回答(用LLM润色)
results_str = json.dumps(results, ensure_ascii=False, indent=2)
prompt = f"""作为支付助手主控,请根据以下专家分析结果,给用户一个清晰、专业的综合回答。
用户问题:{user_query}
商户ID:{merchant_id}
交易金额:{amount}元
是否跨境:{'是' if is_cross_border else '否'}
各专家分析结果:
{results_str}
请输出:
1. 总体结论(一句话)
2. 风险评估结果
3. 推荐方案
4. 注意事项
用中文回答,专业但易懂。
"""
response = client.chat.completions.create(
model=MODEL,
messages=[{"role": "user", "content": prompt}],
temperature=0.3,
)
return {
"orchestrator_decision": {
"merchant_id": merchant_id,
"amount": amount,
"is_cross_border": is_cross_border,
"experts_called": needed_agents,
"expert_results": results
},
"final_answer": response.choices[0].message.content
}
# ====== 4. 测试 ======
if __name__ == "__main__":
test_cases = [
("商户M001有一笔3万元的支付,帮我评估一下风险和推荐通道", "综合评估(风控+路由)"),
("商户M002要做一笔5000美元的跨境支付,帮我看看", "跨境支付全流程"),
("商户M003有一笔1万元支付,风险怎么样", "高风险商户"),
]
print("=" * 60)
print("Stage 3: Multi-Agent 编排")
print("=" * 60)
for query, case_name in test_cases:
print(f"\n{'='*60}")
print(f"测试案例: {case_name}")
print(f"用户问题: {query}")
print(f"{'='*60}\n")
result = orchestrator_agent(query)
print("各专家Agent分析:")
for expert, data in result["orchestrator_decision"]["expert_results"].items():
print(f"\n 【{data['agent']}】")
for k, v in data.items():
if k != "agent" and not isinstance(v, list):
print(f" {k}: {v}")
print(f"\n{'='*40}")
print("📋 综合回答:")
print(result["final_answer"])
print("\n" + "=" * 60)
print("Stage 3 完成!理解了Multi-Agent分工协作模式")
print("=" * 60)
PYEOF
python stage3_multi_agent.py
跑完后想一想
- 为什么要拆成多个 Agent? 一个 Agent 不能同时做风控和路由吗?
- 并行 vs 串行:风控和路由同时跑,节省了多少时间?
- 主控 Agent 的价值:如果没有主控,直接调专家不行吗?
- 边界问题:什么时候该加新的专家 Agent,什么时候在现有 Agent 里加功能?
学习要点
Multi-Agent 的核心优势:
- 专业化分工:每个 Agent 只做自己擅长的,效果更好
- 并行处理:多个专家同时工作,速度更快
- 可维护性:改一个专家的逻辑不影响其他
- 可扩展性:新增业务场景 = 新增专家 Agent
常见 Multi-Agent 模式:
- 主控 + 专家(本项目用的):一个调度,多个专家执行
- 流水线模式:A 的输出是 B 的输入,顺序执行
- 辩论模式:多个 Agent 各抒己见,投票或讨论得出结论
- 群聊模式:多个 Agent 自由讨论,适合创意类任务
支付场景为什么选「主控 + 专家」:
- 支付决策有明确的分工边界(风控、路由、清算)
- 需要并行处理提高效率
- 决策链路需要清晰可追溯
面试使用指南
不要说:"我做了个多 Agent 系统"
要说:"我用 Multi-Agent 架构重构了支付助手,拆成了风控专家、路由专家、跨境专家三个专业 Agent,由主控 Agent 统一调度。这样每个 Agent 更专业,还能并行处理。风控和路由同时跑,响应时间减少了接近一半。"
面试官可能追问:
- "什么时候用单 Agent,什么时候用 Multi-Agent?"
- "任务单一、领域聚焦用单 Agent;任务涉及多个专业领域、需要并行处理、或者逻辑复杂到一个 Prompt 装不下,就上 Multi-Agent。"
- "Multi-Agent 之间怎么通信?"
- "可以用消息队列、共享状态、或者主控调度。简单场景用主控调度就行,复杂场景可以用 LangGraph 这种编排框架。"
跑完之后的心得
学习到的点
核心优势(PM 视角,解决单 Agent 痛点)
- 专业深度更高
- 单 Agent 一套逻辑兼顾风控 + 路由 + 跨境,规则杂糅容易遗漏;
- 每个专家只负责一小块业务,规则可以无限细化、独立迭代,互不干扰。
- 并行计算提速
- 无依赖的专家(风控 + 路由)多线程同时运行,不用串行一步步 ReAct 轮询,大幅减少 LLM 调用次数与耗时。
- 可插拔扩展
- 新增对账 Agent、退款 Agent、分账 Agent,只需要新增函数 + 主控增加匹配规则,原有逻辑完全不动。
- 职责隔离,便于运维
- 风控规则变更只改 risk_agent;通道费率调整只改 routing_agent,故障定位清晰。
三阶段架构横向对比(单 ReAct Agent / MCP 工具服务 / Multi-Agent)
需要优化的点
提出的 5 个优化方向(从支付 PM 视角)
- 意图识别 → LLM 参数抽取 ✅
- 痛点:正则只能匹配 M001、纯数字,处理不了"环球数码 5 万美金"
- 方案:用 LLM 做语义理解,提取商户名称、金额、币种
- 价值:用户体验提升,不用记商户 ID
- 专家分布式化 ✅
- 痛点:本地函数无法水平扩展
- 方案:每个专家封装为 MCP 服务
- 价值:生产级部署,支持高并发、故障隔离
- Agent 间通信 🚀
- 痛点:当前是主控单次分发,专家不对话
- 方案:AutoGen 风格的专家协商
- 价值:动态修正风险评分,更智能
- 例子很贴切:
- 跨境专家:36万人民币,超限!
- 风控专家:收到通知,追加大额跨境风险因子
- 最终风险:175分 → 215分(更准确)
- 多轮对话记忆 🚀
- 痛点:每次请求独立,无法复用参数
- 方案:工作记忆存储上下文
- 价值:用户体验更好,不用重复输入
- 异常处理机制 🚀
- 痛点:专家调用失败怎么办?
- 方案:重试机制 + 降级策略
- 价值:生产环境可靠性
生产级 Multi-Agent 架构演进(从 Demo 到生产级的演进路径)
- 当前(Demo 级)
- 主控Agent → 专家Agent1 + 专家Agent2 + 专家Agent3(本地函数)
- 生产级(企业级)
主控Agent → [MCP服务1] → [MCP服务2] → [MCP服务3]
↓ ↓ ↓
负载均衡 故障转移 缓存
- 高级(AutoGen 风格)
主控Agent ←→ 风控Agent ←→ 路由Agent ←→ 跨境Agent
↓ ↓ ↓ ↓
工作记忆 消息队列 消息队列 消息队列
"多轮对话记忆功能将提升用户体验,避免重复输入商户信息"
"专家间通信能让风险评分更准确,比如跨境超限时动态调整风险因子"