Day 13 --- 多 Agent 协作(Router + 子 Agent 分流)
源代码:源代码
一、目标
实现 Router 路由分发 + 子 Agent 专业处理 的多 Agent 协作架构。用户消息先经过 Router 意图分类,再自动转发给对应领域的子 Agent,每个子 Agent 有独立的角色设定(System Prompt)和对话记忆。
二、架构图
markdown
用户消息(任意话题)
↓
Router(裸 LLM 分类)
├── CUSTOMER_SERVICE → 客服 Agent
├── AFTER_SALES → 售后 Agent
├── TECH_SUPPORT → 技术支持 Agent
└── GENERAL → 通用 Agent
↓
子 Agent 回答 → 返回给用户
关键设计
| 层次 | 实现方式 | 说明 |
|---|---|---|
| Router | chatModel.generate() 裸 LLM 调用 |
无 Tools,纯文本分类 prompt,要求只输出类别名 |
| 子 Agent | LangChain4j AiServices + @SystemMessage |
每个 Agent 独立角色设定 + 独立 ChatMemory(10 条) |
| 分发 | Map<String, Object> + instanceof |
根据 Router 输出匹配到对应 Bean |
三、技术栈
- 框架: Spring Boot 2.7.18 + Tomcat 9.0.83
- LLM: deepseek-ai/DeepSeek-V3 via 硅基流动(OpenAI 兼容)
- Agent: LangChain4j 0.36.2(AiServices、@SystemMessage、@UserMessage)
- 语言: Java 17
四、项目结构
bash
day13/
├── pom.xml
├── src/main/java/com/day13/demo/
│ ├── Day13Application.java # 启动类
│ ├── config/ChatModelConfig.java # LLM Bean 配置
│ ├── controller/
│ │ └── MultiAgentController.java # REST API: GET /agent/chat
│ ├── service/
│ │ └── MultiAgentService.java # 核心:Router + 4 个子 Agent
│ ├── dto/Result.java # 统一响应体
│ └── tool/WeatherTool.java # 华风爱科天气 Tool(备用)
└── src/main/resources/
└── application.yml # 硅基流动 API Key(明文)
五、核心代码
5.1 Router 分类 Prompt
java
private static final String ROUTER_PROMPT = """
你是一个路由分发器。根据用户消息,判断属于哪个类别,**只回复类别名称,不要解释,不要加标点**:
- 订单查询、物流追踪、商品信息、退换货政策、促销优惠 → CUSTOMER_SERVICE
- 投诉、退款、差评、产品质量问题、维修、赔偿 → AFTER_SALES
- 技术问题、报错排查、安装配置、API/SDK使用、bug报告 → TECH_SUPPORT
- 无法归类或普通闲聊 → GENERAL
用户消息:
""";
为什么用裸 LLM? AiServices Router 模式需要 template 非空(@SystemMessage),但 Router 只需要做一次分类无需多轮对话,直接用 chatModel.generate() 更轻量。
5.2 子 Agent 接口(4 个独立角色)
java
// 客服
interface CustomerServiceAgent {
@SystemMessage("你是客服专员,负责订单查询、物流追踪、商品咨询、退换货政策。请友好热情地回复。")
String chat(@UserMessage String userMessage);
}
// 售后
interface AfterSalesAgent {
@SystemMessage("你是售后专员,处理投诉退款维修。请先致歉,给出具体方案。")
String chat(@UserMessage String userMessage);
}
// 技术支持
interface TechSupportAgent {
@SystemMessage("你是技术支持工程师,负责技术排查。请专业但易懂地回复。")
String chat(@UserMessage String userMessage);
}
// 通用
interface GeneralAgent {
@SystemMessage("你是通用 AI 助手,回答各类问题。")
String chat(@UserMessage String userMessage);
}
每个子 Agent 通过 AiServices.builder() 构建,拥有独立的 MessageWindowChatMemory.withMaxMessages(10)。
5.3 分发逻辑
java
public String chat(String message) {
// 1. Router 分类
String category = chatModel.generate(ROUTER_PROMPT + message);
category = category.trim().toUpperCase();
// 2. 路由匹配
Object subAgent = subAgents.getOrDefault(category, subAgents.get("GENERAL"));
// 3. 调用子 Agent
if (subAgent instanceof CustomerServiceAgent agent) {
return "[客服] " + agent.chat(message);
} else if (subAgent instanceof AfterSalesAgent agent) {
return "[售后] " + agent.chat(message);
} // ... TechSupport / General
}
六、启动与测试
bash
cd day13
mvn spring-boot:run -DskipTests
# 测试(4 个场景)
# 客服
curl "http://localhost:8088/agent/chat?message=我的订单什么时候到"
# 售后
curl "http://localhost:8088/agent/chat?message=收到的手机屏幕有划痕,我要退款"
# 技术支持
curl "http://localhost:8088/agent/chat?message=SDK初始化报NullPointerException怎么解决"
# 通用
curl "http://localhost:8088/agent/chat?message=你好"
测试截图:

七、验证结果(实测)
| 场景 | 用户消息 | Router 分类 | 子 Agent | 响应摘要 |
|---|---|---|---|---|
| 客服 | "我的订单什么时候到" | CUSTOMER_SERVICE |
客服 | 物流追踪建议、正常 3-5 天达 |
| 售后 | "手机屏幕有划痕退款" | AFTER_SALES |
售后 | 先致歉、退款/换货/补偿三方案 |
| 技术 | "SDK NPE 怎么解决" | TECH_SUPPORT |
技术支持 | 4 步排查 + Java 代码示例 |
| 通用 | "你好" | GENERAL |
通用 | 问候并引导到专业部门 |
✅ 4 个场景全部正确路由 + 子 Agent 给出领域相关回答。
九、下一步优化方向
- 多轮对话 : 当前每个子 Agent 有独立
ChatMemory,但 Router 无记忆 --- 后续可让 Router 记住上下文 - 动态子 Agent 注册 : 用 Spring Bean 扫描 + 自定义注解
@AgentType("CUSTOMER_SERVICE")替代硬编码 Map - 工具嵌入子 Agent: 客服 Agent 接入订单查询 Tool,技术支持 Agent 接入知识库 Tool
- Router 置信度: 让 LLM 同时输出分类 + 置信度,低置信度时反问用户确认
十、与 Day 11/12 的关系
| Day | 主题 | 核心能力 |
|---|---|---|
| Day 11 | Agent 自主决策 | 单 Agent + Tool 调用(天气/搜索) |
| Day 12 | SSE 流式对话 | 逐 token 推送前端 |
| Day 13 | 多 Agent 协作 | Router 分流 + 角色分离 + 独立记忆 |
Day 13 是 Day 11 的架构升级:从「一个 Agent 包揽一切」升级为「多个专业 Agent 各司其职」。