-
Notifications
You must be signed in to change notification settings - Fork 1.1k
add subagent personal assistant #449
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
47d3f81
2168b2c
df52285
889131b
5b4fcfd
31901c1
8aff290
457a96b
17c0714
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| # Spring AI Alibaba SubAgent Personal Assistant Example | ||
|
|
||
| 本示例展示如何使用 Spring AI Alibaba 的 ReactAgent 框架构建一个多智能体监督者模式系统,通过主智能体协调多个子智能体,实现日历代理与邮件发送功能。 | ||
| ## 功能特性 | ||
|
|
||
| - **多智能体**: Subagent 使用 Tool Calling 模式被 Supervisor Agent 调用。 | ||
| - **人工介入**: 通过在 Supervisor Agent 配置 hooks 加入中断功能。 | ||
|
|
||
| ## 快速开始 | ||
|
|
||
| ### 前置条件 | ||
|
|
||
| - Java 21+ | ||
| - Maven 3.6+ | ||
| - DashScope API Key | ||
|
|
||
| ### 运行步骤 | ||
|
|
||
| 1. **设置 API Key** | ||
|
|
||
| ```bash | ||
| export DASHSCOPE_API_KEY=your-api-key | ||
| ``` | ||
|
|
||
| 2. **构建项目** | ||
|
|
||
| ```bash | ||
| cd subagent-personal-assistant-example | ||
| mvn clean package -DskipTests | ||
| ``` | ||
|
|
||
| 3. **运行应用** | ||
|
|
||
| ```bash | ||
| mvn spring-boot:run | ||
| ``` | ||
|
|
||
| 4. **访问API** | ||
|
|
||
| ``` shell | ||
| curl --location 'http://127.0.0.1:8080/react/agent/supervisorAgent?query=Schedule%20a%20meeting%20with%20the%20design%20team%20next%20Tuesday%20at%202pm%20for%201%20hour%2C%20and%20send%20them%20an%20email%20reminder%20about%20reviewing%20the%20new%20mockups.&threadId=user-session-124&nodeId=_AGENT_HOOK_HITL' \ | ||
| --header 'Content-Type: application/json' \ | ||
| --header 'Accept: text/event-stream' \ | ||
| --data '' | ||
| ```` | ||
| ## Agent说明 | ||
| * supervisor_agent: 监督者智能体,负责协调多个子智能体,实现日历代理与邮件发送功能。 | ||
| * calendar_agent: 日历日程助理,检查可用时间和安排日历事件。 | ||
| * email_agent: 创建邮件主题和邮件发送。 | ||
| ## 工具说明 | ||
|
|
||
| | 工具名称 | 功能 | 输入参数 | | ||
| |---------|-------------------|-----------------------| | ||
| | `get_user_email_tool` | 获取用户邮箱 | UserInfo | | ||
| | `get_current_date_time` | 获取当前日期和时间 | 无 | | ||
| | `get_available_time_slots` | 获取可用时间 slots |AvailableTimeInfo | | ||
| | `create_calendar_event` | 创建日历事件 | CalendarInfo | | ||
| | `send_email` | 发送邮件 | EmailInfo | | ||
|
|
||
| ## 示例对话 | ||
|
|
||
| ``` | ||
| 用户: Schedule a meeting with the design team next Tuesday at 2pm for 1 hour, and send them an email reminder about reviewing the new mockups. | ||
|
|
||
| Agent: | ||
| I'll help you schedule a meeting with the design team and send them an email reminder. Let me break this down into steps: | ||
|
|
||
| 1. First, I need to get the email addresses of the design team members | ||
| 2. Then schedule the calendar event for next Tuesday at 2pm for 1 hour | ||
| 3. Finally, send an email reminder about reviewing the new mockups | ||
|
|
||
| Let me start by getting the design team members' information: | ||
|
|
||
| ================================= Tool Message ================================= | ||
|
|
||
| id: call_e06f221fa93b4e8ea77e62d0 | ||
| name: get_user_email_tool | ||
| responseData: "Available user list for [{\"departmentName\":\"design(设计团队)\",\"email\":\"wangwu@agent.cn\",\"userName\":\"wangwu(王五)\"}]" | ||
| Now I have the design team member information. I'll schedule the meeting for next Tuesday at 2pm for 1 hour with Wang Wu (王五) from the design team: | ||
|
|
||
| 检测到中断,需要人工审批 | ||
| 工具: calendar_agent | ||
| 参数: {"input": "Schedule a meeting with wangwu@agent.cn next Tuesday at 2pm for 1 hour. Subject: Design Team Meeting - Mockup Review"} | ||
| 描述: The AI is requesting to use the tool: calendar_agent. | ||
| Description: Calendar event pending approval | ||
| With the following arguments: {"input": "Schedule a meeting with wangwu@agent.cn next Tuesday at 2pm for 1 hour. Subject: Design Team Meeting - Mockup Review"} | ||
| Do you approve? | ||
| 检测到中断,等待人工介入... node: _AGENT_HOOK_HITL | ||
| 人工介入开始... | ||
| 检测到中断,需要人工审批 | ||
| 工具: email_agent | ||
| 参数: {"input": "Send an email to wangwu@agent.cn with subject 'Reminder: Design Team Meeting - Mockup Review' and content 'Hi Wang Wu, This is a reminder about our upcoming meeting next Tuesday (February 17, 2026) at 2:00 PM to review the new mockups. Please come prepared with your feedback. Looking forward to our discussion!'"} | ||
| 描述: The AI is requesting to use the tool: email_agent. | ||
| Description: Outbound email pending approval | ||
| With the following arguments: {"input": "Send an email to wangwu@agent.cn with subject 'Reminder: Design Team Meeting - Mockup Review' and content 'Hi Wang Wu, This is a reminder about our upcoming meeting next Tuesday (February 17, 2026) at 2:00 PM to review the new mockups. Please come prepared with your feedback. Looking forward to our discussion!'"} | ||
| Do you approve? | ||
| 检测到中断,等待人工介入... node: _AGENT_HOOK_HITL | ||
| 人工介入开始... | ||
| Email sent to wangwu@agent.cn - Subject: Reminder: Design Team Meeting - Mockup Review | ||
| body: Hi Wang Wu, This is a reminder about our upcoming meeting next Tuesday (February 17, 2026) at 2:00 PM to review the new mockups. Please come prepared with your feedback. Looking forward to our discussion! | ||
| ``` | ||
| ## 注意事项 | ||
| 1. 当检测到人工接入时,需要带着nodeId重新发起请求。 | ||
| 2. 当前模型使用的qwen3-max-2026-01-23,模型不同可能导致示例结果有所偏差。 | ||
|
|
||
| ## 相关链接 | ||
|
|
||
| - [Spring AI Alibaba 文档](https://java2ai.com) | ||
| - [Spring AI Alibaba GitHub](https://github.com/alibaba/spring-ai-alibaba) | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,60 @@ | ||||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||||
| <modelVersion>4.0.0</modelVersion> | ||||||
| <parent> | ||||||
| <groupId>com.alibaba.cloud.ai</groupId> | ||||||
| <artifactId>spring-ai-alibaba-examples</artifactId> | ||||||
| <version>1.0.0</version> | ||||||
| <relativePath>../../pom.xml</relativePath> | ||||||
| </parent> | ||||||
|
|
||||||
| <artifactId>subagent-personal-assistant-example</artifactId> | ||||||
| <name>Spring AI Alibaba SubAgent Personal Assistant Example</name> | ||||||
| <description>Multi Agent Personal Assistant</description> | ||||||
|
|
||||||
| <properties> | ||||||
| <maven.compiler.source>21</maven.compiler.source> | ||||||
| <maven.compiler.target>21</maven.compiler.target> | ||||||
|
Comment on lines
+18
to
+19
|
||||||
| <maven.compiler.source>21</maven.compiler.source> | |
| <maven.compiler.target>21</maven.compiler.target> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| /* | ||
| * Copyright 2026-2027 the original author or authors. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * https://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package com.cloud.alibaba.ai.example.agent; | ||
|
|
||
| import com.alibaba.cloud.ai.graph.action.InterruptionMetadata; | ||
|
|
||
| public class HITLHelper { | ||
| /** | ||
| * 批准所有工具调用 | ||
| */ | ||
| public static InterruptionMetadata approveAll(InterruptionMetadata interruptionMetadata) { | ||
| InterruptionMetadata.Builder builder = InterruptionMetadata.builder() | ||
| .nodeId(interruptionMetadata.node()) | ||
| .state(interruptionMetadata.state()); | ||
|
|
||
| interruptionMetadata.toolFeedbacks().forEach(toolFeedback -> { | ||
| builder.addToolFeedback( | ||
| InterruptionMetadata.ToolFeedback.builder(toolFeedback) | ||
| .result(InterruptionMetadata.ToolFeedback.FeedbackResult.APPROVED) | ||
| .description("Agree to tool execution.") | ||
| .build() | ||
| ); | ||
| }); | ||
|
|
||
| return builder.build(); | ||
| } | ||
|
|
||
| /** | ||
| * 拒绝所有工具调用 | ||
| */ | ||
| public static InterruptionMetadata rejectAll( | ||
| InterruptionMetadata interruptionMetadata, | ||
| String reason) { | ||
| InterruptionMetadata.Builder builder = InterruptionMetadata.builder() | ||
| .nodeId(interruptionMetadata.node()) | ||
| .state(interruptionMetadata.state()); | ||
|
|
||
| interruptionMetadata.toolFeedbacks().forEach(toolFeedback -> { | ||
| builder.addToolFeedback( | ||
| InterruptionMetadata.ToolFeedback.builder(toolFeedback) | ||
| .result(InterruptionMetadata.ToolFeedback.FeedbackResult.REJECTED) | ||
| .description(reason) | ||
| .build() | ||
| ); | ||
| }); | ||
|
|
||
| return builder.build(); | ||
| } | ||
|
|
||
| /** | ||
| * 编辑特定工具的参数 | ||
| */ | ||
| public static InterruptionMetadata editTool( | ||
| InterruptionMetadata interruptionMetadata, | ||
| String toolName, | ||
| String newArguments) { | ||
| InterruptionMetadata.Builder builder = InterruptionMetadata.builder() | ||
| .nodeId(interruptionMetadata.node()) | ||
| .state(interruptionMetadata.state()); | ||
|
|
||
| interruptionMetadata.toolFeedbacks().forEach(toolFeedback -> { | ||
| if (toolFeedback.getName().equals(toolName)) { | ||
| builder.addToolFeedback( | ||
| InterruptionMetadata.ToolFeedback.builder(toolFeedback) | ||
| .arguments(newArguments) | ||
| .result(InterruptionMetadata.ToolFeedback.FeedbackResult.EDITED) | ||
| .build() | ||
| ); | ||
| } else { | ||
| builder.addToolFeedback( | ||
| InterruptionMetadata.ToolFeedback.builder(toolFeedback) | ||
| .result(InterruptionMetadata.ToolFeedback.FeedbackResult.APPROVED) | ||
| .build() | ||
| ); | ||
| } | ||
| }); | ||
|
|
||
| return builder.build(); | ||
| } | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| /* | ||
| * Copyright 2026-2027 the original author or authors. | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * https://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| package com.cloud.alibaba.ai.example.agent; | ||
|
|
||
| import org.springframework.boot.SpringApplication; | ||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
|
|
||
| /** | ||
| * @author wangjx | ||
| * @since 2026-02-13 | ||
| */ | ||
| @SpringBootApplication | ||
| public class SubAgentPersonalAssistantApplication { | ||
| public static void main(String[] args) { | ||
| SpringApplication.run(SubAgentPersonalAssistantApplication.class, args); | ||
| } | ||
|
Comment on lines
+18
to
+29
|
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The curl example code block is closed with four backticks instead of three, which breaks Markdown rendering for the rest of the README. Please close it with the matching triple-backtick fence.