当前位置: 首页 > news >正文

一次消息如何变成多步行动:拆开 OpenClaw 的 Agent Loop

本篇把这些静态概念串成一台运行中的状态机,回答问题:

一次用户消息,为什么可能产生多次模型调用、多个 Tool Call,最后才形成一个回答?

答案是:因为 OpenClaw 在外层提供了一个固定的程序循环,而“这一步是调工具还是收尾”由模型在每一轮里临时决定。

本文用一个“两跳读取”任务把这条循环逼出来,再用一个分支实验证明:真正决定循环长短的,是 Tool Result 的内容。


1. 先把词分清:Turn / Run / Model Call / Tool Call

概念含义
Session可持续多轮的逻辑会话
Turn用户发一条消息、拿到一个最终回答的交互单元
RunOpenClaw 对一次输入执行的完整 Agent 运行(一个runId
Model CallAgent 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. 实验设计:两跳读取,逼出真实的多步

关键是让第二步“无法被提前预判”,这样模型就不得不真的循环两圈:

  1. 先读manifest.txt
  2. 第二个文件的路径写在 Manifest 里,只有读完第一步才知道;
  3. 再读target.txt
  4. 根据目标文件返回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关键内容
1Model Call 1toolUseread(manifest.txt)
2Tool Result 1Manifest 暴露TARGET_FILE=…/target.txt
3Model Call 2toolUseread(target.txt)
4Tool Result 2VALUE_A=17VALUE_B=25
5Model Call 3stop最终回答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)↔TR1read(target)↔TR2。这是从证据(而非模型自述)判断“谁对应谁”的唯一可靠依据。

其三,Tool Result 会重新进入下一次 Context。模型是从第一条 Tool Result 里读到TARGET_FILE的值,才发出了第二个read。也就是说,工具结果被回填进历史、参与了下一轮 Context 组装——这正是 Mission012 里“Transcript 增长 → Context 重组”在循环中的体现。

顺带一个缓存现象(Mission012 已详述,这里只作印证):三次调用的模型input依次是5832 → 72 → 43,而cacheRead8192 → 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=5947cacheRead=36480total=14275
  • lastCallUsage(仅最后一次):input=43cacheRead=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.startedtrace.metadatacontext.compiledprompt.submittedmodel.completedtrace.artifactssession.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. 结论:一条固定循环,套着一个会决策的模型

  1. 一个用户 Turn ≠ 一次模型调用。本次一个 Turn = 1 Run / 3 Model Call / 2 Tool Call / 2 Tool Result / 1 最终回答。
  2. stopReason是循环红绿灯toolUse继续、stop退出;Tool Result 不带stopReason
  3. toolCallId是配对锚点:Tool Call 的id= Tool Result 的toolCallId,靠它从证据判断因果,而非听模型自述。
  4. Tool Result 会回填进下一次 Context:第二个read的路径,来自第一条 Tool Result。
  5. Runtime 执行、模型决策:Runtime 只判断“技术上成没成功”,模型判断“语义上够不够、下一步做什么”。
  6. 模型是循环里的 if/else:同规则、不同 Tool Result → 不同循环长度;但它是概率式判断,不是确定性分支。
  7. 聚合 usage 会重复计缓存:聚合cacheRead是逐次相加,不能当单次上下文大小。
  8. 观测用 Transcript:本构建的 Trajectory 只是收尾总结快照,逐圈细节在 Transcript 里。

一句话:OpenClaw 提供的是一条写死的程序循环,循环里的每一步动作则交给模型概率式地决定。理解 Agent,就是理解这条“程序 + 模型”的分工——以及用toolCallIdstopReason、Transcript 这些证据,而不是模型的自我描述,去还原它真正做了什么。

学习资源推荐

如果你想更深入地学习大模型,以下是一些非常有价值的学习资源,这些资源将帮助你从不同角度学习大模型,提升你的实践能力。

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!​

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示

​因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取

四、AI大模型商业化落地方案

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

http://www.jsqmd.com/news/1304736/

相关文章:

  • JasperReports报表引擎实战:从模板设计到Spring Boot集成与性能优化
  • OMG数据集:多模态基因组语言模型的数据基石与实战指南
  • Qt QSS样式表开发实战与性能优化指南
  • 从模拟到数字:乘法器核心原理、实现与应用全解析
  • 电容式触摸屏原理与架构解析:从自互电容到In-Cell技术
  • Anthropic百亿融资揭示AI行业估值逻辑与技术趋势
  • 硕士论文答辩:从心态转变到逻辑构建的7个核心原则
  • LAMP栈集成Lua脚本实现工业节流阀自动控制方案
  • .NET 8 Web开发入门(三):解构引擎——依赖注入(DI)与中间件管道
  • Python信号处理:STFT时频分析与scipy.signal.stft实战指南
  • 关键拍卖反转(KAR)策略:基于订单流分析的市场转折点捕捉技术
  • 4K60P横屏直拍:技术视角下的偶像表演艺术深度解析
  • PrimeTime静态时序分析:get_cells命令的精准定位与高效应用
  • 单片机RS485通信实战:从差分信号原理到多机组网应用
  • 多模型协作编程:Grok、DeepSeek、GLM在AI开发中的集成实践
  • 深度智能体多模型适配:架构设计与调优实战指南
  • Python中使用Vosk实现离线语音识别实践
  • 语音转文本程序,带有GUI
  • MATLAB视频处理全流程:从帧提取到重构输出的核心技巧
  • 读懂 B200:巨头全收,一卡难求
  • RISC-V RoCC协处理器接口实战:从架构解析到Sobel加速器设计
  • 《吞食天地2:蜀汉英雄传》1.5版深度攻略:系统解析与全流程图文指南
  • C++自定义类型哈希实现:从原理到实战避坑指南
  • 腾讯云COS前端直传图片实践:从本地存储到云原生架构优化
  • OpenClaw高危漏洞CVE-2026-25253剖析与AI应用安全加固实战
  • 零基础修改《仙剑奇侠传》:可视化工具实现游戏个性化定制
  • FPGA高速接口时序校准:IDELAYCTRL原理、配置与调试实战
  • 光的物理特性与隐喻意义探析
  • I2C通信协议深度解析:从原理到实战调试全指南
  • 数字电路通信——时序与I2C,I2S,SPI,UART协议