工具运行流程(Tool Loop)
适用版本:
v4.0.8.2
Tool.async_plan_and_execute() 在 v4.0.8.2 中不是一个简单 while 循环,而是一个由 TriggerFlow 驱动的标准化回路。
1. 总体流程
如何阅读这张图
PLAN与EXECUTE不是文档概念,而是 runtime 内部的显式阶段。- 这让 Tool Loop 和普通 TriggerFlow 一样可以维护状态、做超时控制,也能被更稳定地调试。
2. 回合状态长什么样
text
round_state = {
"done_plans": [...], # 累积到当前轮为止的全部执行记录
"last_round_records": [...], # 仅上一轮的记录
"round_index": 0, # 当前轮数
}架构思路
done_plans负责提供全局上下文,避免模型忘记已经做过什么。last_round_records负责给规划器提供最近一轮的直接反馈,尤其适合失败重试和 follow-up。round_index是硬边界,防止回路无限转。
3. 规划阶段:plan_step
默认规划器会创建一个独立 ModelRequest,并读取这些上下文:
input.user_inputinput.user_extra_requirementinput.available_toolsinfo.done_plansinfo.last_round_resultinfo.round_indexinfo.max_rounds
输出结构被约束为:
python
{
"next_action": "execute" | "response",
"execution_commands": [
{
"purpose": str,
"tool_name": str,
"tool_kwargs": dict,
"todo_suggestion": str,
}
],
}兼容归一化规则:
- 传回
tool_commands也会被收敛成execution_commands - 传回单个
tool_command也会被提升为列表 - 缺失
next_action时,框架会根据是否存在命令自动推断
4. instant 短路
默认规划器会监听流式结构化输出里的 next_action。
若在 instant 流里尽早确认:
next_action=response
则会直接关闭规划流并返回,不再等待完整结果体。这一点对“无需调用工具的请求”很重要。
5. 执行阶段:execute_step
执行器收到的是一组归一化后的 ToolCommand:
python
{
"purpose": str,
"tool_name": str,
"tool_kwargs": dict,
"todo_suggestion": str,
"next": str, # 与 todo_suggestion 对齐后的兼容字段
}默认执行器会:
- 读取
tool.loop.concurrency - 并发调用
async_call_tool(tool_name, tool_kwargs) - 把结果规范化成
ToolExecutionRecord
规范化后的执行记录:
python
{
"purpose": str,
"tool_name": str,
"kwargs": dict,
"todo_suggestion": str,
"next": str,
"success": bool,
"result": Any,
"error": str,
}6. 何时停止
以下任一条件满足时,Tool Loop 会结束:
next_action != "execute"use_tool被归一化为False- 没有可执行命令
- 达到
max_rounds
7. 收敛与注入
循环结束后,如果 done_plans 非空,框架会:
to_action_results(done_plans)->prompt.action_results- 注入
extra_instruction - 把原始记录附加到
extra.tool_logs
如果没有任何执行记录,则不注入工具结果。