跳转至

尝试运行时

选定 harness 在尝试运行期间以及最终化时调用的辅助功能:受保护的输入注入、工具结果中间件、终结结果分类、实时 Token 用量以及 Agent 结束时的副作用。属于 Agent harness 插件 参考的一部分。

受保护的活跃运行注入

接受 source-bound 控件的后端会在其活跃运行句柄上声明 messageInjectionV2。该能力由来自 openclaw/plugin-sdk/agent-harness-runtime 的 setActiveEmbeddedRun 进行上下文类型约束;其类型也可以从该函数的 handle 参数推导得出。它要求 version: 2、isAvailable() 以及 queueMessage(text, options, assertCurrent, authorityKind)。必需的第三个参数是针对该次单独注入的宿主拥有的断言,而不是运行 ID、指纹或诊断标识。必需的 authorityKind 对于普通输入为 "run",对于其源生命周期同样约束分派的输入为 "source-bound"。两者都保留 backing-run 检查;source-bound 输入绝不能被重新标记为普通输入。

在等待准备完成后、并在队列变更或 provider 分派之前,与后端自身的 live-run 检查一起调用 assertCurrent()。宿主会将返回 false 或抛出异常的 source authority 规范化为拒绝,并保留该注入的撤销状态,即使源之后再次看起来是当前的。插件调用所提供的断言;它们不会重建其 authority。批处理后端会保留并重新验证每个条目的断言,包括在重试之前;省略已撤销的条目,而不会取消独立接受的工作或污染后续已授权的控件。

当提供时,在该输入提交、取消或最终拒绝后,调用一次 options.onQueueSettled()。onQueueAccepted(true) 仅报告准入。对于 waitForTranscriptCommit: false 提前返回的后端,会保留 settlement 回调,直到其确切输入完成;核心使用它来释放所选发送者保留的 source authority。

可选 V2 claimPendingUserInputAnswer(text, options, assertCurrent, authorityKind) 和 cancelPendingUserInput(resolvedBy, assertCurrent, authorityKind) 方法需要相同的断言和 authority kind。将其贯穿问题注册和持久化,直到最终的 claim 或取消边界。不要仅通过在调用某个 SDK 方法之前进行检查来实现 V2,而该方法本身在分派前会 await。如果 sink 无法强制该断言,则保持 V2 不受支持。

V1 messageInjection、队列选项、queueAgentHarnessMessage 以及 v2026.8.1 中发布的 setActiveEmbeddedRun 签名保持源码兼容。将解析后的 agent ID 作为 setActiveEmbeddedRun 的第五个参数传入,以便原始 global 和 unknown 键保留其所有者。在匹配的 live host binding 内的遗留调用会继承其已验证的 agent;仅 ambient caller 不提供所有权。在该绑定之外,省略的所有权使用限定 session key 或为 session 活动配置的默认 agent。无范围的 V1 注入保留其现有行为。source-bound 控件要求 V2,并且当只有 V1 可用时,会在队列或 I/O 之前显式拒绝;它们绝不会回退到未检查的 V1 回调。现有弃用窗口保持不变。

Copilot 仍仅限 V1:@github/copilot-sdk 1.0.11 在 send 入口后等待 trace-context 和 JSON-RPC writer 准备,而没有最终分派保护。因此,有范围的 steering 会在其队列、问题 claim 或 provider I/O 之前失败;普通无范围注入不变。改为检查状态、取消运行或启动新的显式请求。当受保护注入受支持时更新运行时。一旦上游提供最终分派断言,将 Copilot 迁移到 V2 并移除此内部 V1 依赖;不要添加未检查的回退或缩短已发布 API 的弃用窗口。

工具结果中间件

具有匹配 manifest 契约的捆绑插件和显式启用的已安装插件,可以通过 api.registerAgentToolResultMiddleware(...) 附加运行时中立的工具结果中间件,前提是它们的 manifest 在 contracts.agentToolResultMiddleware 中声明了目标 runtime ids。此受信任接缝用于异步工具结果转换,这些转换必须在选定 harness 将工具输出反馈给模型之前运行。支持的 runtime ids 为 agentsapi、codex 和 openclaw。

中间件选项可以将 runtimes 与 matcher 工具名称列表组合。每次注册都保持该配对完整,因此为不同 runtime 注册同一 handler 不会扩大任一 matcher。Matcher 使用非空 canonical OpenClaw tool ids;省略 matcher 以匹配所有工具。

省略 runtimes 会使用插件 contracts.agentToolResultMiddleware 中声明的所有受支持 runtime,包括声明时的 agentsapi。仅提供 runtimes 以选择该声明的子集。注册会拒绝空的 runtime 列表或 manifest 中缺失的任何目标 runtime。

遗留捆绑插件仍可使用 api.registerCodexAppServerExtensionFactory(...) 用于仅限 Codex app-server 的中间件,但新的结果转换应使用运行时中立 API。仅限 embedded-runner 的 api.registerEmbeddedExtensionFactory(...) 钩子已被移除;嵌入式工具结果转换必须使用运行时中立中间件。

在中间件转换其结果之前,保留来自宿主 message tool 的 details.messageDelivery.sourceReplyDelivered,并将其带入 attempt 结果。这确认最终外部 source reply,且不依赖于 destination 参数或 transcript 镜像。

使用同一 runtime 子路径中的 extractMessagingToolSourceReplyPayload(result) 以在展示变化中保留内部 source-reply payload。对于已确认的 messaging delivery,collectMessagingMediaUrlsFromRecord(args) 收集其附件引用用于 delivery 去重。这两个 helper 都不建立 delivery 或授予 local-file 信任。

远程工作区的回复附件

文件位于远程的测试框架可以在关闭其文件传输之前调用可选的 params.hostCapabilities.prepareReplyMedia。 宿主会应用现有的发送方读取策略和通道/账户字节限制, 然后保存已授权的附件字节以供投递。

请求 结果 测试框架操作
kind: "attempt", attempt preparedMedia 在同一个结果对象上设置 attempt.preparedReplyMedia。核心在最终答案选择后应用它。
kind: "payload", payload 准备好的 payload 通过 onBlockReply 投递此副本;保持持久化消息不变。

两个请求都提供 readWorkspaceFile(relativePath, { maxBytes, signal })。 读取器必须强制实施字节限制和工作区边界,并响应 取消。它只接收在宿主捕获的策略下已授权的路径。当远程工作区具有不同的 绝对路径时,提供 workspaceRoot;宿主在检查策略之前将该别名映射到逻辑工作区。当原生会话或传输所有权可以独立于宿主尝试被撤销时,提供 assertCurrent。宿主会保留此额外检查, 直到最终媒体写入和发布。在准备完成之前保持读取器存活。

对于提供方已接受其字节的工件,使用 kind: "artifact", 并附带 buffer、fileName、assertCurrent 以及可选的 signal。宿主 会在捕获的通道/账户字节限制下暂存这些精确字节,并返回 一个准备好的 payload。此请求不授予文件系统读取权限,也不应用 图像转换或宿主文件 MIME 允许列表。测试框架负责在下载前验证 提供方工件的会话、轮次、环境和路径; 宿主负责出站目标,并在发布前保留实时权限。

缺失、被拒绝和超大的附件会产生常规的投递失败 通知;准备过程不会回退到过期的 Gateway 工作区文件。 准备好的事实包含文件位置和失败信息,绝不含实时读取器。不要 重写助手文本或转录消息以插入 Gateway 文件路径。 当该能力不存在时,此远程附件准备不可用。

共享尝试机制

官方原生测试框架使用私有 openclaw/plugin-sdk/agent-harness-attempt-runtime 中的 buildCurrentInboundPrompt, 使用通道的连接符将准备好的 currentInboundContext 与当前提示组合。 随每条消息提交此上下文,包括恢复的会话。Steering 接收其自己的 options.currentInboundContext;不要重用初始 轮次的上下文。将上下文排除在原始用户转录和待处理 问题答案文本之外。对话字段是模型上下文,而非工具权限。

来自 openclaw/plugin-sdk/agent-harness-runtime 的 resolveAgentHarnessBeforePromptBuildResult 使用准备好的历史和工具权限运行提示钩子。将已接受的消息作为 currentUserMessage 传递;辅助函数 会为其普通和已授权钩子提取文本部分和 idempotencyKey。 字符串输入和单独的 currentUserMessageId 仍受支持。当不存在已接受消息时,测试框架 负责回退。

将 messages 作为数组或异步加载器提供,它仅在 before_prompt_build 钩子需要历史时运行。仅心跳的贡献不会读取对话历史。 生产私有的 resolveAgentHarnessHistoryLimits 辅助函数应用共享的 Codex 和 Agents API 转录读取预算。

Agents API 会为同一逻辑运行和原生会话的重试保留第一个成功准备好的、有界的钩子历史。 提示钩子仍在每次尝试中使用当前输入和实时宿主权限运行;其历史保持 在原始轮次前快照。因此,已接受的 steering 不会强制 通过原始消息现已过期的准入进行新的转录读取。 此快照是数据,而非更新的转录读取权限:后续转录 更改由下一个逻辑运行观察,而更改的记录器、会话、 运行标识或历史预算需要新的读取。会话重置和运行 取消保留其现有权限检查。

developerInstructions.build 回调接收 toolsAllow 和 hasToolRestrictions。省略的策略或修剪后的 * 条目表示不受限制; 空列表或不包含 * 的列表表示受限。强制实施每轮 限制的后端会在该回调内应用或拒绝它们,在已授权召回 运行之前。Agents API 使用钩子上下文继续,但不强制实施钩子工具列表。

官方测试框架使用仅限 JavaScript 的私有 openclaw/plugin-sdk/agent-harness-attempt-runtime 来处理截止时间、取消 和生命周期/事件发布;它不是第三方 Plugin SDK 契约。 Codex 和 AgentsAPI 还使用 shouldIncludeAgentHarnessRuntimeContext 将运行时提示添加 从轻量级 cron 输入中排除,并使用 resolveAgentWorkspaceMemoryRouting 选择已接受的内存工具并检查 它们是否到达提示工作区。后端保留工作区选择、工具 名称归一化和原生提示渲染。

createAgentHarnessAttemptDeadlineController 接收原始 startedAtMs、 执行 timeoutMs、后端 settlementTimeoutMs、中止 signal 和超时 回调。第一次 beginSettlement(receivedAtMs) 启动一个绝对结算 截止时间;重复调用不会延长它。中止或 dispose() 会关闭它。 createAgentHarnessAttemptCancellation 保留显式取消原因, 并在终端边界冻结准入。emitAgentHarnessAttemptEvent 隔离观察者失败,createAgentHarnessAttemptLifecycle 门控 生命周期事件并去重执行阶段。原生中断、 完成决策、输出刷新和清理仍由后端负责。

私有 openclaw/plugin-sdk/agent-harness-tool-runtime 通过 createAgentHarnessToolExecutionRegistry 和 createAgentHarnessToolExecutionBoundaryRegistry 提供关联的执行 Promise 以及参数/开始快照。已消费的快照不能由迟到的完成重新发布。核心工具守卫和 observeToolTerminal 仍保持权威;原生解码和结果编码仍由执行框架负责。

共享宿主工具结果事实

官方执行框架使用私有的、仅限 JavaScript 的 openclaw/plugin-sdk/agent-harness-tool-runtime 来执行宿主工具并记录可移植工具事实。 runAgentHarnessToolInvocation 负责参数准备、在现有执行边界处进行校验、单调执行快照、中间件和 清理。其结果和失败回调会将这些事实传递给原生适配器,而不会接管它们对回执或超时的所有权。 recordAgentHarnessToolResultTelemetry 收集宿主工具投递、媒体、TTS、 cron 和心跳事实,使用调用方准备好的源回复投影。 当展示中间件重写结果时,该调用会保留执行失败。recordAgentHarnessMessagingDelivery 记录已经确认的消息投递,而 recordAgentHarnessToolResultMedia 收集并信任过滤已展示的媒体。 调用方保留其原生回执、路由、取消和结果编码契约;这些辅助函数不会建立投递,也不会授予执行权限。

工作区暂存附件

已接纳的附件事实可以引用暂存在已准备的工作区下的文件,而不是托管媒体存储中的文件。使用来自 openclaw/plugin-sdk/file-access-runtime 的 root(workspaceDir) 和 createStagedInputPathMatcher(root),在有界的 root.read(relativePath, { maxBytes }) 之前验证暂存所有权。 将事实的工作区与尝试的已准备工作区匹配,通过等待的读取保留宿主当前运行的断言,并使用已接纳的媒体事实,而不是从用户或模型文本中提取的路径。匹配器共享暂存所有者的精确标记契约,并且仅为该捕获缓存结果。

最终工具参数校验

官方原生执行框架适配器可以在宿主绑定工具的 execute 调用周围,调用来自私有 openclaw/plugin-sdk/agent-harness-tool-runtime 的 runWithToolExecutionValidation(callId, validate, execute)。校验器在现有工具执行边界处,接收策略和调用前钩子调整后的最终参数。 对于已声明的工具模式,使用共享的模式校验辅助函数。不要 复制私有校验标记,也不要运行第二个调用前钩子。校验 范围限定于该工具调用,并与并发调用保持隔离。

在中间件之前保留已接纳的后台工作:来自 openclaw/plugin-sdk/agent-harness-tool-runtime 的 isAsyncStartedToolResult 和 readAsyncStartedTaskIds 会暴露其任务元数据。来自 openclaw/plugin-sdk/agent-harness-tool-runtime 的 normalizeAcceptedSessionSpawnResult 会保留子会话的完成所有权。将它们记录的事实带入尝试结果,以便恢复机制无法重放已接纳的工作。

终结结果分类

拥有自身协议投影的原生执行框架可以在已完成的回合未产生可见助手文本时,使用来自 openclaw/plugin-sdk/agent-harness-runtime 的 classifyAgentHarnessTerminalOutcome(...)。该辅助函数返回 empty、reasoning-only 或 planning-only,以便 OpenClaw 的回退策略决定是否在不同模型上重试。planning-only 要求执行框架显式提供 planText 字段;OpenClaw 不会从助手文本中推断它。该辅助函数 有意将提示错误、进行中的回合以及诸如 NO_REPLY 的有意静默回复保持未分类。

实时输出 Token 用量

每完成一个模型响应,调用一次 params.hostCapabilities.reportOutputTokens?.(outputTokens)。传入该响应的输出 Token 数,而不是线程生命周期或累计尝试总数。在调用之前,对原生响应通知进行去重。

宿主会将此回调绑定到已接纳的运行,将该响应加入其生命周期范围内的总数,并全局以及通过 params.onAgentEvent 发布累计的 usage 事件。不要发出第二个 usage 事件。重试共享同一运行总数;运行清理会释放它。已关闭或被取代的能力会拒绝报告。无效或非正计数不会发出事件。

该能力是可选的,用于兼容较旧的宿主;当它不存在时,实时输出 Token 报告不可用。请将最后一次响应的上下文快照和持久化的计费用量与此实时计数器分开。

代理结束副作用

原生执行框架必须在最终确定一次尝试后,调用来自 openclaw/plugin-sdk/agent-harness-runtime 的 runAgentEndSideEffects(...)。它会分派可移植的 agent_end 钩子和 OpenClaw 的研究捕获,而不会延迟交互式回复。对于本地、非交互式运行,如果尝试必须等到这些副作用完成才能解决,请使用 awaitAgentEndSideEffects(...)。两个辅助函数都接受与 runAgentHarnessAgentEndHook(...) 相同的 { event, ctx } 负载;它们的失败不会改变已完成的尝试结果。

传入使用与尝试运行所用的相同 EmbeddedRunAttemptParams 通过 buildEmbeddedForegroundPromptContext(params, agentDir) 构建的 ctx.foregroundPromptContext。分离的 Skill Workshop 体验评审会从该上下文重建其系统提示和工具目录,因此评审会共享前台回合的提示缓存前缀。 仅在没有前台提示的运行中省略它,例如 CLI 钩子上下文;对于这些运行,评审会被跳过。

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