会话和结果
原生会话如何绑定到 OpenClaw 会话并镜像到其转录中,以及工具、媒体、终端结果和已结算回合的结果如何通过 attempt result 返回。属于 Agent harness 插件 参考的一部分。
原生会话与转录镜像¶
一个 harness 可能保留原生会话 ID、线程 ID 或守护进程侧恢复 token。将该绑定显式关联到 OpenClaw 会话,并持续将用户可见的助手/工具输出镜像到 OpenClaw 转录中。
OpenClaw 转录仍然是以下场景的兼容层:
- 频道可见的会话历史
- 转录搜索和索引
- 在后续回合切换回内置 OpenClaw harness
- 通用的
/new、/reset以及会话删除行为
对于用户消息镜像,请使用来自 openclaw/plugin-sdk/agent-harness-runtime 的
restorePreparedUserTurnOperationalMetaForRuntime({ runtimeMessage, preparedMessage })。
将宿主准备好的输入的独立、可信快照作为 preparedMessage 传入。在可能就地修改它们的钩子之前,
克隆 content 和所选提及元数据,并保持该快照不变。
该辅助函数会在用户消息上恢复操作元数据,而不会替换原生内容或钩子重写后的内容。
非用户运行时消息将原样返回。只有当整个 content 值与准备好的快照完全匹配时,
人类提及才会保留;修改后的文本不得继承旧的选择。
恢复的元数据既不会授权操作,也不能证明一次新的转录追加。在规范追加之后,
将其已提交的消息、锚点以及实际的 { appended } 结果传递给
userTurnTranscriptRecorder.markRuntimePersisted(...)。只有 appended: true
才能触发原始输入提交通知;幂等的历史匹配必须报告 false。
将原生绑定存储在插件状态中。实现 reset(...) 用于就地会话重置,并实现
withSessionDeletion(params, run) 用于删除会话键,包括过期和维护。同一键下物理会话 ID
的变化是转移,而不是删除;保留任何压缩采纳路径。
Core 会为每个 harness ID、每个进程记录一次 reset-hook 失败,包括跨插件重载。 后续重置仍会调用该钩子,以便其可以恢复。
当新默认位置为空时,ACPX 会自动将会话从其旧的 <workspace>/state 默认位置迁移到
<OPENCLAW_STATE_DIR>/acpx。仅当需要保留不同位置时,才设置
plugins.entries.acpx.config.stateDir;显式值永远不会被重新定位。采纳失败会发出警告,
并为该进程保留旧位置,以免更新悄悄隐藏现有会话。
withSessionDeletion 在调用 run({ commit, rollback }) 之前获取原生所有者的租约。
Core 在会话行删除边界处调用同步的 commit(),并在事务失败时调用 rollback()。
回滚还必须容忍失败或未应用的提交。将异步订阅清理保留在 run 之后,以免持有
SQLite 写入队列;在会话事务提交后,不要为错误恢复绑定。
在等待的工作之后以及修改原生状态之前,重新检查 params.assertCurrent()。
该回调属于一个已注册 harness 的生命周期;在操作关闭后保留它并不会保留权限。
删除后钩子是通知,而不是持久绑定删除的所有者。
当原生绑定必须因成功的同键回退或分支切换而失效时,实现
withSessionContextReset(params, run)。此可选钩子使用相同的已准备 commit/rollback
契约,但保留会话键和保留的历史。Core 仅在验证请求的截断后提交失效,并在转录事务失败时
恢复它。在已提交的变更稳定后释放订阅。可选的 previousSessionId 是记录的前驱,
允许在压缩后退役尚未转移的绑定,而无需在准备期间采纳它。普通压缩不会调用此钩子,
并继续保留原生线程连续性。
共享原生绑定生命周期¶
官方 harness 使用仅 JavaScript 的私有 openclaw/plugin-sdk/agent-harness-session-runtime;
它不是第三方 Plugin SDK 契约。绑定变更使用与操作绑定的插件状态观察和共享状态工作进程中的
条件写入。同步读取仍然服务于原生租约断言,同步删除/回滚仍然是宿主现有事务契约的一部分。
createNativeSessionBindingLifecycle 负责精确 token 租约获取、续期、变更栅栏以及事务性
删除/回滚。后端提供同一插件状态命名空间的匹配同步和异步视图、其记录编解码器、获取/保留
策略、错误和计时。通过 assertCurrent 传递宿主权限,并在 assertRecordCurrent 中验证
预期的 generation。租约协调存储;它们不授予执行权限。将原生清理保留在宿主事务提交之后。
在 withLease 内部,调用 captureLeaseAssertion(key) 以捕获精确的所有者,并在原生请求或
转录写入之前重新检查其存活且未过期的租约。将其与宿主权限结合用于常规工作。清理可以在宿主
退役后使用保留的租约所有权,但即使 harness 仍然存活,也必须拒绝已过期、已被替换或已关闭的
租约。
captureNativeSessionGenerationAuthority、reclaimNativeSessionGeneration 和
resolveNativeSessionBinding 在等待期间保留宿主 generation 和前驱,并在过期回收之前采纳
经过验证的前驱。缺失的宿主条目允许临时会话;读取失败不能授权绑定。
createNativeSessionInitializationOwner 将绑定和上游链接写入与精确的宿主创建句柄关联。
回滚需要匹配的存储、身份、绑定和存活权限,仅删除精确的上游链接,然后调用后端清理。
队列选择、原生协议/策略和资源清理仍由后端负责;core 拥有宿主会话生命周期。
工具与媒体结果¶
openclaw/plugin-sdk/agent-harness-runtime 中的 inferToolMetaFromArgs 返回紧凑的、有损的显示元数据。深度超过 64 层的数组值会被省略;较浅的兄弟节点仍会参与预览。该辅助函数可能返回 undefined。保留原始参数用于校验和执行:显示元数据既不是参数替换,也不是通用遍历限制。
核心构造 OpenClaw 工具列表,并将其传入已准备的尝试。当执行框架执行动态工具调用时,应通过执行框架结果形状返回工具结果,而不是自行发送频道媒体。
这使文本、图像、视频、音乐、TTS、审批和消息工具的输出与 OpenClaw 支持的运行保持相同的投递路径。
对于消息工具,使用 openclaw/plugin-sdk/agent-harness-runtime 中的 readEmbeddedMessageDeliveryFact 读取原始结果的 details.messageDelivery。只有已确定投递才算作已发送消息;成功的试运行和被抑制的发送不得抑制后续回复。当工具同时报告错误时,保留部分投递证据。没有投递事实的消息工具结果使用 isDeliveredMessagingToolResult,它负责工具资格和回执解释。对于核心会话工具,它会读取原始 Gateway 结果的 details.status:sent 确认投递,conversations_turn 的 replied 和 timeout 也确认投递。对等回复超时或关联错误不会撤销频道发送,也不会改变工具的错误状态。queued、suppressed 和 unknown 不确认投递,即使它们包含已准备的消息 ID。会话协调结果不是外部投递回执。当旧版插件结果需要具体消息 ID 时,使用 requirePluginDeliveryId: true;权威核心会话状态不需要它。projectPluginMessageDeliveryFact 将旧版结果信封读取为共享投递形状,并保留部分投递状态用于附件处理。对于旧版消息发送,除非结果确认部分投递,否则错误优先于消息 ID。使用 isDeliveredMessagingToolSendToCurrentSource 进行源路由比较,并使用 extractMessagingToolSourceReplyPayload 保留附件元数据和转录所有者的确认。展示中间件不能建立新的投递事实。
同一运行时入口导出 sanitizeToolArgs,用于诊断工具参数和事件负载。它会脱敏嵌套字段而不修改输入,并保留自身的 JSON 键,包括 __proto__;重复引用会变成 "[Circular]"。使用 sanitizeToolResult 进行结果展示,它还会应用共享的结果大小和图像存储规则。
对于成功的 sessions_spawn 结果,使用 openclaw/plugin-sdk/agent-harness-tool-runtime 中的 normalizeAcceptedSessionSpawnResult,并将其 AcceptedSessionSpawn 保留在尝试的 acceptedSessionSpawns 中。在中间件修改其详情之前捕获原始结果。保留 expectsCompletionMessage:核心需要该事实,以便在请求方让出时转移子完成投递。该辅助函数对未接受或不完整的回执返回 null,并将缺失的完成意图视为 false。
仅为可信执行框架运行时自行创建并持久化的原生工件设置 AgentHarnessAttemptResult.hostOwnedToolMediaUrls。每个条目还必须出现在 toolMediaUrls 中。切勿包含模型选择的动态工具或 OpenClaw 工具媒体。在 message_tool_only 路由上,这种狭窄的来源证明可让原生运行时工件在源回复抑制中存活;正常发送策略和环境房间准入仍然适用。
工具终结结果¶
AgentHarnessAttemptParams.observeToolTerminal 是宿主拥有的终结结果累加器。执行 OpenClaw 动态工具或原生工具的执行框架必须在每个工具达到一个终结结果时调用它,且在尝试结果最终确定之前。不执行工具的执行框架无需调用它。
从执行边界报告事实:
- 当存在协议调用 ID 时,传递协议调用 ID、规范工具名称,以及经过准备或钩子重写后实际到达工具的参数。
- 将原始宿主工具结果或抛出的错误作为
result传递。核心从该对象读取私有效果来源证明;序列化字段无法提供此证明。在投影宿主结果时,保留内部结果状态。 - 当校验、审批或其他守卫在工具实现开始前阻止调用时,设置
executionStarted: false。一旦分发可能已经发生,保守地报告true。 - 报告
outcome: "success"或outcome: "failure"。包含运行时可用的结构化失败字段,而不是从显示文本推断失败。 - 仅对不使用 OpenClaw 工具定义的原生工具使用
nativeMutation。在那里提供协议拥有的变更和重放事实;不要将 OpenClaw 的变更分类器复制到执行框架中。
该回调返回该调用的规范解析结果。将其 lastToolError 带入 AgentHarnessAttemptResult,并在执行框架投影中使用其执行、参数和副作用事实,而不是推导并行状态。宿主会跨无关的成功工具保留未解决的变更失败,并仅在匹配操作成功后清除它。
为了与旧版实验性执行框架保持源码兼容性,该回调仍为可选。对于执行工具的执行框架而言,可选并不意味着可忽略:如果没有终结报告,OpenClaw 无法在后续工具调用中保留变更工具的失败真相,包括静默心跳完成。
已确定工具最终化¶
在执行框架已完成所有工具调用,但其原生回合在没有助手文本的情况下结束时,OpenClaw 可能需要一个最终的可见回答。执行框架可以通过实现 finalizeSettledTurn({ attempt, settledAttempt }) 来选择加入该恢复机制。
回调是一项独立能力,而不是另一次普通尝试。它必须:
- 使用完全受限的原生转录,或通过已确定工具结果边界冻结的完整应用转录;
- 不暴露任何工具、权限授予或用户输入能力、原生执行钩子、代理、技能、记忆、调度、扩展或远程控制;
- 仅发送宿主提供的最终化提示;并且
- 如果其选定的转录/隔离策略无法强制实施这些限制,则失败关闭。
OpenClaw 将回调作为终端子操作调用一次,位于普通尝试和重试循环之外。失败会以副作用感知的不完整回合警告结束运行;它不能进入普通认证/配置文件轮换、模型回退、上下文恢复、压缩续接或钩子请求的修订路径。最终化还会跳过插件提示变更、before_agent_run、LLM 输入/输出、终端修订以及 agent_end 钩子。核心诊断仍会记录该操作及其失败。
回调返回 AgentHarnessSettledTurnFinalizationResult,而不是普通尝试结果。其公开字段仅限于已完成的助手消息、最终化调用用量、转录所有权元数据和诊断跟踪。工具、投递、媒体、生成、生命周期、重放、会话和回退状态不能跨越此结果边界。未知字段和助手工具调用会失败关闭。
内部复用其完整尝试引擎的 harness 可以在返回前调用 projectSettledTurnFinalizationAttemptResult(...)。该辅助函数拒绝规范失败、工具、投递、重放和生命周期证据,然后仅投射窄结果。它是原生隔离之后的纵深防御,而不是移除原生能力表面的替代方案。
基于投射的 harness 必须在已确定回合被镜像后捕获活动分支,并证明当前提示以及每个当前工具调用/结果都通过该边界存在。将冻结证据放在 settledAttempt.settledTurnFinalizationContext 上,作为以下之一:
source: "openclaw-transcript"并带messages:通过边界的完整应用转录。source: "harness"并带data:一个不可变的有界投射,仅由拥有该 harness 解释。核心将此不透明值透传;最终化器在使用前必须验证其自身的上下文类型。source: "unavailable":harness 允许对此已确定回合进行最终化,但无法捕获安全重放证据。最终化器必须在提供程序或原生 I/O 之前拒绝此状态;核心仍可使用其现有的宿主拥有的回退,而不重复工具。
不可用状态记录资格,而不是已验证的历史。符合条件的捕获失败,包括缺失、漂移或过大的证据,可以到达该无模型回退。不要对 harness 从最终化中排除的失败发出它,例如认证或使用限制错误。仅命令 harness 必须在 messagesSnapshot 中保留归属的助手工具调用条目;当可见助手字段缺失时,宿主回退可以使用该已确定批次身份。
在获取消息时强制实施投射限制,而不是在检查大小之前克隆整个转录。成功捕获必须在返回尝试之前完成所有身份和来源证据检查。不要在 data 中保留打开的转录读取器。最终化器必须拒绝缺失、不支持、模糊或过大的上下文。它不得截断消息、丢弃较早历史,或将应用投射描述为精确原生历史。恢复一个受限原生会话的 harness 不需要此投射字段。
不要通过调用带有尽力而为 disableTools 提示的 runAttempt 来实现此回调。harness 所有者必须强制实施完整的原生能力边界。OpenClaw 不提供通用回退,因为它无法证明任意原生运行时遵守了这些限制。
回调对于实验性第三方 harness 兼容性仍保持可选。当所选 harness 省略它时,OpenClaw 保留现有的不完整回合错误,而不是冒着重复副作用的风险。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw