XAgent ReACT 框架深度解析:实现细节、提示词设计与通用方案对比
本文聚焦 XAgent Inner Loop 中的
ReACTChainSearch,从源码级别拆解其「推理---行动---观察」闭环如何落地,完整收录 ToolAgent 提示词与 function schema,并与论文 ReACT、LangChain、OpenAI Agents 等通用方案做对照。适合已读过task_handler.py外层循环、希望深入理解单个子任务如何被 ReACT 驱动的工程师。
1. 背景:ReACT 在 XAgent 中的位置
1.1 双层循环
XAgent 把任务执行拆成两层:
text
Outer Loop (task_handler.outer_loop)
├── PlanAgent 生成 / refine 计划树
└── 对每个 TODO 子任务:
Inner Loop (task_handler.inner_loop)
└── ReACTChainSearch.generate_chain()
└── 直到 subtask_submit 或步数耗尽
Outer Loop 管「做什么、顺序如何、失败后怎么改计划」;Inner Loop 管「当前这一个子任务怎么靠工具做完」。
1.2 入口代码
inner_loop 是 ReACT 的唯一入口:
python
# XAgent/workflow/task_handler.py
search_method = ReACTChainSearch(xagent_core_components=self.xagent_core)
arguments = function_manager.get_function_schema('action_reasoning')['parameters']
search_method.run(
config=self.config,
agent=agent, # ToolAgent,RequiredAbilities.tool_tree_search
arguments=arguments,
functions=self.function_handler.intrinsic_tools(self.config.enable_ask_human_for_help),
task_id=task_ids_str,
now_dealing_task=self.now_dealing_task,
plan_agent=self.plan_agent,
)
执行完成后,now_dealing_task.process_node = search_method.get_finish_node(),submit 结果挂在 Plan 节点上,供 Outer Loop 的 posterior_process 和 plan_refine_mode 使用。
1.3 命名与实现的落差
类名 ReACTChainSearch、TaskSearchTree 暗示「树搜索」,但实现是 单链 ReACT:
- 每步只扩展一个子节点(
make_father_relation) - 无分支、无 backtracking、无 value-based 选优
max_try默认为 1,几乎不重试整条链
准确说法:Chain-based ReACT,不是 MCTS 或 Best-of-N 搜索。
2. 核心类:ReACTChainSearch
文件:XAgent/inner_loop_search_algorithms/ReACT.py
2.1 类职责
| 成员 | 作用 |
|---|---|
tree_list |
每次 generate_chain 追加一棵 TaskSearchTree(支持多次 attempt,默认只用 1 次) |
finish_node |
链终止时的 ToolNode(submit 节点或最后一步工具节点) |
need_for_plan_refine |
从 subtask_submit 解析出的 refine 标志,供 Outer Loop 使用 |
status |
SUCCESS / FAIL / HAVE_AT_LEAST_ONE_ANSWER |
2.2 run() vs generate_chain()
python
def run(self, ...):
for _attempt_id in range(max_try): # 默认 max_try=1
self.generate_chain(...)
if self.status == SearchMethodStatusCode.HAVE_AT_LEAST_ONE_ANSWER:
self.status = SearchMethodStatusCode.SUCCESS
else:
self.status = SearchMethodStatusCode.FAIL
run() 只做重试包装和最终状态归一;所有 ReACT 语义在 generate_chain() 的 while 循环里。
3. generate_chain:逐步拆解
3.1 循环骨架
python
def generate_chain(self, config, agent, arguments, functions, task_id, now_dealing_task, plan_agent):
self.tree_list.append(TaskSearchTree())
now_attempt_tree = self.tree_list[-1]
now_node = now_attempt_tree.root # 空 ToolNode,depth=0
while now_node.get_depth() < config.max_subtask_chain_length: # 默认 15
# ① 可选:人工中断改写 thoughts
# ② make_message:拼 Observation 历史
# ③ 读 workspace 文件结构
# ④ ToolAgent.parse:Reason + Act(一次 LLM 调用)
# ⑤ message_to_tool_node
# ⑥ FunctionHandler.handle_tool_call:执行
# ⑦ 挂树、推 UI、now_node 下移
# ⑧ submit 则 break
self.finish_node = now_node
默认配置(assets/gpt-3.5-turbo_config.yml):
yaml
max_subtask_chain_length: 15
max_retry_times: 3
enable_summary: true
enable_ask_human_for_help: False
3.2 单步数据流
4. Re / Act / Ob 在 XAgent 里分别是什么
这是理解 XAgent ReACT 的关键:三个字母都在,但形态与论文不同。
4.1 Reason(Re)--- 同一次 function call 里的 schema 字段
模型被强制调用 subtask_handle(或最后一步的 subtask_submit),在 同一个 JSON 里必须先填:
| 字段 | schema 描述 | 字数提示 |
|---|---|---|
plan |
下一步宏观计划 | array,约 30 词 |
thought |
内部推理,从前步结果学习并纠错 | 约 50 词 |
reasoning |
为什么给出该 thought | 约 100 词 |
criticism |
对当前 thought/plan 的 constructive 自我批评 | 无硬上限 |
tool_call |
实际工具名 + 参数 | --- |
来源:XAgent/ai_functions/pure_functions/task_handle_functions.yml
此外,inner_loop 还把 action_reasoning 的 parameters merge 进 function schema(与 Plan refine 里 merge simple_thought 是同一套 BaseAgent.generate 机制)。在 OpenAI 路径下 ToolAgent.parse 会把 arguments=None,推理字段完全由 subtask_handle schema 承载。
日志输出(Re 的可视化)在 core.print_assistant_thoughts:
python
# THOUGHTS / REASONING / PLAN / CRITICISM 分别打印
assistant_thoughts = assistant_reply_json_valid.get("thoughts", {}).get("properties", {})
结论:Reason 不是单独一轮 LLM,而是 Act 之前的 mandatory structured fields。
4.2 Act(Act)--- tool_call 或 subtask_submit
ToolAgent.message_to_tool_node 拆分 message:
python
new_node.data['thoughts']['properties'] = message["arguments"] # Re 部分
new_node.data["command"]["properties"]["name"] = function_call["name"] # Act 部分
new_node.data["command"]["properties"]["args"] = function_call["arguments"]
OpenAI 路径的特殊处理:真实外部工具不直接作为顶层 function,而是嵌在 subtask_handle.tool_call 里。ToolAgent.parse 会:
- 从
functions里滤掉subtask_submit、subtask_handle - 把可用工具 schema 追加进 system prompt 文本
- 只保留
[subtask_submit, subtask_handle]两个顶层 function - 解析后把
tool_call拆出来 变成真正的function_call
这是为兼容早期 OpenAI function calling 限制的 hack,也是 XAgent ReACT 与「标准 tool use」差异最大的地方之一。
FunctionHandler.handle_tool_call 路由:
command_name |
行为 |
|---|---|
| 外部工具名 | toolserver_interface.execute_command_client |
subtask_submit |
解析 success / refine 建议,不访问 ToolServer |
ask_human_for_help |
interaction.ask_for_human_help |
| 空 | 视为成功,无输出 |
4.3 Observe(Ob)--- 写入 ToolNode,下轮经 make_message 喂回
执行后:
python
# function_handler.py
node.data["tool_output"] = command_result
node.data["tool_status_code"] = tool_output_status_code
node.history.add("system", f"Command {command_name} returned: {command_result}", "action_result")
下一轮,make_message 从当前节点沿父链收集历史:
python
# node.py --- ToolNode.process
def process(self):
data = []
now_node = self
while now_node.father != None:
data = [now_node.data] + data
now_node = now_node.father
return data
make_message 生成两条 user 消息:
python
# 消息 1:当前子任务完整描述
now_subtask_prompt = f'''Now you will perform the following subtask:\n"""\n{terminal_task_info}\n"""\n'''
# 消息 2:已执行步骤(含 tool_output 摘要)
user_prompt = f"""The following steps have been performed (you have already done the following and the current file contents are shown below):\n
{action_process}
"""
若 enable_summary=True,action_process = summarize_action(action_process, terminal_task_info),会对每一步调用 summarize_action、actions_reflection 等 LLM 摘要,再按 token 预算拼接 [return]。
结论:Observation 不以 Observation: 文本标签出现,而是下一轮 prompt 里的 user 上下文注入。
5. 完整提示词(ToolAgent)
来源:XAgent/agent/tool_agent/prompt.py
Dispatcher 默认使用以下模板(占位符由 fill_in_placeholders 替换)。
5.1 SYSTEM_PROMPT(全文)
text
You are an experimental cutting-edge super capable autonomous agent specialized in learning from environmental feeback and following rules to do correct and efficient actions.
Your decisions must always be made independently without seeking user assistance.
You can interactive with real world through tools, all your tool call will be executed in a isolated docker container with root privilege. Don't worry about the security and try your best to handle the task.
As a Super Agent build with super powerful tools, you are capable of handling any given task, thus your capabilities are far above regular simple AI or LLM.
--- Your Workflow ---
1. You will first be given a task (query) together with a plan to handle it.
2. Then you will handle one of the subtasks. Steps:
- Decide what action should be taken next:
- If the action is something like text understanding, text classification, text analyzing, do it on your own and use FileSystem tools to write down your answer.
- If not, try your best to use available tools to do it. Ask user for help when you face problems. Chat with former autonomous agent when you have problems or when you get confused about what other autonomous agent have done.
- After decide the action, call functions to apply action.
3. After you reached all subtask goals, you must use FileSystemEnv to write a task report contains all information for goals before submit the subtask.
4. Finally, call `subtask_submit` to submit the subtask and give the detailed suggestions about the future planning.
--- Resources ---
- Internet access for searches and information gathering, write down the knowledge you get.
- A FileSystemEnv to read and write files (text, code, markdown, latex...), always write down detailed content as it will help further actions.
- A python notebook to execute python code. Always follow python coding rules. Contains libs like numpy, pandas, matplotlib, sklearn, etc.
- A ShellEnv with root privilege to execute bash command to further achieve complex goals. The shell is a powerful tool, you can use it to install packages, download files or dataset, run programs, async debugging, etc.
- Ask for help to human if needed, you can only use `ask_for_human_help` function to ask for help, never use file system to write down your question to human.
--- Maximum Your Performance ---
1. Continuously review and analyze your actions to ensure you are performing to the best of your abilities.
2. Constructively self-criticize your big-picture behavior constantly.
3. Reflect on past decisions and strategies to refine your approach.
4. Every command has a cost, so be smart and efficient. Aim to complete tasks in the least number of steps.
5. When generating function call, please check the json format carefully.
5.1 Please remember to generate the function call field after the "criticism" field.
5.2 Please check all content is in json format carefully.
*** Important Rules ***
- You must follow your workflow.
- You are more than a Large Language Model (LLM), you have the capability to do acutal things rather than simply give guidance or write text.
- With the help of tools, you can do nearly everything. You can not only write guides or code, but can also use the tools to actually do the task like setup service or develop complex program.
- If the task is something like text understanding, classification, analyzing, etc, do it on your own and use FileSystem tools to write down your answer, don't use external tools or execute codes.
- Do not use python notebook to process text, you can process text by yourself.
- You can only give up when the tools are insufficient.
- You must pass literal and concrete value to tools, do not use reference or pointer, labels.
- Always use a tool efficiently, reduce the number of steps as much as possible.
- File system struture is printed every time, do not print_filesystem_structure again.
- Submit the subtask immediately if no further actions needed.
- Run any program with the shell if you need, you have the full control of you docker container. You are not limited.
- You can doing any task with the help of given tools, even developing complex programs or configure complex develop environment.
- Only use ask_for_human_help to ask for help, do not use file system or any other tools to write down your question to human.
--- Plan Overview ---
The query has already been splited into a tree based plan as follows:
{{all_plan}}
You have already performed some of the subtasks.
占位符 {{all_plan}} :每轮由 generate_chain 填入,来自 plan_agent.latest_plan.to_json(),可经 summarize_plan 压缩。
5.2 USER_PROMPT(全文)
text
Now, it's your turn give the next function call (please output all the necessary parameters for the function call).
--- Status ---
Current Subtask: {{subtask_id}}
File System Structure: {{workspace_files}}
--- Available Operations ---
- Use tools to handle the subtask and interact with real world.
- Use "subtask_submit" only when you achieve all milestones of the current subtask or you make sure it's impossible with the given tools. Remember, you should also given suggestions to plan rectify agent, So he can rectify the plan after you submit the current subtask.
*** Important Notice ***
- You can at most use {{max_length}} steps of tool calls. After that you must use "subtask_submit". This is the {{step_num}}'th step now, watch out the budget.
- If milestone is too hard to achieve, you can use "subtask_submit" to give up the subtask and divide it into smaller subtasks.
- You always have the ability to solve the given task, just have a try and explore possible solution if necessary and use the tools efficiently.
{{human_help_prompt}}
Now show your super capability as a super agent that beyond regular AIs or LLMs!
运行时占位符:
| 占位符 | 来源 |
|---|---|
subtask_id |
now_dealing_task.get_subtask_id() |
workspace_files |
FileSystemEnv_print_filesys_struture(截断 1000 token) |
max_length |
config.max_subtask_chain_length |
step_num |
now_node.get_depth() + 1 |
human_help_prompt |
是否允许 ask_human_for_help |
5.3 最终 messages 组装顺序
ToolAgent.parse 与 PlanRefineAgent 相同:
python
messages = prompt_messages[:additional_insert_index] + additional_messages + prompt_messages[additional_insert_index:]
# additional_insert_index = -1
实际顺序:
text
[system] SYSTEM_PROMPT(含 all_plan、OpenAI 路径下还追加 Available Tools JSON)
[user] make_message 第 1 条:当前 subtask 描述
[user] make_message 第 2 条:已执行步骤 + tool 返回
[user] USER_PROMPT(含 subtask_id、workspace、步数预算)
OpenAI 路径还会在 messages[0]['content'] 末尾动态拼接:
text
--- Avaliable Tools ---
You are allowed to use tools in the "subtask_handle.tool_call" function field.
Remember the "subtask_handle.tool_call.tool_input" field should always in JSON...
{tools JSON schema}
6. Function Schema 完整定义
6.1 subtask_handle(普通一步:Re + Act)
yaml
# task_handle_functions.yml
- name: subtask_handle
description: give some reason together with a tool call.
parameters:
properties:
plan:
type: array
items:
type: string
description: "Max 1 items about what to do next. Around 30 words."
thought:
type: string
description: "internal reasoning and thoughts, learn from the former results and correct your action. Around 50 words."
reasoning:
type: string
description: "Why you give the `thought`. Around 100 words."
criticism:
type: string
description: "constructive self-criticism of the current thought and plan on its weakness and strength."
tool_call:
type: object
required: [tool_name]
properties:
tool_name:
type: string
enum: [] # 运行时由 change_subtask_handle_function_enum 填充
tool_input:
anyOf: [object, string]
required: ["plan", "thought", "reasoning", "criticism", "tool_call"]
6.2 subtask_submit(终止一步:提交 + 驱动 Outer Loop)
yaml
- name: subtask_submit
parameters:
properties:
result:
properties:
conclusion: string # ~400 words
milestones: array[string]
success: boolean
submit_type:
enum: [give_answer, give_up, max_tool_call, human_suggestion]
suggestions_for_latter_subtasks_plan:
properties:
need_for_plan_refine: boolean
reason: string # ~50 words,给 PlanRefineAgent
required: ["submit_type", "result", "suggestions_for_latter_subtasks_plan"]
subtask_submit 同时承担:
- Inner Loop 退出信号
- Outer Loop 状态更新(SUCCESS / FAIL)
need_for_plan_refine→ 是否进入plan_refine_mode
6.3 action_reasoning(merge 用,OpenAI 路径下被 bypass)
yaml
# reasoning.yml --- inner_loop 传入 arguments,但 ToolAgent 在 openai 模式下置 arguments=None
required: ["plan", "thought", "reasoning", "criticism"]
7. 退出条件与强制策略
7.1 正常退出
python
if tool_output_status_code == ToolCallStatusCode.SUBMIT_AS_SUCCESS:
self.status = SearchMethodStatusCode.HAVE_AT_LEAST_ONE_ANSWER
break
elif tool_output_status_code == ToolCallStatusCode.SUBMIT_AS_FAILED:
break
SUBMIT_AS_SUCCESS:子任务标记 SUCCESS,可能触发 plan refineSUBMIT_AS_FAILED:子任务标记 FAIL,同样可能 refine(例如请求 split)
7.2 步数耗尽强制 submit
python
if now_node.get_depth() == config.max_subtask_chain_length - 1:
function_call = {"name": "subtask_submit"}
倒数第二步(depth=13,max=15)起 只能 调用 subtask_submit,防止无限工具循环。
7.3 人工中断(可选)
python
if now_node.father != None and interaction.interrupt:
receive_data = interaction.receive(can_modify)
data, rewrite_flag = self.rewrite_input_func(now_node.data, receive_data)
now_node.data = data # 改写 thought/reasoning/plan/criticism
根节点(depth=0)不检查 interrupt;从第二步起用户可注入建议改写当前步思考,但不直接改 tool 参数。
8. Observation 压缩:summarize_action
当 enable_summary=true(默认开启),历史 Observation 不是 raw tool_output 全量灌回,而是经 summarize_action 多级压缩:
- 逐步格式化:
[thought]、[tool calling]、[return] - 每步调用 LLM
summarize_action生成 summary + description - 调用
actions_reflection提取 key_actions 和 suggestions - 按 token 预算(
max_return_length: 8192)优先保留关键步的完整 return
这对长 ReACT 链至关重要:Observation 层本身又是一层 LLM 摘要系统,不是简单字符串拼接。
9. ToolNode 数据结构
python
# node.py
self.data = {
"content": "",
"thoughts": {
"properties": {
"thought": "",
"reasoning": "",
"plan": "",
"criticism": "",
},
},
"command": {
"properties": {
"name": "", # 工具名或 subtask_submit
"args": "",
},
},
"tool_output": "",
"tool_status_code": ToolCallStatusCode.TOOL_CALL_SUCCESS,
}
self.history: MessageHistory = MessageHistory()
ReACT 链在 TaskSearchTree 上表现为:
text
root (空节点, depth=0)
└── step1 ToolNode (thoughts + command + tool_output)
└── step2 ToolNode
└── ...
└── submit ToolNode (finish_node)
10. 与通用 ReACT 方案对比
10.1 对照总表
| 维度 | 论文 ReACT | LangChain ReAct Agent | OpenAI Assistants / Responses API | XAgent ReACTChainSearch |
|---|---|---|---|---|
| 输出格式 | 自由文本 Thought/Action/Observation |
文本或 tool calls | 原生 tools + tool_outputs 多轮 |
嵌套 subtask_handle function call |
| Reason 与 Act | 分两行文本 | 通常同轮或分两轮 | 分轮:assistant tool_calls → tool role | 同一次 JSON:thought + tool_call |
| Observation 回放 | 追加为 assistant/user 文本 | Message history | 官方 tool role message |
user 消息注入(make_message + summarize) |
| 计划上下文 | 无 | 可选 AgentExecutor + planner | 可选 instructions | 强制 system 里嵌 full plan tree |
| 终止 | 模型输出 Finish | 自定义 stop | 模型停止调 tool | 强制 subtask_submit + 步数上限 |
| 失败后 | 同链继续 | 同链或重跑 | 同 thread 继续 | submit → Outer Loop refine Plan |
| 工具协议 | 文本 Action | LangChain Tool | OpenAI tools schema | ToolServer HTTP + 嵌套 JSON |
| 搜索 | 单链 | 单链为主 | 单链 | 名含 Search,实际单链 |
10.2 论文 ReACT(Yao et al.)
经典格式:
text
Thought 1: ...
Action 1: Search[entity]
Observation 1: ...
Thought 2: ...
XAgent 差异:
- 没有
Thought:/Action:/Observation:文本标签 - Reason 是 schema 字段,Act 是
tool_call,Ob 是下轮 user 上下文 - 多了 plan tree、submit 协议、plan refine 闭环
- 多了 Docker 沙箱、文件系统快照每轮注入
XAgent 优势: 结构化程度高,便于录制和 UI 展示;与 function calling 时代模型对齐。
XAgent 劣势: ReACT 语义被掩盖在 function call 里;Observation 非标准 chat 格式,对部分模型不一定最优。
10.3 LangChain create_react_agent
典型模式:
python
# 概念示意
agent = create_react_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, max_iterations=N)
executor.invoke({"input": task})
特点:
- Tools 直接注册为 LangChain Tool 对象
- Prompt 模板显式含
{tools}、{tool_names}、agent_scratchpad agent_scratchpad自动拼接 Thought/Action/Observation 或 tool messages
对比 XAgent:
| 点 | LangChain | XAgent |
|---|---|---|
| scratchpad | 框架自动维护 | 手动 make_message + ToolNode.process |
| 推理字段 | 通常只有 Thought | thought + reasoning + plan + criticism 四字段 |
| 提交语义 | 无标准 subtask_submit | submit 带 success/refine 建议,接 Outer Loop |
| 工具层 | 进程内 Python 函数 | 远程 ToolServer Docker |
XAgent 更像 带计划树的企业级 ReACT Runtime ,LangChain ReAct 更像 轻量单任务循环。
10.4 OpenAI 现代 Tool Use(Chat Completions / Agents SDK)
标准多轮:
text
user: 任务
assistant: tool_calls: [{name, arguments}]
tool: {tool_call_id, content: 结果}
assistant: tool_calls: [...] 或 最终回答
对比 XAgent:
- OpenAI:
tool是独立 role,Observation 语义清晰 - XAgent:Observation 塞进
additional_messages的 user 文本;OpenAI 路径还把真实 tools 降级 为subtask_handle.tool_call嵌套
XAgent 的嵌套是为解决「每轮既要推理字段又要调工具」且兼容旧 API 的折中;现代 API 可直接:
python
response = client.chat.completions.create(
messages=history,
tools=[...], # 每个工具顶层注册
)
或用 Structured Output 分离 reasoning JSON 与 tool calls。
10.5 Plan-and-Execute / LangGraph
Plan-and-Execute 典型拆法:
text
Planner LLM → 静态步骤列表
For each step:
Executor LLM + tools
Replanner(可选)→ 改计划
XAgent 等价映射:
| Plan-and-Execute | XAgent |
|---|---|
| Planner | PlanGenerateAgent |
| Executor | ReACTChainSearch + ToolAgent |
| Replanner | PlanRefineAgent(仅改未来节点) |
| Step list | Plan 树(中序遍历) |
XAgent 的 ReACT 绑死在 Plan 节点上 :每轮 system prompt 带 整棵 plan 树,不是只给当前 step。上下文更重,但有利于避免 subtask 间目标漂移。
10.6 AutoGPT / BabyAGI 系
早期自主 Agent 常用:
text
命令 JSON:{"command": "web_search", "args": {...}}
或文本:NEXT ACTION: ...
与 XAgent 相似点:structured command + 环境反馈循环。
差异:XAgent 有显式 Plan 树、submit/refine 协议、ToolServer 沙箱、录制回放;AutoGPT 系更扁平,计划常是内存里的 todo list。
11. XAgent ReACT 的设计取舍总结
11.1 做得好的地方
- Re + Act 合一:一步 LLM 调用拿齐推理与动作,latency 低于严格三步分离。
- 强制反思字段:schema 层保证每步有 thought/criticism,不是可选 CoT。
- Observation 摘要 :
summarize_action解决长链 context 爆炸。 - 硬边界:15 步 + 强制 submit,避免 runaway tool loop。
- 与 Outer Loop 协议化对接 :
subtask_submit是明确的 Inner/Outer 边界 API。 - ToolNode 树:轨迹结构化,便于 UI、recorder、posterior reflect。
- 每轮 workspace 快照:文件结构实时注入,减轻「忘了环境状态」。
11.2 偏旧或易混淆的地方
- 嵌套 tool_call:与 modern flat tools 不一致,维护成本高。
- Observation 非 tool role:多轮理解可能弱于标准 chat。
- 连续 user messages:system 后多条 user,非 canonical format。
- 名不副实:ChainSearch 无搜索。
- 根节点空跑:depth=0 的 root 不执行,第一步 depth=1 才真正调 LLM。
- summary 依赖额外 LLM 调用:Observation 压缩本身耗 token/成本。
12. 一步 ReACT 的完整生命周期(示例)
假设当前 subtask 为 1.2,已执行 2 步,第 3 步开始:
text
1. make_message 生成:
user: "Now you will perform subtask 1.2: ..."
user: "The following steps have been performed: [0] ShellEnv(...); [1] FileSystemEnv(...); ..."
2. placeholders 填充 USER_PROMPT:
subtask_id=1.2, step_num=3, max_length=15, workspace_files=...
3. ToolAgent.parse → LLM 返回 subtask_handle:
{
"plan": ["Read config and patch port"],
"thought": "Previous shell output shows service on 8080, need to change config",
"reasoning": "...",
"criticism": "...",
"tool_call": {"tool_name": "FileSystemEnv_read_file", "tool_input": {"filepath": "..."}}
}
4. message_to_tool_node → 新 ToolNode
5. FunctionHandler → ToolServer 读文件 → tool_output 写入节点
6. interaction.insert_data → Web UI 展示 THOUGHTS / COMMAND / RESULT
7. now_node 指向新节点;若未 submit,回到 while 顶部
13. 若现代化 XAgent ReACT,建议方向
- 扁平 tools :外部工具顶层注册;reasoning 用 Structured Output 或单独字段,不再嵌套
subtask_handle.tool_call。 - 标准 Observation :用
toolrole message 或 assistant tool_calls + tool results 真多轮,替代make_message伪 user 历史。 - 保留 submit 协议 :
subtask_submit作为 structured terminal action 仍然有价值,是 Plan 层接口。 - 可选分离 Reason:高能力模型可用两次调用(cheap reason + action),低能力模型保持合并 schema。
- rename :
ReACTChainSearch→ReACTChainExecutor,避免 Search 误导。
14. 关键代码索引
| 主题 | 路径 |
|---|---|
| ReACT 主循环 | XAgent/inner_loop_search_algorithms/ReACT.py |
| Inner Loop 入口 | XAgent/workflow/task_handler.py → inner_loop |
| ToolAgent 提示词 | XAgent/agent/tool_agent/prompt.py |
| ToolAgent 解析 / OpenAI hack | XAgent/agent/tool_agent/agent.py |
| Function schema | XAgent/ai_functions/pure_functions/task_handle_functions.yml |
| 工具执行 / Observation 写回 | XAgent/function_handler.py |
| ToolNode / process | XAgent/data_structure/node.py |
| 历史摘要 | XAgent/agent/summarize.py → summarize_action |
| 配置上限 | assets/gpt-3.5-turbo_config.yml |
| 思考日志 | XAgent/core.py → print_assistant_thoughts |
15. 结论
XAgent 的 ReACT 不是论文里文本交替的 ReACT,而是:
在 Plan 节点约束下,用
subtask_handle把 Reason 与 Act 压进一次 structured function call,用 ToolNode 链保存 Observation,用make_message+summarize_action把 Observation 注入下一轮 prompt,用subtask_submit关闭 Inner Loop 并 handoff 给 Outer Loop 的 Plan refine。
理解这套框架,需要同时看:提示词(workflow + 步数预算)、schema(四段推理 + tool_call)、generate_chain 循环、FunctionHandler 中介、Observation 摘要管道------缺一不可。
与通用方案比,XAgent 走的是 「重协议、重结构、重 Plan 上下文」 路线,适合长任务、可审计、需人机协作的场景;若只需短链路 tool agent,现代 flat tool use + 标准 message history 往往更简单。两种路线没有绝对优劣,取决于你要的是 Runtime 完整性 还是 集成简洁性。