跳转至

Code Mode 工具面

模型可见工具

当代码模式激活时,模型可以看到 exec、wait 以及任何必需的仅限直接调用的工具。其他所有已启用的工具都会从模型可见的工具列表中隐藏,并注册到代码模式目录中。

使用 exec 进行工具编排、数据联接、循环、并行嵌套调用和结构化转换。仅在 exec 返回可恢复的 waiting 结果时使用 wait。

exec

exec 启动一个代码模式单元并返回一个结果。输入代码由模型生成,必须视为不可信输入。

面向模型的输入:

type CodeModeExecInput = {
  title: string;
  code: string;
  restartSafe?: boolean;
  required?: boolean;
};

规则:

  • 每个新单元都需要一个不超过 120 个字符的非空 title。使用简短的目的描述,通常为 3–7 个单词,例如 "Inspect the dependency graph"(检查依赖关系图)。描述预期工作,不要声称成功或包含机密信息。Control UI 会在执行行上显示此标题。嵌套工具保留各自的摘要;wait 不需要标题,并在原始单元下恢复活动。
  • code 是必需的面向模型的 JavaScript 字段,且必须为非空。
  • command 被接受为 exec 兼容的别名,用于钩子策略和可信重写(普通 OpenClaw shell exec 工具也使用 command 字段)。空白的调用方别名视为不存在;若钩子或可信策略使某个已填充的别名失效(将其置为空白或非字符串),则两个别名都会失效,执行将以失败关闭(fail closed)方式结束。当两个别名均为非空时,它们的值必须匹配。
  • 编写纯 JavaScript。TypeScript 注解、接口以及其他仅限 TypeScript 的语法均不被接受。工具签名和 API.read 声明仍可作为编写调用时的文档参考。
  • 已退役的 language 和 typecheck 字段会因 invalid_input 错误而被拒绝。工具参数会在每次调用到达其正常执行所有者时进行验证;代码模式不会在执行前对整个程序进行类型检查。
  • 不要在新的 exec 上设置 restartSafe。仅当 OpenClaw 在网关重启后明确请求重放时才将其设置为 true,并且绝不要为 write、edit、exec 或任何变更操作设置该字段。每个目录调用都必须明确具备重放安全性。OpenClaw 会拒绝未标记的目录工具以及未经证明具备重放安全性的命名空间表面。某个通用 exec 表面不会仅仅因为某条命令看起来是只读的就具备重放安全性;请使用经审计的 read、grep 或 find 工具。挂起的结果会标记为具备重放安全性,以便重启恢复能够从转录文本重建被中断的轮次,而不是恢复进程本地的延续。恢复仍仅限于经审计的只读核心工具以及明确具备重放安全性的插件工具。对于普通调用,请省略该字段。
  • exec 拒绝 import、require、动态导入和模块加载器模式。
  • exec 永远不会递归地暴露普通 shell exec 实现。
  • 外部代码模式 exec 钩子事件携带 toolKind: "code_mode_exec" 和 toolInputKind: "javascript",因此策略可以区分代码模式单元与共享相同工具名称的 shell 风格 exec 调用。

结果:

type CodeModeResult = CodeModeCompletedResult | CodeModeWaitingResult | CodeModeFailedResult;

type CodeModeCompletedResult = {
  status: "completed";
  value: unknown;
  output?: CodeModeOutput[];
  telemetry: CodeModeTelemetry;
};

type CodeModeWaitingResult = {
  status: "waiting";
  runId: string;
  reason: "pending_tools" | "yield";
  pendingToolCalls?: CodeModePendingToolCall[];
  output?: CodeModeOutput[];
  telemetry: CodeModeTelemetry;
};

type CodeModeFailedResult = {
  status: "failed";
  error: string;
  code?: CodeModeErrorCode;
  output?: CodeModeOutput[];
  telemetry: CodeModeTelemetry;
};

当访客以可恢复状态挂起、且该状态仍需要模型可见的延续时——即显式的 yield_control(...),或在 exec 期限内尚未解析的桥接工具调用——exec 会返回 waiting。结果中包含供 wait 使用的 runId。原生通道的 exec 审批有所不同:在等待操作者决策期间,OpenClaw 会同时挂起代码模式执行预算和所属代理运行预算。原始 exec 保持进行中,并在审批解析后以其未使用的预算精确恢复;它不会返回 pending_tools,也不需要模型通过 wait 轮询。如果访客在兄弟调用等待审批期间显式让出,该单元在停驻期间会继续观察该审批。其下一次 wait 也会等待该待定决策。每次调用仅获得其自身未使用的执行预算;停驻时间以及先前调用的审批暂停不会增加执行额度。取消、所有者检查和延续过期机制保持不变。桥接请求——catalog.search、句柄 describe()、可调用的工具句柄以及包括 MCP 在内的命名空间调用——会在同一 exec/wait 调用内部自动排空,只要它们在期限内解析。这样,一个等待多个工具的紧凑代码块可以在一个模型轮次内运行完成,而不必强制每个 await 都对应一次模型工具调用。没有 yieldMs 或 background: true 的桥接 shell exec 会在转入后台前等待剩余调用预算(tools.codeMode.timeoutMs,默认 10 秒)减去恢复余量;因此在该时间窗口内完成的命令会在同一轮次内以内联方式返回。延迟的顺序调用会更早转入后台,但仍会返回其进程句柄,以便访客可以内联恢复。

仅当访客虚拟机没有待处理工作,并且最终值在 OpenClaw 的输出适配器运行后能够与 JSON 兼容时,exec 才会返回 completed。

新的 exec 和 wait 结果文本使用紧凑 JSON,以便为工具数据留出更多上下文预算。状态、延续、重放安全性、遥测以及结构化的 details 字段都会保留。JSON 字符串内部的文本保持其原始空白。TUI 将这些结果显示为字面文本,因此 Markdown 语法和长 Token 格式无法改变其值。URL 仍以文本形式可见,而不会变成 Markdown 链接。

必需结果

当完成当前任务需要该程序的结果时,使用 required: true。现有单元格所有者会在 VM 暂停期间保持工具调用打开,然后在待处理工具结果落定时恢复该确切延续。它不会返回 waiting 句柄,也不会发起模型轮询调用。已完成的操作不会被重放。失败、Stop、所有者替换以及现有运行和工具截止时间仍会结束该操作。

required 仅暂停 VM 外工具等待。准备、来宾执行、检查点和恢复共享原始执行额度;每次落定都不授予新的额度。输出、内存、待处理调用和活跃单元格限制保持不变。yield_control 不能放弃未完成的必需程序;请完成该程序或取消所属运行。普通单元格保留其现有的显式让出行为。

必需单元格会收集普通 shell 命令直至完成。显式 background: true 仍然是有意分离的服务的退出选项。在普通单元格内的 shell exec({required: true, ...}) 或 agents_wait({required: true, ...}) 也会使该单元格变为必需。这些声明不会启用 tools.exec.notifyOnExit。

对于必需收集器结果,请在必需单元格中等待 agents.run(...),或调用 agents_wait({ids, required: true})。普通通告子项仍使用其现有的 sessions_yield 交接。已接受的后台句柄不是终端结果:此功能不会从计划文本推断义务,也不会静默地将每个异步服务变为必需工作。

会话历史中的来源

在内置 OpenClaw 运行时中,JSON Code Mode 工具执行原始输入。会话历史会保留外层调用 JavaScript code 和 command 字段中的计算,例如 const API_TOKEN = computeToken();,以及布尔或 null 初始化器,同时掩蔽凭据字面量、可识别 Token、已注册机密和已配置脱敏模式。凭据赋值使用完整掩码,以便重复存储脱敏保持稳定。

此处理方式不适用于 shell 命令、嵌套工具调用、无关参数字符串或助手文本。大型或无法识别的源语法仍受诊断掩蔽约束。存储的源是脱敏记录,不是用于恢复凭据的地方;无需额外设置。这适用于新调用;已脱敏的源无法重建。Copilot 运行时的独立转录日志尚未保留此源结构。原生 Codex 使用独立的自由格式源路径;此行为不描述其存储。

wait

wait 继续一个已挂起的代码模式 VM。

输入:

type CodeModeWaitInput = {
  runId: string;
};

输出是与 exec 返回的相同 CodeModeResult 联合类型。

wait 的存在是因为嵌套 OpenClaw 工具可能缓慢、交互式或流式传输部分更新;模型不应需要在主机等待普通外部工作时保持一个长时间 exec 调用打开。原生通道 exec 审批是例外:它们保留在原始 exec 内,以便审批权限仍绑定到已准入的运行。

快速内联主机交换保留相同的执行上下文。显式让出或耗尽的调用预算可以挂起它,而无需重放工具。Node 保留实时工作上下文;QuickJS 对其 VM 进行快照,并可以释放工作进程。QuickJS 工作池压力也可能在同一调用内部暂停单元格。实际 QuickJS 检查点会强制 maxSnapshotBytes,因此大型实时堆可能内联完成,但在必须真正暂停时失败。

两个执行器使用相同的 wait 约定:

  1. exec 评估代码,直到完成、失败或挂起。
  2. 挂起时,所选执行器保留其延续,OpenClaw 记录待处理主机工作。
  3. 当待处理工作落定时,wait 恢复同一执行器。Node 继续其实时上下文;QuickJS 恢复其快照并重新注册回调。
  4. OpenClaw 传递嵌套工具结果,并让 JavaScript 延续运行。
  5. wait 返回 completed、failed 或另一个 waiting 结果。

延续是运行时状态,不是用户工件:其所有权仅存在于进程内映射中(无数据库或磁盘写入),它们会过期,并且范围限定于创建它们的运行和会话。QuickJS 快照有大小限制;Node 则保留实时工作内存。参见 Code Mode 执行器。一个单元格所有者跨越初始执行、挂起和每次恢复。取消所属运行或当前工具调用,或在尝试拆除时关闭其工具目录,会取消活跃工作进程和待处理主机工作,并释放已暂停的延续,即使随后没有 wait 调用。目录描述刷新和客户端工具添加不会关闭所有者。忽略取消的外部操作可能仍会完成,但无法恢复已关闭的来宾、发出后续来宾输出或启动另一个来宾工具调用。

进程范围的 64 个槽位限制适用于已挂起单元格及其预留恢复槽位。恢复会保留其槽位,直到完成或再次暂停;初始执行在分发主机工作前预留槽位,并在实时执行和内部暂停期间保留它。没有主机工作的单元格不消耗槽位。

快照 TTL 测量单元格暂停期间的空闲时间。已准入的 wait 会在待处理工具落定期间,在其调用截止时间下保持单元格存活。如果该调用再次返回 waiting,暂停会启动一个新的快照 TTL。

wait 在以下情况下失败(作为 failed 结果):

  • runId 未知或其延续已过期。
  • 调用者不在与已挂起运行相同的运行/会话范围内。
  • 该 runId 已有一个 wait 正在进行。
  • 所选执行器无法恢复(例如,其工作进程已退出或 QuickJS 恢复失败)。
  • QuickJS 检查点将超过 maxSnapshotBytes。普通超大的成功输出会被截断,并仍保持成功。

工具目录

隐藏目录包含经过有效策略过滤后的工具,顺序如下:OpenClaw 核心工具、捆绑插件工具、外部插件工具、MCP 工具,然后是当前运行中客户端提供的工具。

目录 ID 保持为不透明的、仅限主机使用的路由标识。它们在单次运行内保持稳定,并在可能的情况下在等效工具集之间保持确定性,但绝不会包含在 prompt、来宾元数据、句柄描述或错误中。策略、审批、遥测、重放安全性和命名空间调度继续在内部使用它们。

在 worker 启动之前,OpenClaw 会为每个精确工具名称投影出一个有效胜出者,并计算其最终的来宾可调用名称。这与直接模式优先级一致:较晚的客户端工具赢得精确名称遮蔽,而插件冲突强制执行保持不变。最终确定的投影会随桥接调用和继续恢复传递;消费者不会从目录中重建它。

目录会省略代码模式控制工具(exec、wait、tool_search、tool_describe、tool_call)和仅限直接调用的工具。控制工具不得通过目录递归;仅限直接调用的工具保持模型可见,因为其结构化结果无法跨越 JSON 来宾桥。

MCP 条目保留在运行作用域目录中,以便策略、审批、钩子、遥测、转录投影和精确工具 ID 与正常工具执行保持共享。catalog.search(...) 会同时搜索原生和 MCP 能力,并返回可调用句柄。MCP 匹配项会标识其最终的 MCP.<server>.<tool> 路径和声明文件;调用句柄会使用同一个命名空间调度器。catalog.all() 仅列出原生和客户端句柄。远程描述和模式不会进入受信任的快速索引。

工具搜索交互

对于代码模式处于活动状态的运行,代码模式会取代 OpenClaw 工具搜索模型表面。

当代码模式通过强制 true 或 "auto" 激活时:

  • OpenClaw 不会将 tool_search、tool_describe 或 tool_call 暴露为模型可见工具。
  • 相同的目录化思路移入来宾运行时内部。
  • 来宾运行时会接收裸异步全局变量,以及用于原生工具的可调用搜索/描述句柄,外加按需的 MCP 搜索句柄。
  • MCP 调用使用生成的 MCP 命名空间,可直接使用或通过搜索句柄使用;句柄的 describe() 会请求精确的 $api() 头部和模式。
  • 嵌套调用通过工具搜索所使用的同一 OpenClaw 执行器路径进行调度。

有关代码模式在活动运行中取代的 OpenClaw 结构化目录表面,请参阅工具搜索。

工具名称与冲突

对模型可见的 exec 工具是代码模式工具。如果启用了普通 OpenClaw shell exec 工具,它将对模型隐藏,并像其他任何工具一样编入目录。

在来宾运行时内部:

  • 精确的 JavaScript 安全工具名称保持精确:web_search(...) 和 sessions_spawn(...)。
  • 无效标识符字符会变成 _;仍然无效的首字符会获得 tool_ 前缀。例如,当该名称可用时,llm-task 会变成 llm_task。
  • JavaScript 保留字、专用全局变量和规范化冲突会获得一个从仅限主机的标识派生的确定性短后缀。
  • 精确的安全名称会优先采用无后缀拼写。原始工具绝不会覆盖 catalog、MCP、API、nodes、skills、namespaces、输出/计时器辅助函数或可选的 Swarm 全局变量。
  • 当策略允许时,普通 shell exec 工具可作为 exec(...) 来宾全局变量调用。代码模式控制 exec 在来宾内部不可递归使用。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw