多 Agent 协作请假审批系统 技术设计文档
基于 Spring AI Alibaba(通义千问)+ 手动 ReAct 循环 + SSE 实时追踪,把传统「Web 表单 + 审批页」业务改造为对话式体验。用户只和一个主 Agent 聊天,主 Agent 在后台自动调度收集、审批、查询三个子 Agent 完成业务闭环。
1. 项目定位
| 项 |
说明 |
| 业务场景 |
员工请假申请 + 审批 |
| 原流程 |
用户在前端填写表单 → 保存草稿 / 提交 → 管理员在另一个页面审批 |
| 新流程 |
用户只和主 Agent 对话,字段在对话中被提取并落库,审批也通过自然语言完成 |
| 核心挑战 |
对话式拿到结构化数据、角色隔离、可追溯可视化 |
| 解法 |
Supervisor + 子 Agent 工具化 + 手动 ReAct + SSE + 读写分离 |
2. 技术栈
| 层 |
选型 |
作用 |
| 运行时 |
JDK 17 |
基础环境 |
| 框架 |
Spring Boot 3.3.5 |
Web / 依赖注入 / 事务 |
| AI 编排 |
Spring AI 1.0.0 |
ChatModel、ToolCalling、消息抽象 |
| 大模型 |
Spring AI Alibaba DashScope Starter 1.0.0.3(qwen-plus) |
通义千问对接 |
| 数据访问 |
Spring Data JPA + MySQL 8 |
持久化 |
| 工具库 |
Lombok 1.18.34 |
去除样板代码 |
| 前端 |
原生 HTML + fetch 流式读取 |
极简 SSE 消费 |
| 推送 |
SseEmitter(text/event-stream) |
Agent 过程实时可视化 |
3. 整体架构
3.1 分层
| 层 |
组件 |
职责 |
| 接入层 |
/api/chat + SSE |
接收对话、流式返回事件 |
| 编排层 |
Supervisor Agent |
理解意图 + 路由,唯一面向用户 |
| 子 Agent 层 |
Collector / Approver / Query |
职责单一、被 Supervisor 通过工具调用 |
| 工具层 |
@Tool 注解方法 |
封装业务能力,内置权限硬校验 |
| 服务层 |
LeaveFormService / FormQueryService |
写服务 + 读服务分离 |
| 持久化层 |
JPA Repository |
落库 MySQL |
3.2 调用关系示意
Browser ──POST /api/chat──▶ AgentChatController
│
▼
AgentOrchestrator
│
▼
Supervisor (ManualReActAgent)
/ │ \
▼ ▼ ▼
callCollector callApprover callQuery (@Tool 方法)
│ │ │
▼ ▼ ▼
Collector Approver Query (子 ManualReActAgent)
Agent Agent Agent
│ │ │
▼ ▼ ▼
FormCollector FormApprover FormQuery (业务工具层)
Tools Tools Tools
│ │ │
▼ ▼ ▼
LeaveFormService FormQueryService (应用服务)
│ │
└──────── JPA ─────────┘
│
▼
MySQL
4. Agent 角色矩阵
| Agent |
是否面向用户 |
可调用工具 |
权限要求 |
典型场景 |
| Supervisor |
是 |
callCollector / callApprover / callQuery |
无(自身不操作业务) |
所有用户输入的第一站 |
| Collector |
否 |
saveDraft / submit |
APPLICANT |
新建请假、补字段、提交 |
| Approver |
否 |
listPending / getForm / approve |
APPROVER |
查待办、通过或驳回 |
| Query |
否 |
listMyApplications / listMyApprovals / searchByStatus / getDetail / getTimeline |
只读,按角色自动裁剪查询范围 |
查「我有哪些」「走到哪了」 |
4.1 设计原则
| 原则 |
体现 |
| 单一职责 |
每个子 Agent 只做一件事,工具集互不重叠 |
| 读写分离 |
业务 Agent 只写数据;只读查询集中到 Query Agent |
| 身份隔离 |
工具入口有 requireXxx 硬校验,LLM 即使被诱导也无法越权 |
| 可观测 |
所有过程事件(思考、工具调用、交接)都通过 SSE 推给前端 |
5. 数据模型
5.1 leave_form(请假主表)
| 字段 |
类型 |
是否索引 |
含义 |
| id |
VARCHAR(64) |
主键 |
uuid 前 8 位 |
| applicant |
VARCHAR(64) |
是 |
申请人姓名 |
| leave_type |
VARCHAR(32) |
否 |
年假 / 病假 / 事假 |
| start_date |
VARCHAR(32) |
否 |
yyyy-MM-dd |
| end_date |
VARCHAR(32) |
否 |
y |