在开发 AI Agent 应用时,我们经常遇到用户的一个请求可能涉及多个操作,比如"安排会议并发送邮件提醒"。传统的做法是在代码中硬编码调用顺序,但这样缺乏灵活性。如果用户说"先发邮件再安排会议"呢?或者"如果会议冲突,改到第二天并通知所有人",硬编码的逻辑就会瞬间崩塌。
本文将深入探讨如何利用 Spring AI Alibaba 框架实现 监督者模式。我们将构建一个智能个人助理,让大语言模型担任"管家"角色,动态感知上下文、拆解任务并路由给专业的子Agent,实现真正的智能编排。
1.什么是监督者模式
监督者模式是一种多智能体(Multi-Agent)架构模式。其核心思想是引入一个中心化的监督者Agent,它不直接处理具体业务,而是负责:
- 接收意图:理解用户的复杂指令。
- 动态路由:根据当前状态,决定调用哪个子Agent(作为工具)。
- 循环决策:子Agent执行后返回结果,监督者根据结果决定是"继续下一步"还是"结束任务"。
传统硬编码工作流是显式的代码逻辑,灵活性很低,只适合流程固定、确定性高的任务;监督者模式是LLM自主决策,灵活性很高,修改提示词就能调整行为,还可以基于错误信息自主决定重试或切换,非常适合那些流程多变的场景。
在新版 Spring AI Alibaba 中,监督者模式通常通过将子Agent封装为工具来实现。
- Supervisor Agent :持有
ReactAgent实例,并配置AgentTool。 - Sub-Agent :独立的
ReactAgent,拥有自己的 System Prompt 和专用工具。 - 交互机制:监督者通过函数调用触发子Agent,子Agent执行完毕后,将结果作为工具调用的返回值返回给监督者,形成闭环。
2.构建智能个人助理
我们将实现一个场景:用户请求"下周二下午2点与设计团队开会1小时,并给他们发邮件提醒审查新模型"。这涉及日程管理 和邮件发送两个领域。
环境准备
xml
<dependencies>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-agent-framework</artifactId>
<version>1.1.2.2</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
<version>1.1.2.2</version>
</dependency>
</dependencies>
定义子Agent
java
@Configuration
public class SupervisorConfig {
// 1. 日程助手:专注于时间解析和日历操作
private static final String CALENDAR_AGENT_PROMPT = """
你是一名日程安排助手。
职责:将自然语言形式的调度请求(如"下周二下午 2 点")解析为 ISO 日期时间格式。
工具:使用"get_available_time_slots"检查空闲时间,使用"create_calendar_event"创建事件。
输出:在最终回复中一定要确认所安排的事项细节。
""";
// 2. 邮件助手:专注于内容撰写和发送
private static final String EMAIL_AGENT_PROMPT = """
你是一名专业的电子邮件助手。
职责:根据自然语言请求撰写商务邮件。
工具:提取收件人,设计主题和正文,使用"send_email"发送。
输出:在最终回复中一定要确认邮件已发送及内容摘要。
""";
@Bean
public ReactAgent calendarAgent(CalendarStubTools tools) {
return ReactAgent.builder()
.name("schedule_event")
.description("用于安排日历事件的专家")
.systemPrompt(CALENDAR_AGENT_PROMPT)
.model(chatModel) // 注入 ChatModel
.tools(tools.getTools()) // 注入具体API工具
.inputType(String.class)
.build();
}
@Bean
public ReactAgent emailAgent(EmailStubTools tools) {
return ReactAgent.builder()
.name("manage_email")
.description("用于发送电子邮件的专家")
.systemPrompt(EMAIL_AGENT_PROMPT)
.model(chatModel)
.tools(tools.getTools())
.inputType(String.class)
.build();
}
}
构建监督者Agent
java
@Bean
public ReactAgent supervisorAgent(
@Qualifier("calendarAgent") ReactAgent calendarAgent,
@Qualifier("emailAgent") ReactAgent emailAgent,
MemorySaver memorySaver) {
return ReactAgent.builder()
.name("personal_assistant")
.systemPrompt("""
你是一个乐于助人的个人助理管家。
你可以协调"日程助手"和"邮件助手"来完成用户请求。
执行策略:
1. 分析用户请求,如果涉及多个步骤(如先开会后发邮件),请按顺序依次调用工具。
2. 如果子Agent返回信息不足(如缺少参会人),请直接向用户追问,不要编造信息。
3. 只有当所有子任务都完成后,才向用户输出最终结果。
""")
.model(chatModel)
.saver(memorySaver) // 必须配置 MemorySaver 以保持多轮对话上下文
.tools(
// 关键点:将子Agent包装为工具,让监督者"看见"并调用它们
AgentTool.getFunctionToolCallback(calendarAgent),
AgentTool.getFunctionToolCallback(emailAgent)
)
.build();
}
测试验证
java
@Test
void testSupervisorWorkflow() {
String complexQuery = """
请于下周二下午 2 点安排一次与设计团队的会议,时长 1 小时,
并给他们发送一封电子邮件以提醒他们对新的模型进行审查。
""";
// 调用监督者
AssistantMessage response = supervisorAgent.call(new UserMessage(complexQuery));
log.info("最终回复: {}", response.getText());
}
3.日志解析
通过日志,我们可以清晰地看到监督者是如何"思考"和"行动"的。
场景一:信息不足时的反问机制
用户输入:"安排明天上午 9 点的团队站立会议"
| 时间戳 | 日志级别 | 关键内容 | 流程解析 |
|---|---|---|---|
| 15:13:16 | INFO | User request: 安排明天上午... | 步骤1:接收输入。监督者接收指令。 |
| 15:13:17 | DEBUG | ASSISTANT toolCalls=[schedule_event(...)] | 步骤2:决策路由。监督者判断需要日程助手,生成工具调用。 |
| 15:13:20 | DEBUG | TOOL role=TOOL, name=schedule_event, content="需要参会人邮箱..." | 步骤3:子Agent执行。子Agent发现缺少关键参数(参会人),返回询问信息。 |
| 15:13:23 | INFO | Assistant: 为了帮您准确安排...需要确认参会人... | 步骤4:反馈用户。监督者收到子Agent的"询问",没有强行结束,而是将问题转达给用户。 |
洞察 :监督者模式不仅仅是执行,还能处理异常流。子Agent的"反问"被监督者正确识别并传递给用户,实现了多轮对话的闭环。
3.2 场景二:多步骤复杂任务串联(完整流程)
阶段1:监督者接收第二个请求(含历史上下文)
| 行号 | 时间戳 | 日志内容 | 监督者模式流程对应 |
|---|---|---|---|
| 6 | 15:13:23.003 | INFO - User request: 请于下周二下午 2 点安排一次与设计团队的会议,会时长 1 小时,并给他们发送一封电子邮件... |
步骤1:监督者接收新用户输入(同时保留历史对话) |
阶段2:第一次路由 → schedule_event
| 行号 | 时间戳 | 日志内容 | 监督者模式流程对应 |
|---|---|---|---|
| 7 | 15:13:26.305 | DEBUG - ASSISTANT toolCalls=[ToolCall[name=schedule_event, arguments={"input": "下周二下午 2 点与设计团队开会,时长 1 小时"}]] |
步骤2:LLM分析后,决定先调用schedule_event |
| 8 | 15:13:27.085 | DEBUG - Response 200 OK |
子Agent执行中 |
| 9 | 15:13:28.919 | DEBUG - TOOL role=TOOL, name=schedule_event, content="已为您安排会议:主题:与设计团队开会 时间:下周二(2024年1月16日)下午2:00-3:00" |
步骤3:schedule_event执行完成,返回监督者 |
阶段3:第二次路由 → manage_email
| 行号 | 时间戳 | 日志内容 | 监督者模式流程对应 |
|---|---|---|---|
| 10 | 15:13:36.761 | DEBUG - ASSISTANT toolCalls=[ToolCall[name=manage_email, arguments={"input": "给设计团队发送一封邮件,提醒他们对新的模型进行审查。会议定于下周二下午 2 点。"}]] |
步骤2(第二次):监督者根据前序结果,决定调用manage_email |
| 11 | 15:13:37.313 | DEBUG - Response 200 OK |
子Agent执行中 |
| 12 | 15:13:38.547 | DEBUG - TOOL role=TOOL, name=manage_email, content="邮件已成功发送给设计团队..." |
步骤3(第二次):manage_email执行完成,返回监督者 |
阶段4:监督者输出最终结果
| 行号 | 时间戳 | 日志内容 | 监督者模式流程对应 |
|---|---|---|---|
| 13 | 15:13:40.480 | INFO - Assistant: 任务已完成:1.会议安排 2.邮件发送 |
步骤4:监督者判断所有任务完成,输出FINISH |
我们基于 Spring AI Alibaba 的监督者模式实现了控制流与业务逻辑的解耦,利用 LLM 的推理能力处理不确定性。通过 ReactAgent 和 AgentTool 的组合,我们仅需少量代码即可构建出具备多步规划 、上下文记忆 和异常处理能力的智能系统。这种模式特别适合企业级应用中的复杂助手场景,如IT运维自动化工单处理、智能客服工单流转等。