JAVA实现Manus智能体
摘要:本文介绍了智能体(Agent)的概念及其关键技术,重点分析了OpenManus项目的实现原理。智能体是一种能够感知环境、自主规划并执行任务的AI系统,分为反应式、有限规划和自主规划三个层次。文章详细讲解了OpenManus的架构设计,包括分层代理模式(BaseAgent、ReActAgent、ToolCallAgent)、核心组件(记忆系统、工具调用、流程控制)以及关键技术(CoT思维链、R

目录
不久前Manus也是火爆全球,后来MetaGPT 核心团队用 3 小时 “爆肝” 写出开源复刻版,这类智能体通过思考-行动-观察的循环模式工作,能够持续推荐任务直至完成目标,今天我们就来学习一下OpenManus是如何实现,并且使用Java模仿做一个OpenManus
一. 什么是智能体
智能体(Agent)和普通的大模型不同,智能体是一个能够感知环境、进行推理、制定计划并且能够自主采取行动来实现特定目标的AI系统,就像一个有主观能动性的人类一样。
智能体能够:
感知环境:通过各种输入渠道获取信息(多模态),理解用户需求和环境状态
自主规划任务步骤:将复杂任务分解为可执行的子任务,并设计执行顺序
主动调用工具完成任务:根据需要选择并使用各种外部工具和 API,扩展自身能力边界
进行多步推理:通过思维链(Chain of Thought)逐步分析问题并推导解决方案
持续学习和记忆过去的交互:保持上下文连贯性,利用历史交互改进决策
根据环境反馈调整行为:根据执行结果动态调整策略,实现闭环优化
智能体的分类
智能体是可以不断进化的,按照自主性和规划能力,智能体也分为几个不同的层次
反应式智能体
反应式智能体根据当前输入和固定的规则做出反应,比如说简单的聊天机器人,没有真正的自主规划能力,在23年时大多数AI聊天机器人都是反应式智能体:
有限规划智能体
有限规划智能体能进行简单的多步骤执行,但执行路径通常是预设的(有点类似于工作流),鉴定为能干事但是干不了复杂的大事的智能体,24年流行的很多可联网搜索、调用知识库和工具的AI应用都是这类智能体
比如:
办公流程助手 一键整理文档→提取要点→生成简报,固定步骤执行
电商客服机器人 咨询查单→核对信息→售后登记,按预设流程应答
简单插件型 AI 联网搜索→汇总信息→作答,最多几步固定调用
游戏简易 NPC 检测敌人→走位→攻击,短步骤行为规划
手机语音助手 设闹钟→查路线→播放音乐,单次多步固定任务
表单自动填报工具 读取数据→填入对应栏位→提交,限定流程执行
自主规划智能体
自主规划智能体能够根据任务目标自主分解任务、指定计划、选择工具一步步执行,直到完成任务,25 年初很火的 Manus 项目,它的核心亮点在于其 “自主执行” 能力

当然还有现在很火的Claude code、codex、OpenClaw等自主规划智能体
二. 智能体关键技术
CoT 思维链
CoT 是一种让AI像人类一样进行 思考 的技术,帮助AI在处理复杂问题时能够按步骤思考,对于复杂的推理类问题,先思考后执行,对于思维链有几种实现方式:
1. 提示词手动引导
直接话术要求分步思考 示例:一步步推理,先分析条件,再推导答案,最后给出结果
2. 少样本思维链
投喂 1 - 几组带推理步骤案例,模型模仿逻辑 Prompt 示例
例1:
问:3+2×4
思:先算乘法2×4=8,再算加法3+8=11
答:11 请按上面步骤回答:6-8÷2
3. 手动结构化思维链
人为划定思考框架,固定推理维度 格式:拆解条件→梳理关系→推导计算→总结结论
4. 自动思维链 Auto-CoT
模型自动拆分问题、生成推理步骤,无需人工写样例 自动把复杂题拆成多个子小问题依次求解
5. 智能体链式推理 Agent-CoT
闭环四步循环,自主规划反思
1. 规划:拆分整体任务
2. 执行:分步调用工具 / 运算
3. 复盘:检查结果对错
4. 修正:出错回溯重推
那么在OpenManus 的早期版本中,就有一段实现CoT的系统提示词:
You are an assistant focused on Chain of Thought reasoning. For each question, please follow these steps:
1. Break down the problem: Divide complex problems into smaller, more manageable parts
2. Think step by step: Think through each part in detail, showing your reasoning process
3. Synthesize conclusions: Integrate the thinking from each part into a complete solution
4. Provide an answer: Give a final concise answer
Your response should follow this format:
Thinking: [Detailed thought process, including problem decomposition, reasoning for each step, and analysis]
Answer: [Final answer based on the thought process, clear and concise]
Remember, the thinking process is more important than the final answer, as it demonstrates how you reached your conclusion.
Agent Loop 执行循环
Agent Loop 是智能体最核心的工作机制,这是指智能体在没有用户输入的情况下,自主重复执行推理和工具调用的过程,比如说我们的claude code:
下面是Agent Loop实现的伪代码:
public String execute() {
List<String> results = new ArrayList<>();
while (currentStep < MAX_STEPS && !isFinished) {
currentStep++;
// 实现具体的步骤逻辑
String stepResult = Step();
results.add("步骤 " + currentStep + ": " + stepResult);
}
if (currentStep >= MAX_STEPS) {
results.add("达到最大步骤数: " + MAX_STEPS);
}
return String.join("\n", results);
}
ReAct模式
ReAct是一种结合推理和行动的智能体架构,”思考 - 行动 - 观察” 的循环,目的是通过交互式决策解决复杂任务:
核心思想:
推理(Reason):将原始问题拆分为多步骤任务,明确当前要执行的步骤,比如 “第一步需要打开编程导航网站”。
行动(Act):调用外部工具执行动作,比如调用搜索引擎、打开浏览器访问网页等。
观察(Observe):获取工具返回的结果,反馈给智能体进行下一步决策。比如将打开的网页代码输入给 AI。
循环迭代:不断重复上述 3 个过程,直到任务完成或达到终止条件。
三. OpenManus实现原理
接下来我们来了解一下OpenManus源码中的整体架构

| 目录 / 文件 | 核心作用 |
|---|---|
agent/ |
智能体核心逻辑(规划、记忆、推理) |
daytona/ |
Daytona 沙箱集成(安全代码执行环境) |
flow/ |
任务流编排(多步骤 / 多智能体协作) |
mcp/ |
MCP(Multi-Component Protocol)服务器 / 组件管理 |
prompt/ |
提示词模板、工具描述 |
sandbox/ |
代码沙箱 / 安全运行环境 |
tool/ |
工具调用实现(搜索、分析、浏览器等) |
utils/ |
通用工具函数、日志、格式化 |
__init__.py |
Python 包初始化,带版本检查 |
bedrock.py |
AWS Bedrock LLM 客户端 |
config.py |
全局配置(API Key、参数、开关) |
exceptions.py |
自定义异常定义 |
llm.py |
大模型客户端封装 |
logger.py |
日志系统配置 |
schema.py |
数据模型 / 消息结构定义 |
那么了解了整个文件夹的组织形式后,我们来看看agent这个智能体核心包
agent智能体核心包
在agent目录中,采用了分层的代理架构,不同层次的代理负责代理不同的功能,这样对于后续实现更多的智能体就够方便的扩展

OpenManus的代理架构包含以下几层:
- BaseAgent:基础代理抽象类,定义了所有代理的状态管理和执行循环
ReActAgent:实现 ReAct 模式的代理,具有思考(Think)和行动(Act)
ToolCallAgent:能够调用工具的代理,继承自 ReActAgent 并扩展了工具调用能力
Manus:具体实现的智能体实例,集成了所有能力并添加更多专业工具
tool工具调用包
在tool 目录定义了各种各样的工具,比如网页搜索、文件操作、询求用户帮助、代码执行器等等:

| 文件名 | 核心作用 | 关键信息 |
|---|---|---|
__init__.py |
工具包入口 | 提交记录显示在做 pre-commit 格式化优化 |
ask_human.py |
人机交互工具 | 为 Manus 智能体添加了主动询问用户的能力,支持在关键节点请求用户确认 / 输入 |
base.py |
工具基类 | 所有工具的抽象父类,定义了通用接口(如 run()、validate() 等) |
bash.py |
Bash 命令执行工具 | 用于执行 Shell 命令,支持文件操作、系统交互,提交记录提到与 SWEAgent 相关 |
browser_use_tool.py |
浏览器操作工具 | 封装了网页浏览、点击、输入等自动化操作,更新了工具描述 _BROWSER_DESCRIPTION |
computer_use_tool.py |
计算机操作工具 | 类似 OpenAI 的 Computer Use,支持模拟键鼠操作、桌面自动化 |
crawl4ai.py |
网页爬虫工具 | 基于 Crawl4AI 实现的网页内容抓取工具,支持结构化提取 |
create_chat_completion.py |
LLM 对话补全工具 | 项目初始化时创建,用于直接调用 LLM 生成文本 |
file_operators.py |
文件操作工具 | 提供文件读写、复制、删除等操作,移除了构造函数以简化实现 |
mcp.py |
MCP 协议工具 | 对接 MCP 服务的工具,修复了工具名称以兼容 OpenAI API 规范 |
planning.py |
规划工具 | 支持任务拆解、步骤规划,更新了工具调用逻辑和说明文档 |
python_execute.py |
Python 代码执行工具 | 在沙箱中运行 Python 代码,支持数据分析、脚本执行 |
str_replace_editor.py |
文本替换编辑器 | 提供字符串级别的文件编辑功能,修复了部分 Bug |
terminate.py |
任务终止工具 | 用于标记任务完成 / 失败,新增了 max_steps 限制防止无限循环 |
tool_collection.py |
工具集合管理 | 管理所有工具的注册与去重,避免 MCP 服务器重复提供工具 |
web_search.py |
网络搜索工具 | 支持通用搜索和深度研究(DeepResearch),可获取外部信息 |
prompt提示词模板包
prompt 目录定义了整个项目中可能会用到的提示词

| 文件名 | 核心作用 | 关键信息 |
|---|---|---|
__init__.py |
提示词模块入口 | 项目初始化文件,负责导出各个智能体的提示词 |
browser.py |
浏览器智能体提示词 | 为浏览器操作场景定义指令,新增了 terminate 相关逻辑,用于在合适时机结束任务 |
manus.py |
主智能体(Manus)提示词 | 项目核心智能体的提示词模板,合并了人机交互(human interaction)功能 |
mcp.py |
MCP 协议智能体提示词 | 为 MCP 服务交互场景提供专用提示词 |
planning.py |
规划智能体提示词 | 定义任务拆解、步骤规划的指令,修复了思考过程过长、步骤冗余的问题 |
swe.py |
软件工程智能体提示词 | 为代码开发、调试场景定义指令,修复了 SWEAgent 的相关 Bug |
toolcall.py |
工具调用智能体提示词 | 项目初始化时创建,定义工具调用的通用规则与格式 |
visualization.py |
可视化 / 图表生成提示词 | 为数据可视化场景定义指令,回滚了之前优化文件名的改动 |
比如说planning中的提示词:
中文翻译:
PLANNING_SYSTEM_PROMPT = """
你是一名专业的**规划智能体**,擅长通过结构化方案高效解决问题。
你的职责是:
1. 分析用户请求,明确任务范围
2. 利用 `planning` 工具制定清晰、可执行的计划,确保每一步都能带来有效进展
3. 根据需要调用可用工具执行步骤
4. 跟踪任务进度,并在必要时调整计划
5. 任务完成后立即使用 `finish` 结束任务
可用工具会随任务变化,可能包括:
- `planning`:创建、更新、跟踪计划(命令:create、update、mark_step 等)
- `finish`:任务完成时结束执行
将任务拆分为逻辑清晰、结果明确的步骤,避免过度细化或拆分多余子步骤。
考虑步骤依赖关系与验证方法。
知道何时结束任务——目标达成后无需继续思考。
"""
NEXT_STEP_PROMPT = """
根据当前状态,你的下一步行动是什么?
选择最高效的推进方式:
1. 当前计划是否足够?是否需要优化?
2. 是否可以立即执行下一步?
3. 任务是否已完成?如果完成,立即使用 `finish`。
推理过程请简洁明了,然后选择合适的工具或行动。 """
在这段提示词中实际上就是CoT和ReAct思想的一种实现
1. 它包含 CoT(思维链)
提示词要求:
分析任务
拆解步骤
按逻辑推理
结构化思考
这就是 CoT 的核心:分步思考、链式推理。
2. 它包含 ReAct(推理 + 行动)
提示词要求:
用工具执行(planning /finish)
跟踪进度
动态调整计划
思考 → 行动 → 再思考
这就是 ReAct 的核心:Reason + Act 循环。
其他支持
为了实现完整的智能体功能,OpenManus还需要依赖以下几个关键组件:
记忆系统:使用 Memory 类存储对话历史和中间状态
LLM 大模型:通过 LLM 类提供思考和决策能力
工具系统:提供 BaseTool 和 ToolCollection 类扩展智能体的能力边界
流程控制:通过 AgentState 和执行循环管理状态转换和任务流程
虽然在现有的框架中,这些功能都帮我们封装好, 但是在OpenManus中,这些组件都是自主实现的
四. 智能体核心实现
了解整体架构后,我们重点学习 Agent 分层代理架构。
BaseAgent
BaseAgent 是所有代理的基础,定义了代理状态管理和执行循环的核心逻辑。在这一层的核心就是Agent Loop的实现,通过while实现循环,并且定义了死循环检查机制:

在这里的分层设计中,使用了模板方法设计模式,在BaseAgent中定义执行流程,具体的方法(step)交给子类去实现
ReActAgent
在这一层首先继承上层的BaseAgent类,然后实现step方法,最重要的是这一层实现了ReActAgent模式,将代理的执行过程分为思考和行动两种关键步骤:
那么在这一层依然是使用了模板方法模式,这种的思考和怎么行动,任然是交给子类去进行实现
ToolCallAgent
ToolCallAgent 在 ReAct 模式的基础上增加了工具调用能力,是 OpenManus 最重要的一个层次。

class ToolCallAgent(ReActAgent):
"""Base agent class for handling tool/function calls with enhanced abstraction"""
name: str = "toolcall"
description: str = "an agent that can execute tool calls."
system_prompt: str = SYSTEM_PROMPT
next_step_prompt: str = NEXT_STEP_PROMPT
available_tools: ToolCollection = ToolCollection(
CreateChatCompletion(), Terminate()
)
tool_choices: TOOL_CHOICE_TYPE = ToolChoice.AUTO # type: ignore
special_tool_names: List[str] = Field(default_factory=lambda: [Terminate().name])
tool_calls: List[ToolCall] = Field(default_factory=list)
_current_base64_image: Optional[str] = None
max_steps: int = 30
max_observe: Optional[Union[int, bool]] = None
async def think(self) -> bool:
"""Process current state and decide next actions using tools"""
if self.next_step_prompt:
user_msg = Message.user_message(self.next_step_prompt)
self.messages += [user_msg]
try:
# Get response with tool options
response = await self.llm.ask_tool(
messages=self.messages,
system_msgs=(
[Message.system_message(self.system_prompt)]
if self.system_prompt
else None
),
tools=self.available_tools.to_params(),
tool_choice=self.tool_choices,
)
except ValueError:
raise
except Exception as e:
# Check if this is a RetryError containing TokenLimitExceeded
if hasattr(e, "__cause__") and isinstance(e.__cause__, TokenLimitExceeded):
token_limit_error = e.__cause__
logger.error(
f"🚨 Token limit error (from RetryError): {token_limit_error}"
)
self.memory.add_message(
Message.assistant_message(
f"Maximum token limit reached, cannot continue execution: {str(token_limit_error)}"
)
)
self.state = AgentState.FINISHED
return False
raise
self.tool_calls = tool_calls = (
response.tool_calls if response and response.tool_calls else []
)
content = response.content if response and response.content else ""
# Log response info
logger.info(f"✨ {self.name}'s thoughts: {content}")
logger.info(
f"🛠️ {self.name} selected {len(tool_calls) if tool_calls else 0} tools to use"
)
if tool_calls:
logger.info(
f"🧰 Tools being prepared: {[call.function.name for call in tool_calls]}"
)
logger.info(f"🔧 Tool arguments: {tool_calls[0].function.arguments}")
try:
if response is None:
raise RuntimeError("No response received from the LLM")
# Handle different tool_choices modes
if self.tool_choices == ToolChoice.NONE:
if tool_calls:
logger.warning(
f"🤔 Hmm, {self.name} tried to use tools when they weren't available!"
)
if content:
self.memory.add_message(Message.assistant_message(content))
return True
return False
# Create and add assistant message
assistant_msg = (
Message.from_tool_calls(content=content, tool_calls=self.tool_calls)
if self.tool_calls
else Message.assistant_message(content)
)
self.memory.add_message(assistant_msg)
if self.tool_choices == ToolChoice.REQUIRED and not self.tool_calls:
return True # Will be handled in act()
# For 'auto' mode, continue with content if no commands but content exists
if self.tool_choices == ToolChoice.AUTO and not self.tool_calls:
return bool(content)
return bool(self.tool_calls)
except Exception as e:
logger.error(f"🚨 Oops! The {self.name}'s thinking process hit a snag: {e}")
self.memory.add_message(
Message.assistant_message(
f"Error encountered while processing: {str(e)}"
)
)
return False
async def act(self) -> str:
"""Execute tool calls and handle their results"""
if not self.tool_calls:
if self.tool_choices == ToolChoice.REQUIRED:
raise ValueError(TOOL_CALL_REQUIRED)
# Return last message content if no tool calls
return self.messages[-1].content or "No content or commands to execute"
results = []
for command in self.tool_calls:
# Reset base64_image for each tool call
self._current_base64_image = None
result = await self.execute_tool(command)
if self.max_observe:
result = result[: self.max_observe]
logger.info(
f"🎯 Tool '{command.function.name}' completed its mission! Result: {result}"
)
# Add tool response to memory
tool_msg = Message.tool_message(
content=result,
tool_call_id=command.id,
name=command.function.name,
base64_image=self._current_base64_image,
)
self.memory.add_message(tool_msg)
results.append(result)
return "\n\n".join(results)
Manus
Manus 类是 OpenManus 的核心智能体实例,集成了各种工具和能力:

五. 自主实现Manus智能体
再上方介绍的OpenManus都是在实现智能体所需支持的系统,但是在使用AI开发框架下,这些能力都不用我们自己进行实现,下面我们就基于Spring AI框架,实现一个简化版的Manus智能体(重在设计思路)
首先我们定义数据模型来记录当前智能体的状态
/**
* 代理执行状态的枚举类
*/
public enum AgentState {
/**
* 空闲状态
*/
IDLE,
/**
* 运行中状态
*/
RUNNING,
/**
* 已完成状态
*/
FINISHED,
/**
* 错误状态
*/
ERROR
}
开发BaseAgent类
/**
* 抽象基础代理类,用于管理代理状态和执行流程。
*
* 提供状态转换、内存管理和基于步骤的执行循环的基础功能。
* 子类必须实现step方法。
*/
@Data
@Slf4j
public abstract class BaseAgent {
// 核心属性
private String name;
// 提示
private String systemPrompt;
private String nextStepPrompt;
// 状态
private AgentState state = AgentState.IDLE;
// 执行控制
private int maxSteps = 10;
private int currentStep = 0;
// LLM
private ChatClient chatClient;
// Memory(需要自主维护会话上下文)
private List<Message> messageList = new ArrayList<>();
/**
* 运行代理
*
* @param userPrompt 用户提示词
* @return 执行结果
*/
public String run(String userPrompt) {
if (this.state != AgentState.IDLE) {
throw new RuntimeException("Cannot run agent from state: " + this.state);
}
if (StringUtil.isBlank(userPrompt)) {
throw new RuntimeException("Cannot run agent with empty user prompt");
}
// 更改状态
state = AgentState.RUNNING;
// 记录消息上下文
messageList.add(new UserMessage(userPrompt));
// 保存结果列表
List<String> results = new ArrayList<>();
try {
for (int i = 0; i < maxSteps && state != AgentState.FINISHED; i++) {
int stepNumber = i + 1;
currentStep = stepNumber;
log.info("Executing step " + stepNumber + "/" + maxSteps);
// 单步执行
String stepResult = step();
String result = "Step " + stepNumber + ": " + stepResult;
results.add(result);
}
// 检查是否超出步骤限制
if (currentStep >= maxSteps) {
state = AgentState.FINISHED;
results.add("Terminated: Reached max steps (" + maxSteps + ")");
}
return String.join("\n", results);
} catch (Exception e) {
state = AgentState.ERROR;
log.error("Error executing agent", e);
return "执行错误" + e.getMessage();
} finally {
// 清理资源
this.cleanup();
}
}
/**
* 执行单个步骤
*
* @return 步骤执行结果
*/
public abstract String step();
/**
* 清理资源
*/
protected void cleanup() {
// 子类可以重写此方法来清理资源
}
}
开发ReActAgent类
继承自 BaseAgent,并且将 step 方法分解为 think 和 act 两个抽象方法
/**
* ReAct 模式的代理抽象类
* 实现了思考-行动的循环模式
*/
@EqualsAndHashCode(callSuper = true)
@Data
public abstract class ReActAgent extends BaseAgent {
/**
* 处理当前状态并决定下一步行动
*
* @return 是否需要执行行动,true表示需要执行,false表示不需要执行
*/
public abstract boolean think();
/**
* 执行决定的行动
*
* @return 行动执行结果
*/
public abstract String act();
/**
* 执行单个步骤:思考和行动
*
* @return 步骤执行结果
*/
@Override
public String step() {
try {
boolean shouldAct = think();
if (!shouldAct) {
return "思考完成 - 无需行动";
}
return act();
} catch (Exception e) {
// 记录异常日志
e.printStackTrace();
return "步骤执行失败: " + e.getMessage();
}
}
}
开发ToolCallAgent类
ToolCallAgent 负责实现工具调用能力,继承自 ReActAgent,具体实现了 think 和 act 两个抽象方法。
/**
* 处理工具调用的基础代理类,具体实现了 think 和 act 方法,可以用作创建实例的父类
*/
@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
public class ToolCallAgent extends ReActAgent {
// 可用的工具
private final ToolCallback[] availableTools;
// 保存了工具调用信息的响应
private ChatResponse toolCallChatResponse;
// 工具调用管理者
private final ToolCallingManager toolCallingManager;
// 禁用内置的工具调用机制,自己维护上下文
private final ChatOptions chatOptions;
public ToolCallAgent(ToolCallback[] availableTools) {
super();
this.availableTools = availableTools;
this.toolCallingManager = ToolCallingManager.builder().build();
// 禁用 Spring AI 内置的工具调用机制,自己维护选项和消息上下文
this.chatOptions = DashScopeChatOptions.builder()
.withProxyToolCalls(true)
.build();
}
ChatOptions chatOptions = ToolCallingChatOptions.builder()
.toolCallbacks(new CustomerTools())
.internalToolExecutionEnabled(false)
.build();
/**
* 处理当前状态并决定下一步行动
*
* @return 是否需要执行行动
*/
@Override
public boolean think() {
if (getNextStepPrompt() != null && !getNextStepPrompt().isEmpty()) {
UserMessage userMessage = new UserMessage(getNextStepPrompt());
getMessageList().add(userMessage);
}
List<Message> messageList = getMessageList();
Prompt prompt = new Prompt(messageList, chatOptions);
try {
// 获取带工具选项的响应
ChatResponse chatResponse = getChatClient().prompt(prompt)
.system(getSystemPrompt())
.tools(availableTools)
.call()
.chatResponse();
// 记录响应,用于 Act
this.toolCallChatResponse = chatResponse;
AssistantMessage assistantMessage = chatResponse.getResult().getOutput();
// 输出提示信息
String result = assistantMessage.getText();
List<AssistantMessage.ToolCall> toolCallList = assistantMessage.getToolCalls();
log.info(getName() + "的思考: " + result);
log.info(getName() + "选择了 " + toolCallList.size() + " 个工具来使用");
String toolCallInfo = toolCallList.stream()
.map(toolCall -> String.format("工具名称:%s,参数:%s",
toolCall.name(),
toolCall.arguments())
)
.collect(Collectors.joining("\n"));
log.info(toolCallInfo);
if (toolCallList.isEmpty()) {
// 只有不调用工具时,才记录助手消息
getMessageList().add(assistantMessage);
return false;
} else {
// 需要调用工具时,无需记录助手消息,因为调用工具时会自动记录
return true;
}
} catch (Exception e) {
log.error(getName() + "的思考过程遇到了问题: " + e.getMessage());
getMessageList().add(
new AssistantMessage("处理时遇到错误: " + e.getMessage()));
return false;
}
}
/**
* 执行工具调用并处理结果
*
* @return 执行结果
*/
@Override
public String act() {
if (!toolCallChatResponse.hasToolCalls()) {
return "没有工具调用";
}
// 调用工具
Prompt prompt = new Prompt(getMessageList(), chatOptions);
ToolExecutionResult toolExecutionResult = toolCallingManager.executeToolCalls(prompt, toolCallChatResponse);
// 记录消息上下文,conversationHistory 已经包含了助手消息和工具调用返回的结果
setMessageList(toolExecutionResult.conversationHistory());
// 当前工具调用的结果
ToolResponseMessage toolResponseMessage = (ToolResponseMessage) CollUtil.getLast(toolExecutionResult.conversationHistory());
String results = toolResponseMessage.getResponses().stream()
.map(response -> "工具 " + response.name() + " 完成了它的任务!结果: " + response.responseData())
.collect(Collectors.joining("\n"));
// 判断是否调用了终止工具
boolean terminateToolCalled = toolResponseMessage.getResponses().stream()
.anyMatch(response -> "doTerminate".equals(response.name()));
if (terminateToolCalled) {
setState(AgentState.FINISHED);
}
log.info(results);
return results;
}
}
开发 Manus 类
/**
* 拥有自主规划能力的超级智能体
*/
@Component
public class SunnyManus extends ToolCallAgent {
public SunnyManus(ToolCallback[] allTools, ChatModel dashscopeChatModel) {
super(allTools);
this.setName("sunnyManus");
String SYSTEM_PROMPT = """
You are SunnyManus, an AI assistant with autonomous planning capabilities.
## Core Principles
1. **Plan first, execute second**: Before using any tool, think about the overall approach.
2. **Break down complex tasks**: Split multi-step tasks into clear subtasks.
3. **Use the right tool**: Choose the most appropriate tool for each subtask.
4. **Verify results**: After each tool execution, verify the result before proceeding.
5. **Terminate when done**: Call the terminate tool when the task is complete.
## Available Tools
You have access to file operations, terminal commands, web search, web scraping,
PDF generation, resource download, and image search tools.
## Output Format
- Clearly explain your reasoning before each action.
- Summarize what each tool returned.
- Suggest next steps after each action.
""";
this.setSystemPrompt(SYSTEM_PROMPT);
String NEXT_STEP_PROMPT = """
Based on user needs, proactively select the most appropriate tool or combination of tools.
For complex tasks, you can break down the problem and use different tools step by step to solve it.
After using each tool, clearly explain the execution results and suggest the next steps.
If you want to stop the interaction at any point, use the `terminate` tool/function call.
""";
this.setNextStepPrompt(NEXT_STEP_PROMPT);
this.setMaxSteps(20);
// 初始化客户端
ChatClient chatClient = ChatClient.builder(dashscopeChatModel)
.defaultAdvisors(new MyLoggerAdvisor())
.build();
this.setChatClient(chatClient);
}
}
编写测试案例:
package com.sunny.springaiagent.agent;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ManusTest {
@Resource
private SunnyManus sunnyManus;
@Test
void run() {
String usermessage = "我的另一半居住在上海静安区,请帮我找到 5 公里内合适的约会地点,并结合网络图片(需要网络图片的url),指定一份详细约会计划,并生成pdf";
String answer = sunnyManus.run(usermessage);
System.out.println(answer);
Assertions.assertNotNull(answer);
}
}

以上就是我们debug看到的智能体运行结果啦,执行完成后,可以看到每一步的执行结果,并且可以在本地查看到已下载的图片和生成的 PDF。那么到这里我们就算是基于Spring Ai框架的帮助下自主实现了一个基础版Manus啦,本期的核心重点在于Manus的设计思想,感谢大家的观看~ 
更多推荐




所有评论(0)