【第55篇】Graph-多智能体OpenManus
本文档基于开源项目
spring-ai-alibaba-graph-example/multiagent-openmanus,从零开始拆解其多智能体协作架构。
多智能体
一位项目经理面对一个复杂任务(比如"帮我规划一次从上海到东京的三天旅行")。你不可能一个人做完所有事——你需要:
- 规划师:先拆解任务(订机票→订酒店→查景点→做预算)
- 监督者:检查每一步是否完成,决定下一步做什么
- 执行者:实际去订票、查信息、写代码
OpenManus 的核心思想正是如此:把一个大模型拆成三个"角色",让它们像团队一样协作,而不是让一个模型既当裁判又当运动员。这样每个角色可以专注自己的领域,整体效果远胜于单一大模型。
1. 概述
1.1 multiagent-openmanus
multiagent-openmanus 是 Spring AI Alibaba 生态中的一个示例项目,演示了如何用图(Graph)的方式编排多个 AI 智能体(Agent)协同工作。它不是玩具示例,而是可以直接用于生产环境的骨架代码。
| 属性 | 说明 |
|---|---|
| 模块名称 | multiagent-openmanus |
| 核心模式 | Planning → Supervisor → Executor 三级协作 |
| 技术栈 | Spring Boot 3.4、Spring AI Alibaba、Spring Graph、OpenTelemetry |
| 可选组件 | Langfuse(链路追踪)、PlantUML/Mermaid(可视化) |
| 默认端口 | 18080(可在 application.yml 中修改) |
1.2 痛点
单一大模型处理复杂任务时,常常出现:
- 幻觉:模型自信地编造不存在的信息
- 上下文爆炸:任务步骤太多,模型"记不住"前面的指令
- 工具滥用:该搜索的时候不搜索,该计算的时候瞎猜
多智能体架构通过职责分离解决了这些问题:
- Planning Agent 只负责"想",不碰工具
- Executor Agent 只负责"做",不思考全局
- Supervisor Agent 负责"把关",确保不跑偏
2. 三大智能体:各司其职的"数字员工"
2.1 角色分工详解
Planning Agent(规划师)
代码实现:ReactAgent 实例,命名为 "planningAgent"
核心职责:
- 接收用户的自然语言指令(如"帮我查上海今天的天气")
- 将指令拆解成结构化的执行计划(Plan)
- 输出 JSON 格式的计划,包含多个步骤(step)和每个步骤的提示词(prompt)
btw:
实习生做一份报告,如果不给大纲,他可能会漏掉关键章节。Planning Agent 就是那个先写大纲的人。它确保后续执行有章可循,不会遗漏步骤。
关键方法:
// 伪代码示意
String plan = planningAgent.plan("帮我查上海天气");
// 返回类似:
// {
// "steps": [
// {"id": 1, "prompt": "搜索上海今日天气", "tool": "GoogleSearch"},
// {"id": 2, "prompt": "整理温度、湿度、降雨概率", "tool": "PythonExecute"}
// ]
// }
Supervisor Agent(监督者)
代码实现:SupervisorAgent 类
核心职责:
- 解析 Planning Agent 生成的计划
- 评估当前任务状态:是继续执行下一步,还是已经完工?
- 如果继续,生成下一步的提示词(
step_prompt)发给 Executor - 如果完工,输出最终结果(
final_output)
BTW:
这是整个系统的"大脑"。没有监督者,Planning Agent 和 Executor Agent 就像两个盲人——一个只管发号施令,一个只管埋头苦干,没人知道任务到底做完了没有。Supervisor 就是那个不断问"做完了吗?下一步做什么?"的人。
关键方法:
// 伪代码示意
String decision = supervisor.think(currentState);
// 返回 "continue" 或 "end"
State newState = supervisor.apply(currentState);
// 更新状态,生成 step_prompt
决策逻辑:
Executor Agent(执行者)
代码实现:ReactAgent 实例,命名为 "stepAgent"(代码中对应 step_executing_agent 节点)
核心职责:
- 接收 Supervisor 发来的
step_prompt - 调用具体的工具(GoogleSearch、BrowserUseTool、PythonExecute 等)
- 执行实际操作,返回结果
BTW:
这是系统的"手脚"。Planning Agent 说"搜索天气",Supervisor 说"现在执行第 1 步",Executor 才是真正去调用搜索 API 的人。它不关心全局,只专注把当前这一步做好。
关键特性:
- 通过
Builder.getManusAgentToolCalls()注入所有可用工具 - 支持工具链调用:一个步骤可能需要先后调用搜索→浏览→计算
- 执行结果写回
OverAllState,供 Supervisor 下一轮判断
注:代码中没有单独的
ExecutorAgent类。它通过step_executing_agent这个图节点实现。这是 Spring Graph 的设计哲学——节点即逻辑单元,不一定对应一个类。
3. 状态图(StateGraph):智能体协作的"交通指挥中心"
3.1 整体架构图
如果把三个智能体比作三个部门,StateGraph 就是它们之间的工作流程图。它定义了:
- 谁先开始(Planning)
- 谁向谁汇报(Planning → Supervisor)
- 什么条件下走哪条路(Supervisor 的 continue/end 判断)
3.2 数据如何在节点间流动?
所有智能体之间的通信,都通过一个共享的状态对象 OverAllState 完成。你可以把它想象成一个"公共白板",每个智能体在上面读写信息:
核心字段说明:
| 字段名 | 写入者 | 读取者 | 用途 |
|---|---|---|---|
plan |
Planning Agent | Supervisor Agent | 存储拆解后的任务计划 |
step_prompt |
Supervisor Agent | Executor Agent | 当前要执行的具体指令 |
step_output |
Executor Agent | Supervisor Agent | 工具执行后的原始结果 |
final_output |
Supervisor Agent | 用户 | 最终返回给用户的答案 |
human_feedback |
HumanController | Planning Agent | 人工介入时的反馈信息 |
3.3 条件边(Conditional Edges):Supervisor 的决策枢纽
这是整个系统最精妙的设计之一。Supervisor 的 think() 方法就像一个红绿灯:
- 绿灯(continue):还有步骤没做完,发给 Executor 继续执行
- 红灯(end):所有步骤完成或遇到终止条件,直接输出结果
这种设计让系统具备了自动循环执行的能力——不需要写 for 循环,图的拓扑结构本身就定义了循环逻辑。
4. 工具链(Tool):智能体的"瑞士军刀"
4.1 工具全景
Executor Agent 本身不会搜索网页、不会运行代码,它的能力来自于工具链。就像钢铁侠的战甲,核心是人,但战斗力来自装备。
4.2 每个工具的详细说明
| 工具名称 | 所属包 | 功能详解 | 典型使用场景 |
|---|---|---|---|
| GoogleSearch | com.alibaba.cloud.ai.example.graph.openmanus.tool |
通过 SerpAPI 调用 Google 搜索,获取实时网页结果。返回标题、摘要、链接。 | 需要最新信息时(如"今天的新闻"、“某股票实时价格”) |
| BrowserUseTool | 同上 | 启动 Headless Chrome 浏览器,自动访问网页、点击元素、提取内容。支持 JavaScript 渲染。 | 搜索结果需要进一步打开网页读取详情时 |
| FileSaver | 同上 | 本地文件读写,支持文本、JSON、图片等格式。可指定保存路径和编码。 | 保存中间结果、生成报告文件、缓存数据 |
| PythonExecute | 同上 | 在沙箱环境中执行 Python 代码,支持 numpy、pandas 等库。返回 stdout/stderr。 | 复杂计算(如"计算 100 的阶乘")、数据分析、图表生成 |
| PlanningTool | 同上 | 专门用于解析和生成 Plan JSON,内含任务拆解的核心业务逻辑。 | Planning Agent 内部调用,将自然语言转为结构化计划 |
4.3 工具注册机制:解耦的艺术
设计理念
所有工具都实现了 ToolCallback 接口。这意味着:
- Executor Agent 不需要知道工具内部怎么实现的——它只看到一个统一的 “call(toolName, params)” 接口
- 新增工具非常方便——写一个新类实现
ToolCallback,注册到 Builder 即可 - 可以 mock 测试——单元测试时替换为假工具,不依赖外部 API
5. 配置详解:application.yml 逐行解读
5.1 完整配置与注释
server:
port: 18080 # 默认端口,可通过 --server.port=xxx 覆盖
spring:
application:
name: spring-ai-alibaba-graph-example
ai:
# MCP (Model Context Protocol) 服务器配置
# 用于标准化大模型与外部工具的通信协议
mcp:
server:
name: my-weather-server
version: 0.0.1
type: ASYNC # 异步模式,避免阻塞主线程
sse-endpoint: /sse # Server-Sent Events 端点,用于流式推送
sse-message-endpoint: /mcp # MCP 消息接收端点
capabilities:
tool: true # 支持工具调用
resource: true # 支持资源访问
prompt: true # 支持提示词模板
completion: true # 支持自动补全
alibaba:
toolcalling:
weather:
enabled: true # 启用天气工具(需配置 WEATHER_API_KEY)
baidu:
search:
enabled: true # 启用百度搜索(需配置 BAIDU_API_KEY)
tavilysearch:
api-key: ${TAVILY_API_KEY} # Tavily 搜索 API Key(可选)
dashscope:
api-key: ${AI_DASHSCOPE_API_KEY} # 必填:阿里云百炼大模型 API Key
openai:
# 兼容 OpenAI 协议,实际调用的是阿里云 DashScope
base-url: https://dashscope.aliyuncs.com/compatible-mode
api-key: ${AI_DASHSCOPE_API_KEY}
chat:
options:
model: qwen-max-latest # 使用通义千问最新版模型
5.2 环境变量速查表
| 变量名 | 是否必填 | 获取方式 | 用途 |
|---|---|---|---|
AI_DASHSCOPE_API_KEY |
必填 | 阿里云百炼控制台 | 大模型推理 |
WEATHER_API_KEY |
可选 | 和风天气/ OpenWeatherMap | 天气查询 |
TAVILY_API_KEY |
可选 | Tavily 官网 | 通用搜索 |
SERP_API_KEY |
可选 | SerpAPI 官网 | Google 搜索 |
BAIDU_API_KEY |
可选 | 百度开放平台 | 百度搜索 |
5.3 端口冲突解决
# 方式一:启动参数覆盖(推荐,临时生效)
java -jar app.jar --server.port=18081
# 方式二:环境变量(适合 Docker/K8s)
export SERVER_PORT=18081
# 方式三:修改 application.yml(永久生效,需重新打包)
server:
port: 18081
6. 从用户输入到结果输出
6.1 时序图:一次完整的对话
6.2 实战演示:查询天气
Step 1:启动服务
# 设置必填环境变量
export AI_DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 进入项目目录
cd spring-ai-alibaba/spring-ai-alibaba-graph-example/multiagent-openmanus
# 编译并运行
mvn clean compile spring-boot:run
Step 2:发送请求
curl "http://localhost:18080/manus/chat?query=帮我查询上海今天的天气"
Step 3:内部流转
Step 4:人工介入(可选)
如果任务需要人工确认(比如"预算 5000 元够吗?"),系统会暂停,等待用户反馈:
# 人工反馈接口
curl "http://localhost:18080/manus/human/chat?query=预算没问题,继续"
OpenmanusHumanController 会将 HumanFeedback 写回 OverAllState,Planning Agent 读取后重新规划后续步骤。
7. 常见误区
7.1 端口问题
Spring Boot 默认端口是 8080,开发者可能复制了其他项目的文档但没改端口。而本示例为了不和常见服务冲突,特意改成了 18080。
7.2 接口暴露问题
initGraph() 的职责是在 Spring Boot 启动时完成状态图的编译(将节点和边注册到 Graph 引擎)。这是一个生命周期方法,不是业务接口。如果手动调用,可能导致图被重复编译,引发状态混乱。
7.3 端点权限问题
resume 和 resume-to-next-step 依赖于已存在的会话状态(存储在内存或 Redis 中)。如果外部直接调用,但状态不存在,会抛出 NullPointerException。它们设计给内部循环使用,不是给前端调用的。
8. 部署实操指南
8.1 环境准备检查清单
| 依赖 | 最低版本 | 推荐版本 | 验证命令 |
|---|---|---|---|
| JDK | 17 | 21 LTS | java -version |
| Maven | 3.8 | 3.9+ | mvn -v |
| Docker | 20.10(可选) | 最新 | docker version |
8.2 快速启动(3 分钟版)
# 1. 克隆代码
git clone https://github.com/alibaba/spring-ai-alibaba.git
cd spring-ai-alibaba/spring-ai-alibaba-graph-example/multiagent-openmanus
# 2. 配置环境变量
export AI_DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# 3. 编译运行(开发模式)
mvn clean compile spring-boot:run
# 4. 测试
curl "http://localhost:18080/manus/chat?query=hello"
8.3 生产部署(Jar 包版)
# 1. 打包(跳过测试加速)
mvn package -DskipTests
# 2. 运行
java -jar target/multiagent-openmanus-0.0.1-SNAPSHOT.jar --server.port=18080 --spring.profiles.active=prod
8.4 Docker 容器化部署
# Dockerfile
# 阶段一:构建
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
COPY . .
RUN ./mvnw -B -DskipTests clean package
# 阶段二:运行(使用 JRE 减小体积)
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 CMD wget --no-verbose --tries=1 --spider http://localhost:18080/actuator/health || exit 1
EXPOSE 18080
ENTRYPOINT ["java", "-jar", "app.jar"]
# 构建并运行
docker build -t multiagent-openmanus:latest .
docker run -d -p 18080:18080 -e AI_DASHSCOPE_API_KEY=sk-xxxxxxxx -e WEATHER_API_KEY=your_weather_key --name openmanus multiagent-openmanus:latest
9. 核心接口速查
9.1 公开接口
| 接口 | 方法 | 必填参数 | 说明 |
|---|---|---|---|
/manus/chat |
GET | query |
基础对话,自动完成规划→执行→返回全流程 |
/manus/human/chat |
GET | query |
人工介入版,支持暂停/恢复/反馈 |
9.2 内部接口(不建议外部直接调用)
| 接口 | 说明 |
|---|---|
/manus/resume |
恢复会话,需先有状态 |
/manus/resume-to-next-step |
跳到下一步,需先有状态 |
9.3 接口调用示例
# 基础查询
curl -G "http://localhost:18080/manus/chat" --data-urlencode "query=帮我规划一次从上海到东京的三天旅行"
# 人工介入(假设系统暂停等待确认)
curl -G "http://localhost:18080/manus/human/chat" --data-urlencode "query=预算没问题,请继续预订酒店"
10. 常见问题与排障指南
10.1 启动阶段
| 症状 | 根因 | 解决方案 |
|---|---|---|
NoClassDefFoundError: jakarta/servlet/... |
Spring Boot 3.x 使用 jakarta.* 包,JDK/Maven 版本不兼容 |
确保 JDK >= 17,Maven >= 3.8;检查 pom.xml 中 spring-boot.version >= 3.0 |
Connection refused: dashscope.aliyuncs.com |
网络不通或 API Key 错误 | curl -I https://dashscope.aliyuncs.com 测试网络;在阿里云控制台重新生成 Key |
端口冲突 Address already in use |
18080 被占用 | lsof -i:18080 查看占用进程,或改用 --server.port=18081 |
10.2 运行阶段
| 症状 | 根因 | 解决方案 |
|---|---|---|
模型调用超时 TimeoutException |
DashScope 服务繁忙或网络延迟 | 在 application.yml 增加超时配置:spring.ai.openai.chat.options.timeout=60s |
| 工具返回 403/401 | 第三方 API Key 缺失或过期 | 检查环境变量是否生效:echo $TAVILY_API_KEY;确认 Key 未过期 |
编译报错 Missing require-bundle: javafx.web |
browseruse 工具依赖 JavaFX |
在 pom.xml 添加 JavaFX 依赖,或在 IDE 中配置 JavaFX SDK |
| 返回结果为空或 “null” | Plan 解析失败或工具执行异常 | 查看日志中的 OverAllState 内容,检查 plan 是否为有效 JSON |
10.3 调试技巧
# 查看详细日志(开启 DEBUG 级别)
java -jar app.jar --logging.level.com.alibaba.cloud.ai=DEBUG
# 检查当前状态(需开启 Actuator)
curl http://localhost:18080/actuator/health
# 查看内存中的状态图(调试用)
curl http://localhost:18080/actuator/metrics
11. 监控与可观测性
11.1 OpenTelemetry 链路追踪
系统已内置 OTLP 导出器,只需配置端点即可接入追踪系统:
# application.yml
otel:
exporter:
otlp:
endpoint: http://your-jaeger:4317
headers:
authorization: Bearer your-token
11.2 Langfuse 集成(可选)
Langfuse 是一个开源的 LLM 可观测性平台,可以查看每个 Agent 的:
- 调用链(Trace)
- 耗时(Latency)
- Token 消耗
- 输入/输出内容
11.3 Prometheus + Grafana(进阶)
<!-- pom.xml 中添加 -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
访问 http://localhost:18080/actuator/prometheus 获取指标,在 Grafana 中配置 Dashboard 监控 JVM 内存、HTTP 请求量等。
12. 扩展与定制
12.1 添加自定义工具
// Step 1:实现 ToolCallback 接口
@Component
public class MyDatabaseTool implements ToolCallback {
@Override
public String getName() {
return "DatabaseQuery";
}
@Override
public String call(String params) {
// 你的业务逻辑:查询数据库
return queryDatabase(params);
}
}
// Step 2:注册到 Builder
@Bean
public List<ToolCallback> customTools(MyDatabaseTool dbTool) {
return Builder.getManusAgentToolCalls(dbTool);
}
12.2 修改提示词模板
在 src/main/resources/prompts/ 目录下(或代码中的字符串常量),修改对应 Agent 的系统提示词(System Prompt)。例如 Planning Agent 的提示词可以引导它生成更详细的计划。
12.3 接入其他大模型
默认使用阿里云 DashScope(通义千问),但 Spring AI 的抽象层允许你切换到其他模型:
# 切换到 OpenAI
spring:
ai:
openai:
base-url: https://api.openai.com
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4
# 或切换到本地 Ollama
spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
options:
model: llama3
注意:切换模型后,可能需要调整提示词(Prompt),因为不同模型对指令的理解有差异。
13. 文档目录结构
docs/
├── 01-overview.md # 项目概览与核心概念
├── 02-architecture.md # 架构设计(本文档前半部分)
├── 03-state-graph.md # 状态图详解与 Mermaid 图
├── 04-tools.md # 工具链与注册机制
├── 05-configuration.md # application.yml 逐行解读
├── 06-deployment.md # 部署实操指南(本文档后半部分)
├── 07-api-reference.md # 接口速查表
├── 08-troubleshooting.md # 常见问题与排障
├── 09-monitoring.md # 监控与可观测性
├── 10-extending.md # 扩展与定制开发
└── assets/
├── architecture.png
├── state-graph.png
└── sequence-diagram.png
14. 总结
OpenManus 的多智能体架构本质上是一种**“分而治之”**的策略:
- Planning Agent 负责"想清楚"——把模糊需求变成清晰步骤
- Supervisor Agent 负责"把好关"——确保每一步都按计划执行
- Executor Agent 负责"做到位"——调用工具完成具体操作
三者通过 OverAllState 共享状态,通过 StateGraph 定义协作流程,通过 ToolCallback 解耦工具实现。这种设计让系统既灵活(容易扩展新工具)又可靠(职责分离减少错误)。
如果你是第一次接触多智能体系统,建议:
- 先跑通第 8 节的"3 分钟快速启动"
- 用 DEBUG 日志观察一次完整对话的内部状态流转
- 尝试修改 Planning Agent 的提示词,看看计划生成有何变化
- 最后尝试接入自己的业务工具
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)