Jmanus 定位是 java 版本的 manus 实现。

试运行

  1. 配置 jdk 等环境
  2. 拉取源码 https://github.com/spring-ai-alibaba/JManus
  3. 配置好环境变量 DASHSCOPE_API_KEY (百炼大模型 api-key)
  4. 直接运行 OpenManusSpringBootApplication.main,会自动弹出 web 页面 http://localhost:18080/,代表项目已启动完成

查看数据库

通过 http://localhost:18080/h2-console 访问默认的 h2 数据库,用户名和密码可以在 src/main/resources/application-h2.yml 文件中找到

源码学习

在页面上点击“查询股价”,程序会依次执行下列步骤:

  1. 自动下载浏览器
  2. 打开浏览器
  3. 输入查询内容并点击搜索
  4. 打开结果页面,爬取页面内容
  5. 生成最终结果报告

可以通过开发者工具发现调用了后端的 /api/executor/executeByToolNameAsync 接口,请求参数如下

{
    "toolName":"default-plan-id-001000222",
    "replacementParams":{
        "userRequirement":"用浏览器基于百度,查询今天阿里巴巴的股价,并返回最新股价"
    },
    "isVueRequest":true
}

该接口为异步接口,结果通过 /api/executor/details/{planId} 接口获取。

接口逻辑

数据预处理

  • 获取 toolName 入参,此处值为 default-plan-id-001000222
  • 通过 isVueRequest 参数判断是前端调用还是 http 接口调用,此处为 true
  • 通过 toolName 获取 planTemplateId,此处是 null,默认使用 toolName 作为 planTemplateId
  • 获取 conversationId 入参,此处为 null,默认生成一个前缀为 conversation- 的会话id,并保存 memory
  • 获取 uploadedFiles 入参,此处为 null
  • 获取 uploadKey 入参,此处为 null
  • 获取 replacementParams 入参,此处为一个 Map,包含一个键值对,"userRequirement":"用浏览器基于百度,查询今天阿里巴巴的股价,并返回最新股价"

数据处理2

生成前缀为 plan- 的 planId

根据 planTemplateId 获取 planTemplate 的最大版本号

根据 planTemplateId 和 最大版本号获取 json 格式的 planTemplate,此处结果如下

{
  "planType" : "dynamic_agent",
  "currentPlanId" : null,
  "rootPlanId" : null,
  "planTemplateId" : "default-plan-id-001000222",
  "title" : "默认的用户输入(不要删除这个计划)",
  "userRequest" : "Execute default_user_input plan using zh language",
  "directResponse" : false,
  "steps" : [ {
    "stepRequirement" : "<<userRequirement>>",
    "agentName" : "ConfigurableDynaAgent",
    "selectedToolKeys" : null,
    "modelName" : "",
    "terminateColumns" : ""
  } ],
  "result" : null
}

使用输入的 userRequirement 替换掉 json 中的占位符 <<userRequirement>>,生成 Plan

组装计划执行器

根据 Plan 中的 directResponse 和 planType 组装对应的计划执行器

  1. 若 directResponse 为 true,则生成 DirectResponseExecutor;
  2. 若 planType 为 simple,则生成 PlanExecutor;
  3. 若 planType 为 advanced,则生成 MapReducePlanExecutor;
  4. 若 planType 为 dynamic_agent,则生成 DynamicToolPlanExecutor;
  5. 其他则默认为 PlanExecutor

此处为 DynamicToolPlanExecutor

异步业务逻辑(AbstractPlanExecutor.executeAllStepsAsync)

  1. 保存计划执行记录 PlanExecutionRecord,completed 属性为 false;
  2. 保存智能体执行记录 AgentExecutionRecord,状态为 IDLE
  3. 执行 Plan 中的每一个步骤 Step
    1. 根据 Step 相关属性组装 BaseAgent,这里是子类 ConfigurableDynaAgent,若配置文件中 agent.init 设置为 true(默认为 true),则添加工具到 ConfigurableDynaAgent 中,包括浏览器、数据库、终端、Bash、Text文件操作器、表单输入工具;若是开启无限上下文(默认关闭),还会添加定时工具和 Markdown 转换器(这里还注释掉了许多工具,如谷歌搜索或 python 执行器,可能是仍然在测试中);若是配置了 Mcp(默认无),也会添加 Mcp 作为工具
    2. 更新 AgentExecutionRecord 状态、开始时间、Step序号等属性,状态为 RUNNING
    3. 进入 BaseAgent,执行子类 ReactAgent 的 step 方法,分为 think 和 act 两步,首先执行子类 DynamicAgent 的 think 方法
      1. 首先是收集上一步工具执行后的结果,此时是第一步,所以结果为空
      2. 构造提示词
        SystemMessage{textContent='<SystemInfo>
        - SYSTEM INFORMATION:
        OS: Windows 11 10.0 (amd64)
        
        - Current Date:
        2025-10-05
        
        - User Original Requirements (This requirement is the user's initial input, information can be referenced, but in the current interaction round only the current step requirements need to be completed!) :
        默认的用户输入(不要删除这个计划)
        Execute default_user_input plan using zh language
        
        
        - Execution Parameters: 
        No execution parameters provided.
        
        - Historical Executed Step Records:
        
        
        - Current step requirements (this step needs to be completed by you! Required by the user's original request, but if not required in the current step, no need to complete in this step):
        STEP 0: 用浏览器基于百度,查询今天阿里巴巴的股价,并返回最新股价
        
        - Operation step instructions:
        
        Important Notes:
        1. When using tool calls, no additional explanations are needed!
        2. Do not provide reasoning or descriptions before tool calls!
        
        3. Do only and exactly what is required in the current step requirements
        4. If the current step requirements have been completed, call the terminate tool to finish the current step.
        5. The user's original request is for having a global understanding, do not complete this user's original request in the current step.
        
        
        </SystemInfo>
        
        <AgentInfo>
        Based on the current environment information and prompt to make a next step decision
        </AgentInfo>
        ', messageType=SYSTEM, metadata={messageType=SYSTEM}}
        
        UserMessage{content='- Current step environment information:
        
        ', properties={messageType=USER, current_step_env_data=true}, messageType=USER}
      3. 给 ChatClient 添加工具并获取响应结果,注意 internalToolExecutionEnabled 被设置为 false,代表禁止自动调用工具,工具的调用需要应用程序显式处理

        ChatResponse [
          metadata=
          {
            id: chatcmpl-0528175a-26d2-428d-9bef-72b41119d7f6,
            usage: DefaultUsage
          [
            promptTokens=0,
            completionTokens=0,
            totalTokens=0
          ],
          rateLimit
          :
          org.springframework.ai.chat.metadata.EmptyRateLimit@3855ded8
          },
          generations=
          [
            Generation
            [
              assistantMessage=AssistantMessage
              [
                messageType=ASSISTANT,
                toolCalls=
                [
                  ToolCall
                  [
                    id=call_ff29780b343649308ae635,
                    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-0528175a-26d2-428d-9bef-72b41119d7f6
                }
              ],
              chatGenerationMetadata=DefaultChatGenerationMetadata
              [
                finishReason=
                'TOOL_CALLS',
                filters=0,
                metadata=0
              ]
            ]
          ]
        ]
      4. 可以看出,大模型返回结果是要调用名为 browser_use 的工具

      5. 添加思考行动记录 ThinkActRecord

    4. 然后是 DynamicAgent 的 act 方法
      1. 执行工具,此处执行 BrowserUseTool 工具,打开浏览器并导航到百度搜索页
      2. 记录执行结果 ActToolParam
    5. BaseAgent 会不断循环 step 方法,即不断进行 think、act,直到超过最大步数限制或状态变更为 completed
      1. 第二次进行 step,think 方法首先获取上一步执行后的环境信息,包括页面的各种链接和元素等,将 browser_use 的执行结果和执行后环境信息加入消息中,大模型返回结果的工具调用部分如下,可以看出这次仍然是调用 browser_use,只是执行动作由导航变为输入文本
        ToolCall[
        id=call_39ab72cb9fac49b48fa1d6, 
        type=function, 
        name=browser_use, 
        arguments={"action": "input_text", "index": 13, "text": "阿里巴巴 股价"}
        ]
      2. 执行完后第三次进入 step 方法,thingk 方法获取到上一步搜索的各种结果链接,大模型返回的工具调用参数中 arguments={"action": "click", "index": 45},也就是点击 index 为 45 的网页
      3. 执行完后第四次进入 step 方法,think 方法获取到两个tab页以及第一个tab页的各种链接,大模型返回的工具调用参数中 arguments={"action": "get_text"},获取文本
      4. 执行完后第五次进入 step 方法,大模型返回的工具调用参数如下
        ToolCall[
          id=call_1b8139a5ae6345b0a485c9,
          type=function,
          name=terminate,
          arguments=
          {
            "message": "根据查询结果,阿里巴巴-W(股票代码:09988)在2025年10月3日的收盘价为185.100港元。该股价较前一日上涨2.000港元,涨幅为1.09%。最新信息显示,公司股价创近四年来新高,获得南向资金青睐,摩根大通已将其港股目标价上调近45%,预测还有约30%上涨空间。"
          }
        ]

        工具执行完后,由于 toolName 为 terminate,退出标志 shouldTerminate 设置为 true,状态变更为 completed,退出 BaseAgent 的循环

    6. 更新 AgentExecutionRecord 状态、结束时间、Step序号等属性,状态为 FINISHED

生成总结

最后再根据分步执行的结果和用户原始问题,生成总结

总结

从上述流程逻辑来看,Jmanus 至少将数据模型分为了5个层次

  1. PlanTemplate:计划模板,定义了某种计划的框架,内含占位符,不能实际执行
  2. Plan:使用用户输入替换了计划模板中的占位符生成的计划,可以执行,内含一个或多个 Step
  3. Step:计划中的一环,完成一个子目标,可能需要多次 思考+行动 才能完成
  4. think + act:Step 中的一次迭代,没有明确定义为一个实体,实际就是一次大模型调用加一次工具调用
  5. toolCall:工具调用,虽然实际调用时每次大模型返回的都只有一个工具调用,但实际是支持在一次 act 中调用多个工具的

其中 think + act 和 toolCall 的执行次数不确定,取决于大模型的决策,其他层次的执行次数则取决于 PlanTemplate 的配置

整体流程大概是:

通过 PlanTemplate 生成 Plan,然后对 Plan 中的每一个 Step,执行多次 think + act,最后将所有 Step 的执行结果进行一个总结。

ReAct:对于 Step 的每一个 think + act 循环,其实就是应用的 Agent 设计模式中的 ReAct 模式,该模式包含思考、行动、观察三个部分

  • 思考(Thought):展示推理过程,明确任务目标和前置条件。

  • 行动(Act):生成与外部交互的指令,执行具体操作。

  • 观察(Obs):获取执行结果,为下一步推理提供依据。

附图:最终执行结果

Logo

更多推荐