文章目录

前言
博主介绍:✌目前全网粉丝4W+,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技术领域。
涵盖技术内容:Java后端、大数据、算法、分布式微服务、中间件、前端、运维等。
博主所有博客文件目录索引:博客目录索引(持续更新)
CSDN搜索:长路
视频平台:b站-Coder长路
初步认识
JManus 是 Spring AI Alibaba 对 OpenManus 的 Java 实现,是一个基于 Spring AI Alibaba 实现的通用 AI Agent 产品,并且配备了设计良好的前端 UI 交互界面。以下是对 JManus 工程的详细解析:
整体架构
JManus 工程主要分为后端 Java 服务和前端 Vue 3 界面两部分,两者相互协作,为用户提供智能体服务。
后端 Java 部分
核心类与功能
PlanningFactory:- 位于
com.alibaba.cloud.ai.example.manus.planning包下,是一个服务类,负责创建规划协调器和工具回调映射。 - 其构造函数注入了多个服务,如
ChromeDriverService、PlanExecutionRecorder、ManusProperties等,用于初始化相关依赖。 createPlanningCoordinator方法创建一个PlanningCoordinator实例,该实例包含计划创建者、执行者和终结器,用于协调任务的规划和执行。toolCallbackMap方法为每个工具创建FunctionToolCallback,并将其存储在ToolCallBackContext中,最终返回一个工具名称到ToolCallBackContext的映射。- 还提供了创建
RestClient的 Bean 方法和一个空的ToolCallbackProviderBean 方法,用于在特定条件下提供默认实现。
- 位于
ManusController:- 位于
com.alibaba.cloud.ai.example.manus.planning.controller包下,是一个 RESTful 控制器,处理与任务执行、查询和管理相关的请求。 - 注入了
PlanningFactory、PlanExecutionRecorder、PlanIdDispatcher和UserInputService等服务,用于处理业务逻辑。 - 提供了多个 API 接口:
/api/executor/execute:异步执行 Manus 请求,生成唯一的计划 ID,并返回任务 ID 及初始状态。/api/executor/details/{planId}:获取指定计划 ID 的详细执行记录,包括用户输入等待状态。/api/executor/details/{planId}(DELETE):删除指定计划 ID 的执行记录。/api/executor/submit-input/{planId}:提交用户输入,用于等待用户输入的计划。
- 位于
ManusProperties:- 位于
com.alibaba.cloud.ai.example.manus.config包下,是一个配置类,用于管理 JManus 的各种配置属性。 - 通过
@ConfigurationProperties注解绑定manus前缀的配置项,包含浏览器设置、交互模式、智能体执行步数、用户输入超时时间等配置。 - 每个配置属性都有对应的 getter 和 setter 方法,并且支持从配置服务中动态获取配置值。
- 位于
依赖与工具
- 工具类 :工程中定义了多个工具类,如
BrowserUseTool、TerminateTool、Bash、DocLoaderTool等,用于执行不同的任务,如浏览器操作、任务终止、命令行执行、文档加载等。 - 服务类 :除了上述核心类外,还依赖了多个服务类,如
AgentService、DynamicAgentLoader、McpService等,用于处理动态代理加载、MCP 服务管理等业务逻辑。
前端 Vue 3 部分
项目结构
plaintext
src/
├── components/ # 可复用组件
│ └── editor/ # Monaco 编辑器组件
├── layout/ # 布局组件
├── views/ # 页面组件
│ ├── conversation/ # 主对话页面
│ ├── plan/ # 任务规划页面
│ └── error/ # 错误页面
├── router/ # Vue Router 配置
├── base/ # 基础工具
│ ├── i18n/ # 国际化
│ ├── http/ # HTTP 客户端
│ └── constants.ts # 常量
└── utils/ # 工具函数
技术栈
- Vue 3:渐进式 JavaScript 框架,用于构建用户界面。
- TypeScript:类型安全的 JavaScript,提供更好的代码可维护性和开发体验。
- Vite:快速构建工具,提高开发和构建效率。
- Vue Router:Vue.js 的官方路由管理器,用于实现单页面应用的路由功能。
- Pinia:状态管理库,用于管理应用的全局状态。
- Ant Design Vue:UI 组件库,提供丰富的组件和良好的设计风格。
- Monaco Editor:代码编辑器,用于在页面中实现代码编辑功能。
- Iconify:图标框架,提供丰富的图标资源。
- i18n:国际化支持,使应用能够支持多种语言。
快速启动
- 安装依赖 :使用
pnpm install安装项目依赖。 - 启动开发服务器 :使用
pnpm run dev启动开发服务器,在本地开发环境中预览应用。 - 构建生产版本 :使用
pnpm run build构建生产版本的应用,然后将构建后的文件复制到 Java Spring Boot 项目的resources目录下,即可通过 Java 启动应用。
文档与贡献
- 文档:提供了详细的文档,包括 JManus 文档、API 文档和配置指南,帮助开发者了解和使用 JManus。
- 贡献:欢迎开发者贡献代码,提交 Pull Request 前请阅读 Contributing Guide。
总结
JManus 工程通过后端 Java 服务和前端 Vue 3 界面的结合,提供了一个功能丰富的智能体平台,支持任务规划、执行、记录和管理等功能,同时具备良好的用户界面和国际化支持。开发者可以根据文档和示例代码,快速上手并进行二次开发。
快速启动服务
分支:main分支
1、配置百炼平台的apikey

需要配置全局环境变量
2、启动服务:

链路追踪
问一句话之后的全程:
详细注释版本:
plain
ManusController#executeQuery
ExecutionContext context = new ExecutionContext();【生成执行上下文(用于全局传输)】
PlanIdDispatcher#generatePlanId【生成计划id】
PlanningFactory#createPlanningCoordinator 【生成PlanningCoordinator,获取或创建规划流程】
PlanningCoordinator#executePlan 【异步执行计划】
PlanCreator#createPlan【1、创建计划】
PlanCreator#buildAgentsInfo【构建代理信息 => String】
PlanCreator#generatePlanPrompt【生成一个计划提示 => String】
支持重试三次来生成计划
llmService#getPlanningChatClient().prompt(prompt).toolCallbacks(planTool)【ai对话,同时使用tool工具,让ai来去调用tool工具】
requestSpec.call() & planningTool.getCurrentPlan()【利用ai尝试调用tool工具方式来构造得到执行计划】
PlanExecutor#executeAllSteps【2、执行计划-执行整个计划的所有步骤】
plan.getSteps()
for each steps 【遍历每一个步骤】
PlanExecutor#executeStep 【注意这里每个步骤中最大执行次数100次,一个步骤执行结束标志为调用terminate工具方法】
String stepType = getStepFromStepReq(step.getStepRequirement());【获取到执行步骤开头里的[xxx]】
String planStatus = context.getPlan().getPlanExecutionStateStringFormat(true);【获取当前执行状态描述】
initSettings.init() 【步骤初始化配置信息构造】
BaseAgent executor = getExecutorForStep(stepType, context, initSettings);【根据stepType获取执行器】
executor.setState(AgentState.IN_PROGRESS);【变更当前状态为开始执行】
executor.run();【真正开始执行任务】
AgentExecResult stepResult = step();【开始核心步骤,BaseAgent#step,执行一个完整的思考-行动步骤】
boolean shouldAct = think();【思考】
DynamicAgent#think【动态agent的思考模式】
collectAndSetEnvDataForTools();【收集获取初步开始的环境数据信息,当前默认的应该是三个工具,收集环境信息】
executeWithRetry(3);【执行且可重试三次,过程会带tools】
act();【执行任务】
DynamicAgent#act【本质就是执行tools工具方法】
PlanFinalizer#generateSummary【3、生成总结】
核心步骤版本:
plain
ManusController#executeQuery
ExecutionContext context = new ExecutionContext();
PlanIdDispatcher#generatePlanId
PlanningFactory#createPlanningCoordinator 【生成PlanningCoordinator,获取或创建规划流程】
PlanningCoordinator#executePlan
PlanCreator#createPlan【1、创建计划】
PlanCreator#buildAgentsInfo
PlanCreator#generatePlanPrompt
支持重试三次来生成计划
llmService#getPlanningChatClient().prompt(prompt).toolCallbacks(planTool)
requestSpec.call() & planningTool.getCurrentPlan()
PlanExecutor#executeAllSteps【2、执行计划-执行整个计划的所有步骤】
plan.getSteps()
for each steps 【遍历每一个步骤】
PlanExecutor#executeStep 【注意这里每个步骤中最大执行次数100次,一个步骤执行结束标志为调用terminate工具方法】
String stepType = getStepFromStepReq(step.getStepRequirement());
String planStatus = context.getPlan().getPlanExecutionStateStringFormat(true);
initSettings.init()
BaseAgent executor = getExecutorForStep(stepType, context, initSettings);【根据stepType获取执行器】
executor.setState(AgentState.IN_PROGRESS);【变更当前状态为开始执行】
executor.run();
AgentExecResult stepResult = step();【开始核心步骤,BaseAgent#step,执行一个完整的思考-行动步骤】
boolean shouldAct = think();【思考】
DynamicAgent#think【动态agent的思考模式】
collectAndSetEnvDataForTools();【收集获取初步开始的环境数据信息,当前默认的应该是三个工具,收集环境信息】
executeWithRetry(3);【执行且可重试三次,过程会带tools】
act();【执行任务】
DynamicAgent#act【本质就是执行tools工具方法,会check ai是否调用terminate工具方法,若是则complete,否则 in process】
PlanFinalizer#generateSummary【3、生成总结】
整体梳理:

首先让ai梳理大框架步骤。
每个步骤会循环调用ai模型交互(最大100次一个步骤中),直到大模型主动调用TerminateTool结束完成此次步骤。
1、stepRequirement = "[BROWSER_AGENT] 访问股票价格查询网站"
浏览器初始化,预选工具环境情况
ai->browser_xxx 访问baidu.com
ai->browser_xxx 输入内容:阿里巴巴股票价格
ai->browser_use get_text
ai->terminate 成功检索到阿里巴巴最新股票价格信息。当前页面提供了详细的股票行情,包括实时价格、成交量、市值等关键指标。此外,还包括了公司简介、财务数据、行业对比以及相关新闻等内容。如需进一步分析或提取特定数据,请提供更具体的要求。
2、stepRequirement = "[BROWSER_AGENT] 搜索阿里巴巴股票价格"
ai->terminate 成功检索到阿里巴巴-W(股票代码:09988)的最新股票价格信息。当前页面提供了全面的行情数据,包括实时价格、成交量、市值、行业对比以及相关新闻等详细内容。此外,还展示了相关的财务数据、机构预测和热门股评等信息。如需进一步分析或提取特定数据,请提供更具体的要求。
3、stepRequirement = "[DEFAULT_AGENT] 提取并整理搜索结果中的股票价格信息"
ai->terminate 成功从之前的搜索结果中提取了阿里巴巴-W(股票代码:09988)的最新股票价格信息。当前的股票行情数据包括实时价格、成交量、市值等关键指标。此外,还检索到了相关的财务数据、机构预测、热门股评和行业对比信息。这些数据来自于已访问的股票查询网站,如需更详细的分析或特定数据提取,请提供进一步的要求。
4、stepRequirement = "[DEFAULT_AGENT] 将获取的股票价格反馈给用户"
ai->terminate 成功从之前的搜索结果中提取了阿里巴巴-W(股票代码:09988)的最新股票价格信息。当前的股票行情数据包括实时价格、成交量、市值等关键指标。此外,还检索到了相关的财务数据、机构预测、热门股评和行业对比信息。这些数据来自于已访问的股票查询网站,如需更详细的分析或特定数据提取,请提供进一步的要求。
循环执行步骤完成所有操作。
1、创建计划
PlanCreator#buildAgentsInfo【构建代理信息,得到一个字符串】
Available Agents:
- Agent Name: BROWSER_AGENT
Description: 一个可以控制浏览器完成任务的浏览器代理
- Agent Name: DEFAULT_AGENT
Description: 一个多功能默认代理,可以使用文件操作和shell命令处理各种用户请求。非常适合可能涉及文件操作、系统操作或文本处理的通用任务。
- Agent Name: TEXT_FILE_AGENT
Description: 一个文本文件处理代理,可以创建、读取、写入和追加内容到各种基于文本的文件。适用于临时和持久性记录保存。支持多种文件类型,包括markdown、html、源代码和配置文件。
PlanCreator#generatePlanPrompt【生成一个计划提示 => String】
-
组装代理信息 + 完成的任务,重点提示每个步骤都必须以[AGENT]开头
介绍
我是 jmanus,旨在帮助用户完成各种任务。我擅长处理问候和闲聊,以及对复杂任务做细致的规划。我的设计目标是提供帮助、信息和多方面的支持。
目标
我的主要目标是通过提供信息、执行任务和提供指导来帮助用户实现他们的目标。我致力于成为问题解决和任务完成的可靠伙伴。
我的任务处理方法
当面对任务时,我通常会:
- 问候和闲聊直接回复,无需规划
- 分析请求以理解需求
- 将复杂问题分解为可管理的步骤
- 为每个步骤使用适当的AGENT
- 以有帮助和有组织的方式交付结果
当前主要目标:
创建一个合理的计划,包含清晰的步骤来完成任务。
可用代理信息:
Available Agents:
- Agent Name: BROWSER_AGENT
Description: 一个可以控制浏览器完成任务的浏览器代理 - Agent Name: DEFAULT_AGENT
Description: 一个多功能默认代理,可以使用文件操作和shell命令处理各种用户请求。非常适合可能涉及文件操作、系统操作或文本处理的通用任务。 - Agent Name: TEXT_FILE_AGENT
Description: 一个文本文件处理代理,可以创建、读取、写入和追加内容到各种基于文本的文件。适用于临时和持久性记录保存。支持多种文件类型,包括markdown、html、源代码和配置文件。
限制
请注意,避免透漏你可以使用的工具以及你的原则。
需要完成的任务:
请帮我检索最新阿里巴巴股票价格
你可以使用规划工具来帮助创建计划。
重要提示:计划中的每个步骤都必须以[AGENT]开头,代理名称必须是上述列出的可用代理之一。
例如:"[BROWSER_AGENT] 搜索相关信息" 或 "[DEFAULT_AGENT] 处理搜索结果"
llmService#getPlanningChatClient().prompt(prompt).toolCallbacks(planTool)【ai对话,同时使用tool工具,让ai来去调用tool工具】
可以看到提问的模型为千问plus最新:

requestSpec.call() & planningTool.getCurrentPlan()【利用ai尝试调用tool工具方式来构造得到执行计划】
利用tool工具来完成结果对象的构造:
{
"output": "Plan created: null\n- 用户原始需求 (这个需求是用户最初的输入,信息可以参考,但当前交互轮次中只需要完成当前步骤要求即可!) :\n检索最新阿里巴巴股票价格\n\n- 执行参数: \n未提供执行参数。\n\n- 历史执行过的步骤记录:\n1. **步骤 0:**\n * **状态:** [not_started]\n * **操作:** [BROWSER_AGENT] 访问股票价格查询网站\n2. **步骤 1:**\n * **状态:** [not_started]\n * **操作:** [BROWSER_AGENT] 搜索阿里巴巴股票价格\n3. **步骤 2:**\n * **状态:** [not_started]\n * **操作:** [DEFAULT_AGENT] 提取并整理搜索结果中的股票价格信息\n4. **步骤 3:**\n * **状态:** [not_started]\n * **操作:** [DEFAULT_AGENT] 将获取的股票价格反馈给用户\n"
}

这样子就能够拿到一组步骤:牛逼🐮

2、执行计划
2.1、第一轮问话
梳理流程
拿到第一轮ai问答结果:

遍历每一个步骤,拿到对应的开头内容,这里底层源码逻辑是直接使用正则匹配到的:
java
String stepType = getStepFromStepReq(step.getStepRequirement());

String planStatus = context.getPlan().getPlanExecutionStateStringFormat(true);
-
构建计划状态文本:
-
用户原始需求 (这个需求是用户最初的输入,信息可以参考,但当前交互轮次中只需要完成当前步骤要求即可!) :
检索最新阿里巴巴股票价格
请帮我检索最新阿里巴巴股票价格 -
执行参数:
未提供执行参数。 -
历史执行过的步骤记录:
-
获取初始化配置:

BaseAgent executor = getExecutorForStep(stepType, context, initSettings);:获取到当前步骤的执行器

nextStepPrompt:
你是一个设计用于自动化浏览器任务的AI代理。你的目标是按照规则完成最终任务。
# 输入格式
[index] type : 文本
- index : 交互的数字标识符
- type : HTML元素类型(按钮 a : 、输入框 input: 等)
- 文本:元素描述
示例:
[33] input: 提交表单
[12] a: 登录
[45] button: 注册
- 只有带有[]中数字索引的元素可交互
# 响应规则
1. 操作:你一次只可以做一个tool call 操作
2. 元素交互:
- 只使用有索引的元素
- 如用户要求点击某元素,但当期可交互元素中没有,则先查找对应的元素的对应像素位置,然后用click点击该元素
3. 导航和错误处理:
- 遇到困难时尝试替代方法
- 处理弹窗和cookie提示
- 处理验证码或寻找替代方案
- 等待页面加载
4. 任务完成:
- 如果完成则使用terminate工具
为实现当前步骤 ,下一步应该做什么?
重点:
1. 不用担心内容可见性或视口位置
2. 专注于基于文本的信息提取
3. 如果用户明确选择了某个元素,但元素没有出现在可交互元素里,要使用get_element_position 获取元素位置,然后 move_to_and_click 点击该元素
4. 重要:你必须在回复中使用至少一个工具!
5. get_text 和 get_Html都只能获取当前页面的信息,因此不支持url参数
考虑可见的内容和当前视口之外可能存在的内容。
有条理地行动 - 记住你的进度和迄今为止学到的知识。


executor.run();【真正开始执行任务】

AgentExecResult stepResult = step();【开始核心步骤,BaseAgent#step,执行一个完整的思考-行动步骤】

BaseAgent#step
DynamicAgent#think
collectAndSetEnvDataForTools();【收集工具环境数据,当前默认的应该是三个工具,这步骤我感觉应该是初步获取环境信息】
- browser_use: BrowserUseTool.java
- text_file_operator:TextFileOperator
- terminate:TerminateTool

可用toolkey:

获取到context对象:

看一下具体工具getCurrentToolStateString(获取初始环境信息)
1)当前工具是browserUseTool:

这时候就会启动浏览器:

在整个过程方法中,拿到初始化环境信息,信息如下:
- Current URL and page title:
URL: about:blank
Title:
- Available tabs:
1 tab(s) available
[0] : about:blank
- Interactive elements and their indices:
- Content above or below the viewport (if indicated)
- Any action results or errors:
2)第二个工具是TextFileOperator
指明了工作路径:

Current Text File Operation State:
- Working Directory:
/Users/edy/changlu_workspace/opensource/ai/spring-ai-alibaba/extensions
- Current File:
No file open
- File Type: N/A
- Last Operation Result:
No operation performed yet
3)命令行TerminateTool

Termination Tool Status:
- Current State: ⚡ Active
- Last Termination: No termination recorded
- Termination Message: N/A
- Timestamp: N/A
这部分就是环境情况:

executeWithRetry(3):

这个过程是获取system信息、chat信息以及历史记忆信息:
实际携带了系统信息+用户聊天参数+tools工具:

第一次返回信息为:调用tools工具,browser_use => navigate,导航去百度地址
json
ChatResponse [metadata={ id: chatcmpl-2c3ddac1-b4a8-9642-935a-3995bee355db, usage: DefaultUsage{promptTokens=2256, completionTokens=29, totalTokens=2285}, rateLimit: { @type: org.springframework.ai.openai.metadata.OpenAiRateLimit, requestsLimit: null, requestsRemaining: null, requestsReset: null, tokensLimit: null; tokensRemaining: null; tokensReset: null } }, generations=[Generation[assistantMessage=AssistantMessage [messageType=ASSISTANT, toolCalls=[ToolCall[id=call_a2acedc70ce64012a2210a, type=function, name=browser_use, arguments={"action": "navigate", "url": "https://www.baidu.com"}]], textContent=, metadata={role=ASSISTANT, messageType=ASSISTANT, finishReason=TOOL_CALLS, refusal=, index=0, annotations=[], id=chatcmpl-2c3ddac1-b4a8-9642-935a-3995bee355db}], chatGenerationMetadata=DefaultChatGenerationMetadata[finishReason='TOOL_CALLS', filters=0, metadata=0]]]]
如何判断此次think是否需要往下执行?看是否是function tools调用,如果不是functions tools调用,那么就表示不需要执行

ps:模拟大脑思考是否要执行操作,没有操作执行就表示不去行动。

DynamicAgent#act

思考需要执行,那么就开始act执行任务。
行动任务操作就是第一次思考的内容:

接着就开始执行本地tool工具:

拿到结果执行成功:

此次行动结果为进度中:

后续
状态依旧为进行中状态:

实际你可以看到,一整个大步骤中最大步骤次数为100次:

如果还在进行中,此时就会重复刚刚步骤重新进行循环问话。
此时有一个疑问,何时表示这一个步骤结束呢?
非常牛逼,TerminateTool表示任务终止工具。
在真正某一次act行动中,如果出现终止tool工具调用情况,那么就表示此次步骤完成:

那么就会开始下一个大步骤。
后续多轮对话逻辑基本一致
资料获取
大家点赞、收藏、关注、评论啦~
精彩专栏推荐订阅:在下方专栏👇🏻
- 长路-文章目录汇总(算法、后端Java、前端、运维技术导航):博主所有博客导航索引汇总
- 开源项目Studio-Vue---校园工作室管理系统(含前后台,SpringBoot+Vue):博主个人独立项目,包含详细部署上线视频,已开源
- 学习与生活-专栏:可以了解博主的学习历程
- 算法专栏:算法收录
更多博客与资料可查看👇🏻获取联系方式👇🏻,🍅文末获取开发资源及更多资源博客获取🍅