本篇把这些静态概念串成一台运行中的状态机,回答问题:
一次用户消息,为什么可能产生多次模型调用、多个 Tool Call,最后才形成一个回答?
答案是:因为 OpenClaw 在外层提供了一个固定的程序循环,而“这一步是调工具还是收尾”由模型在每一轮里临时决定。
本文用一个“两跳读取”任务把这条循环逼出来,再用一个分支实验证明:真正决定循环长短的,是 Tool Result 的内容。
1. 先把词分清:Turn / Run / Model Call / Tool Call
| 概念 | 含义 |
|---|---|
| Session | 可持续多轮的逻辑会话 |
| Turn | 用户发一条消息、拿到一个最终回答的交互单元 |
| Run | OpenClaw 对一次输入执行的完整 Agent 运行(一个runId) |
| Model Call | Agent Loop 中一次 Provider 推理请求 |
| Tool Call | 模型请求 OpenClaw 执行某个工具(带toolCallId、工具名、参数) |
| Tool Result | 工具执行结果(靠toolCallId与 Tool Call 配对) |
| Final Answer | 循环退出前的最终文本(通常stopReason=stop) |
| Transcript | 持久化的会话事件(JSONL) |
| Trajectory | 运行时观测轨迹(Context / Prompt / 模型事件) |
一句话记牢:一个用户 Turn ≠ 一次模型调用;一个 Run 可以包含多个 Model Call 和多个 Tool Call。
官方把这条循环定义为一次按会话串行的“真实运行”:接收 → 上下文组装 → 模型推理 → 工具执行 → 流式回复 → 持久化(来源:Agent loop)。本文要观察的,就是这条链路在一次任务里到底转了几圈。
2. 理论:Agent Loop 是“程序循环 + 模型决策”
把它写成伪代码,结构会更直白:
while True: context = assemble_context(system_prompt, user_prompt, past_tool_calls, past_tool_results, past_assistant_messages) response = model(context, available_tools) if response.has_tool_call: # 模型选择:继续 result = runtime.execute(response.tool_call) transcript.append(response.tool_call) transcript.append(result) continue return response.text # 模型选择:收尾while循环、执行工具、回填结果、再次调用模型——这一层是代码写死的;而每一圈“要不要调工具、调哪个”——这一层由模型决定。职责划分是:
- Prompt:定义任务目标、约束与分支规则;
- Model:做语义判断、选择下一步动作;
- Runtime:执行工具、回填结果、驱动循环与 Run 生命周期;
- Tool:完成外部操作(读文件、执行命令等);
- Provider:返回模型输出,并标记结束原因(
toolUse/stop)。
说明:
stopReason=toolUse/stop是 Provider(本例是 openai-completions 风格)层面的字段,官方 Agent Loop 文档并未定义它;不同 Provider 或定制构建的具体字符串可能不同,应以 Transcript 实际输出为准。本文所有stopReason都来自实测。
3. 实验设计:两跳读取,逼出真实的多步
关键是让第二步“无法被提前预判”,这样模型就不得不真的循环两圈:
- 先读
manifest.txt; - 第二个文件的路径写在 Manifest 里,只有读完第一步才知道;
- 再读
target.txt; - 根据目标文件返回
MARKER / VALUE_A / VALUE_B / SUM。
因为第二个路径在第一次 Tool Result 返回后才出现,模型不可能在第一次调用里就发出有效的第二个 Tool Call。预期循环是:read(manifest) → read(target) → 最终回答。
运行环境:Provider/Model 为deepseek-official/deepseek-v4-flash,内嵌运行时,单会话,Context 窗口 64,000,不改任何全局配置(避免再引入 Compaction/Pruning 变量)。
4. 主实验:1 个 Turn → 3 次模型调用 / 2 次工具调用
Transcript 完整记录了这条循环:
| # | 事件 | stopReason | 关键内容 |
|---|---|---|---|
| 1 | Model Call 1 | toolUse | read(manifest.txt) |
| 2 | Tool Result 1 | — | Manifest 暴露TARGET_FILE=…/target.txt |
| 3 | Model Call 2 | toolUse | read(target.txt) |
| 4 | Tool Result 2 | — | VALUE_A=17、VALUE_B=25 |
| 5 | Model Call 3 | stop | 最终回答SUM=42 |
于是一个用户 Turn 实际产生了:1 个 Run、3 次 Model Call、2 次 Tool Call、2 条 Tool Result、1 条最终回答。这里有三个可直接读出的机制。
其一,stopReason是循环的红绿灯。toolUse表示“模型还要调工具,循环继续”;stop表示“模型收尾,循环退出”。注意 Tool Result 本身没有stopReason——它是工具执行结果,不是模型响应;stopReason只属于 Assistant 消息。
其二,Tool Call 与 Tool Result 靠toolCallId配对。Assistant 消息里 Tool Call 的id,等于对应 Tool Result 的toolCallId。本次两对都严格匹配:read(manifest)↔TR1、read(target)↔TR2。这是从证据(而非模型自述)判断“谁对应谁”的唯一可靠依据。
其三,Tool Result 会重新进入下一次 Context。模型是从第一条 Tool Result 里读到TARGET_FILE的值,才发出了第二个read。也就是说,工具结果被回填进历史、参与了下一轮 Context 组装——这正是 Mission012 里“Transcript 增长 → Context 重组”在循环中的体现。
顺带一个缓存现象(Mission012 已详述,这里只作印证):三次调用的模型input依次是5832 → 72 → 43,而cacheRead是8192 → 14080 → 14208——历史在涨,但重复前缀命中了 Provider 缓存,单次计费 input 很小。
5. 谁在做决定:Runtime 执行,模型选择
Runtime 不理解业务语义。它只知道“工具在技术上是否执行成功”(比如isError=false),不会主动判断“这段结果里有目标路径,所以下一步该读它”。真正读懂TARGET_FILE、决定再发一个read的,是第二次模型调用。
为了坐实“模型才是分支决策者”,再做一个对照实验:规则完全相同,只改 Manifest 的内容。
Manifest 里写一条决策规则:ACTION=READ_TARGET就继续读目标文件,ACTION=ANSWER_DIRECTLY就直接收尾。结果:
- Continue 分支(Manifest 写
READ_TARGET):read(manifest) → read(target) → 最终回答,共3 次模型调用 / 2 次工具; - Stop 分支(Manifest 写
ANSWER_DIRECTLY):read(manifest) → 最终回答,共2 次模型调用 / 1 次工具。
规则一字未改,只有第一条 Tool Result 的内容不同,模型就走了不同的循环长度。结论很清楚:
模型在循环里扮演的是
if/else,但它是概率式的自然语言判断,不是确定性的程序分支;Runtime 只负责那个固定的while循环。整个系统 =「程序式的 Agent Loop 框架」+「模型驱动的具体行动选择」。
6. 一次 Run 的账本:usage 聚合 vs 单次;Transcript vs Trajectory
6.1 别把聚合 usage 当成单次上下文大小
运行报告里有两个 usage,含义完全不同:
agentMeta.usage(整个 Run 聚合):input=5947、cacheRead=36480、total=14275;lastCallUsage(仅最后一次):input=43、cacheRead=14208。
注意聚合值是逐次相加的:input5947 = 5832+72+43,cacheRead36480 = 8192+14080+14208。也就是说,同一段被缓存的前缀,在三次调用里被重复计入了聚合cacheRead。所以不要用聚合cacheRead去估单次 Prompt 大小——单次规模要看那一次的input + cacheRead (+ cacheWrite)。
6.2 观察 Agent Loop 要用 Transcript,而不是 Trajectory
同一次 Run,两份记录粒度不同:
- Transcript:完整事件序列(3 条 assistant + 2 条 toolResult),能干净还原整条循环;
- Trajectory(本构建的 sidecar):只有7 行——
session.started、trace.metadata、context.compiled、prompt.submitted、model.completed、trace.artifacts、session.ended。
耐人寻味的是:context.compiled/prompt.submitted/model.completed各只出现一次,尽管 Run 内实际发生了 3 次模型调用。那唯一的一次model.completed里,messagesSnapshot一次性打包了全部6 条消息(user → toolCall → toolResult → toolCall → toolResult → final)。
也就是说,本构建的 Trajectory 是一份“收尾时的总结快照”,不是逐轮流水。要逐圈观察 Agent Loop,得靠 Transcript。(官方 Agent Loop 文档描述的实时事件流是lifecycle / assistant / tool;Trajectory sidecar 的具体形态属于构建实现,应以本机实际输出为准。)
7. Context 的机制,落在循环的哪一步
把这条循环和上一篇接起来,就能定位每个机制的位置:
- 每次 Model Call 之前,Context 都要重新组装一遍;
- 每条 Tool Result 之后,Transcript 增长 → Context Engine 重组 →(视配置)Pruning / 预算检查 → 提交下一次 Prompt;
- 压力过大时,才进入 Compaction 或 Context Overflow Recovery。官方也说明:自动压缩会发出
compaction事件并可能触发重试,重试时会重置内存缓冲与工具摘要以避免重复输出(来源:Agent loop · 压缩+重试)。
换句话说,Mission012 讲的“组装、缓存、裁剪、摘要”,都是发生在这条循环里每一圈的 Context 组装阶段。
8. 结论:一条固定循环,套着一个会决策的模型
- 一个用户 Turn ≠ 一次模型调用。本次一个 Turn = 1 Run / 3 Model Call / 2 Tool Call / 2 Tool Result / 1 最终回答。
stopReason是循环红绿灯:toolUse继续、stop退出;Tool Result 不带stopReason。toolCallId是配对锚点:Tool Call 的id= Tool Result 的toolCallId,靠它从证据判断因果,而非听模型自述。- Tool Result 会回填进下一次 Context:第二个
read的路径,来自第一条 Tool Result。 - Runtime 执行、模型决策:Runtime 只判断“技术上成没成功”,模型判断“语义上够不够、下一步做什么”。
- 模型是循环里的 if/else:同规则、不同 Tool Result → 不同循环长度;但它是概率式判断,不是确定性分支。
- 聚合 usage 会重复计缓存:聚合
cacheRead是逐次相加,不能当单次上下文大小。 - 观测用 Transcript:本构建的 Trajectory 只是收尾总结快照,逐圈细节在 Transcript 里。
一句话:OpenClaw 提供的是一条写死的程序循环,循环里的每一步动作则交给模型概率式地决定。理解 Agent,就是理解这条“程序 + 模型”的分工——以及用toolCallId、stopReason、Transcript 这些证据,而不是模型的自我描述,去还原它真正做了什么。
学习资源推荐
如果你想更深入地学习大模型,以下是一些非常有价值的学习资源,这些资源将帮助你从不同角度学习大模型,提升你的实践能力。
一、全套AGI大模型学习路线
AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!
因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取
二、640套AI大模型报告合集
这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示
因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取
三、AI大模型经典PDF籍
随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。
因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取
四、AI大模型商业化落地方案
作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。