OpenClaw 会话转录卫生(Transcript Hygiene):Provider 重放前的内存级清理、配对修复与签名处理机制全解

发布时间:2026/9/13 17:53:10
OpenClaw 会话转录卫生(Transcript Hygiene):Provider 重放前的内存级清理、配对修复与签名处理机制全解 OpenClaw 会话转录卫生Transcript HygieneProvider 重放前的内存级清理、配对修复与签名处理机制全解【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 项目地址: https://gitcode.com/GitHub_Trending/cl/openclawOpenClaw 在每次模型调用构建模型上下文之前会对会话历史做一层Provider 专属的内存级转录修复以匹配不同模型供应商的严格协议要求工具调用 ID 格式、轮次交替、思考签名、图片尺寸等同时绝不改写 SQLite 中持久化的运行时转录状态。本文基于 docs/reference/transcript-hygiene.md 展开结合 transcript-policy.ts、replay-history.ts、session-transcript-repair.ts 等源码完整梳理 OpenClaw 转录卫生的全局规则、Provider 矩阵行为、失败重试恢复与历史演进帮助你理解并排查“Provider 因转录形状而拒绝请求”“跨 Provider 工具调用 ID 不匹配”一类问题。一、转录卫生是什么一次只发生在出站方向的内存投影OpenClaw 对转录的清理sanitization与修复repair遵循一条核心边界所有 Provider 专属的修复都只是「在构建出站模型上下文之前」对内存副本的调整目的是满足严格 Provider 的协议要求。运行时转录状态始终保存在 SQLite 中Provider 专属的 assistant-prefill助手前缀剥离等操作只发生在构造出站 payload 时。因此任何一次重放修复都不会反向污染已存储的会话事实。原文档给出的 Scope 清单即转录卫生覆盖的全部能力面如下本文后续各节将逐一展开仅存在于运行时runtime-only的提示上下文不进入用户可见的转录轮次工具调用 ID 清理tool call id sanitization工具调用入参校验tool call input validation工具结果配对修复tool result pairing repair轮次校验 / 排序turn validation / ordering思考签名thought signature清理思维块签名thinking signature清理图片 payload 清理image payload sanitizationProvider 重放前空白文本块清理Provider 重放前「不完整 reasoning-only 长度回合」清理用户输入来源标记inter-session 路由提示的 provenance taggingProvider 重放前空 assistant 错误回合移除需要强调这里的“重放”指的是把历史转录再次组装成模型上下文的过程而不是修改存档。若你需要了解转录的存储层细节请阅读 Session management deep dive。二、失败尝试与恢复partial text、工具调用与错误如何落库原文档对“运行失败后转录如何收尾”给出了明确的持久化语义纯文本型 assistant 错误会被缓冲直到整个逻辑运行logical run尘埃落定。若后续恢复成功恢复后的回复会取代失败尝试的部分文本因此恢复路径会丢弃失败尝试的 partial text终结性失败terminal failure则保留最后一次尝试的 partial text 与错误信息工具调用、可展示的非文本内容、附件事实attachment facts会立即持久化先于依赖它们的工具结果或恢复后的回复。这些事实行fact rows不携带错误并使用可重放的 stop reason从而保证 Provider 重放时仍保留这些调用对于「文本 事实」混合的消息partial text 与错误仍被单独缓冲终结性结算不会重复落库事实或 usage 记录。从实现上看这套恢复语义复用现有的 assistant-row 形状不需要数据库迁移与 replay-history.ts 中normalizeAssistantReplayContent对失败占位符如isStreamErrorFallbackContent且stopReason error的丢弃逻辑相互印证失败的尝试没有模型内容重放副本中连其遗留占位符一并丢弃但保留已计费的静默回复与不完整的工具/长度状态。三、全局规则一运行时上下文不是用户转录运行时可向某一轮模型提示中加入 system/runtime 上下文但这部分不是终端用户撰写的内容。OpenClaw 为此维护一份面向转录的独立 prompt body用于 Gateway 回复、排队中的 followup、ACP、CLI 与嵌入式embeddedOpenClaw 运行。已存储的用户可见轮次使用这份转录 body而非运行时增强后的 prompt。对于历史上已经持久化了 runtime wrapper 的旧会话Gateway 历史展示层在把消息返回给 WebChat、TUI、REST 或 SSE 客户端前会应用**展示投影display projection**剥离内部元数据对应stripInternalMetadataForDisplay在 replay-history.ts 中的使用确保用户看到的始终是干净转录。四、在哪里运行策略解析与重放清理的职责边界转录卫生的调度集中在嵌入式运行器embedded runner内部分两个阶段策略解析transcript-policy.ts 中的resolveTranscriptPolicy以provider、modelApi、modelId以及运行时模型元数据、配置、工作区、环境变量为键解析出当前生效的TranscriptPolicy清理/修复应用replay-history.ts 中的sanitizeSessionHistory按解析出的策略执行完整的重放清理管道。4.1 TranscriptPolicy 的结构TranscriptPolicy见 transcript-policy.ts是理解 Provider 差异的钥匙它显式声明了每个 Provider 需要哪些能力字段含义sanitizeMode清理范围full或images-onlysanitizeToolCallIds/toolCallIdMode是否清理工具调用 ID 及其模式如strictpreserveNativeAnthropicToolUseIds是否保留 Anthropic 原生 tool_use IDrepairToolUseResultPairing是否执行工具结果配对修复默认开启preserveSignatures是否保留思维签名appendOnlyRuntimeContext是否以追加方式保留运行时上下文载体前缀绑定模型sanitizeThoughtSignatures思考签名清理选项如仅允许 base64dropThinkingBlocks是否丢弃思维块dropReasoningFromHistory是否从历史中剥离 reasoningapplyGoogleTurnOrdering是否应用 Google 式轮次排序修复validateGeminiTurns/validateAnthropicTurns是否做 Gemini / Anthropic 轮次校验allowSyntheticToolResults是否允许合成工具结果4.2 默认策略与 Provider 专属覆盖DEFAULT_TRANSCRIPT_POLICYtranscript-policy.ts是保守基线默认sanitizeMode: images-only、repairToolUseResultPairing: true、其余开关基本关闭。解析流程是若 Provider 插件实现了buildReplayPolicy钩子则以插件策略为准核心不再按传输族做默认推断否则回退到buildUnownedProviderTransportReplayFallbacktranscript-policy.ts为 Google / Anthropic / 严格 OpenAI 兼容等无宿主插件的传输族提供窄回退策略。策略解析结果按config对象做WeakMap缓存transcriptPolicyCache缓存键涵盖 provider、modelApi、modelId、canonicalModelId、是否丢弃思维块、是否保留 reasoning 重放、工作区与插件控制面指纹等resolveTranscriptPolicyCacheKey同一 provider/model/config 元组不会重复解析。值得注意的细节buildUnownedProviderTransportReplayFallback会根据 model id 判断 Claude 家族isClaudeFamilyModelId的正则匹配、根据model.reasoning true或REASONING_CONTENT_REPLAY_MODEL_IDS集合包含 Kimi、Mimo 等模型 id决定是否保留 reasoning 内容重放providerRequiresSignedThinking则把anthropic、amazon-bedrock、anthropic-vertex归为“拥有签名思维块”的 Provider 家族。4.3 旧式 JSONL 校验归属需要区分两个系统Legacy JSONL 的校验与导入属于openclaw doctor --fix嵌入式运行器不会去修复或重新打开文件型运行时转录。也就是说转录卫生是运行时出站投影的职责文件导入修复是doctor命令的职责二者互不越界。五、全局规则二图片清理image sanitization图片 payload始终被清理目的是防止因尺寸超限导致 Provider 拒绝请求对超大的 base64 图片做降采样/重压缩。这同时有助于控制视觉模型的 token 压力最大边长越小 token 占用越低越大细节保留越多。实现位置sanitizeSessionMessagesImages在 src/agents/embedded-agent-helpers/images.ts即sanitizeSessionMessagesImages定义处sanitizeContentBlocksImages在 src/agents/tool-images.ts最大边长通过agents.defaults.imageMaxDimensionPx配置默认值为1200像素该限制通过resolveImageSanitizationLimits注入重放管道此外图片清理这一遍遍历重放内容时还会顺带移除空白文本块清理后变空的 assistant 回合被丢弃除非它持有不透明的 Provider 重放状态变空的 user 回合与 tool-result 回合则被替换为非空的内容省略占位符omitted-content placeholder保证轮次形状完整。六、全局规则三畸形工具调用malformed tool calls同时缺失input和arguments的 assistant 工具调用块在构建模型上下文前会被直接丢弃。这能防止因部分持久化的工具调用例如限流失败后留下的残片触发 Provider 拒绝。实现sanitizeToolCallInputs定义于 session-transcript-repair.ts在sanitizeSessionHistoryreplay-history.ts中应用。从源码看repairToolCallInputs还会校验工具名isAllowedToolCallName仅允许allowedToolNames内的调用、剥离工具名首尾空白sanitizeToolCallBlock并在允许 Provider 思维重放时尽量保留「思维块 合法工具调用」的回合isReplaySafeThinkingAssistantTurn因为 Anthropic 签名思维块必须字节级稳定。丢弃畸形调用时同步计数droppedToolCalls与droppedAssistantMessages保证修复报告可观测。七、全局规则四工具结果配对修复tool result pairing工具结果在每个 assistant 回合内部与工具调用出现位置配对之后才会重写 Provider 专属的调用 ID。原因在于Provider 生成的 ID 可能在后续回合重复因此与重复调用相邻的结果必须留在它所属的那次出现上。配对修复的边界条件如下被错位displaced的结果只有在「恰好存在一个未解析的出现可归属」时才会被移动模棱两可的多余结果被丢弃缺失的结果出现会被合成错误结果synthetic error result填充。实现sanitizeToolUseResultPairing对外导出sanitizeToolUseResultPairingForModel位于 session-transcript-repair.ts合成缺失结果走makeMissingToolResult复用packages/agent-core/src/harness/session/tool-result-pairing.js的配对分类逻辑。两个重要的进阶细节模型切换时Provider 重放会把延迟的异步工具结果移动到其发起调用的旁边然后再移除源模型的异步元数据匹配前会先修剪调用 ID 与结果 ID 的首尾空白避免真实结果因为多余的空白被误判为“缺失结果”而合成错误结果。此外OpenAI Responses 家族在配对修复之后还会执行一次不变式断言assertOpenAIResponsesToolUseResultInvariant会扫描整个历史任何悬空工具调用dangling tool call或孤儿工具结果orphan tool result都会抛出invalid_replay_transcript: OpenAI Responses replay contains ...错误并附带 message index把“静默出错”变成“可定位的显式失败”。八、全局规则五不完整或静默的 reasoning-only 回合在以下两类事件发生后仅含 thinking 或 redacted-thinking 内容的 assistant 回合会从内存重放副本中省略Provider 输出上限导致回合以「不完整 reasoning 状态」结束静默回复清理silent-reply cleanup移除了该回合唯一的可见NO_REPLY文本。静默回复清理的目的很关键防止隐藏的 reasoning 在严格 Provider 重建对话时合并进后续的 assistant 工具使用回合。边界条件同样明确空长度回合empty length turns保持不变含可见文本、工具调用或未知内容块的 length 回合保持不变含工具调用或未知内容块的静默回复回合保持不变存储的转录不会被重写。实现normalizeAssistantReplayContent位于 replay-history.ts。源码中该函数还负责移除转录专用的 OpenClaw assistant 消息isTranscriptOnlyOpenClawAssistantMessage仅从重放副本丢弃、JSONL 保留丢弃空白的 user 文本块剥离 assistant 文本的内部元数据并识别SILENT_REPLY_TOKEN静默文本丢弃「裸 delivery-mirror 重复」回合零 usage、stop reason 为 stop、与前一 assistant 回合内容深度相等。这与原文档「store 不重写」的原则完全一致重放副本可增删持久化事实不动。九、全局规则六会话间输入来源标记inter-session provenance当 Agent 通过sessions_send向另一会话发送提示包括 agent 间回复/公告步骤时OpenClaw 会以message.provenance.kind inter_session持久化新建的 user 回合并且在路由提示文本前追加同一回合内的[Inter-session message] ... isUserfalse标记使当前模型调用能区分「外部会话的输出」与「终端用户的指令」该标记尽可能包含源会话、渠道与工具信息转录在 Provider 侧仍使用role: user保证兼容性但可见文本与 provenance 元数据都标注其为 inter-session 数据上下文重建时OpenClaw 对只有 provenance 元数据、缺少标记的旧 inter-session user 回合应用同样的标记。实现上annotateInterSessionUserMessagesreplay-history.ts在sanitizeSessionHistory管道第一步执行对字符串内容与内容块数组中的文本块分别注入annotateInterSessionPromptText无文本块的 user 回合则前置一条Inter-session content follows.说明文本。相关 provenance 归一化逻辑位于 src/sessions/input-provenance.ts。十、Provider 矩阵当前各家的转录行为对照原文档给出了详尽的 Provider 行为矩阵这是排查“为何这个 Provider 拒绝了这段历史”的第一手对照表完整继承如下。10.1 OpenAI / OpenAI Codex仅做图片清理no-touch beyond image sanitization丢弃孤立的 reasoning 签名后面没有 content block 的独立 reasoning 项并在模型路由切换后丢弃可重放的 OpenAI reasoning保留可重放的 OpenAI Responses reasoning item payload包括加密的空摘要项保证手动/WebSocket 重放时rs_*状态与 assistant 输出项配对原生 ChatGPT Codex Responses 按 Codex wire 对齐方式重放历史 Responses reasoning/message/function payload不携带先前的 item ID同时保留会话prompt_cache_keyOpenAI Responses 家族重放保留同模型的call_*|fc_*reasoning 配对但在 pi-ai payload 转换前确定性归一化畸形或过长的call_id/function-call item id对应normalizeOpenAIResponsesToolCallIds工具结果配对修复可能移动真实匹配的输出并为缺失的工具调用合成 Codex 风格的aborted输出不做轮次校验/排序不剥离 thought 签名。10.2 OpenAI-compatible Chat Completions历史 assistant thinking/reasoning 块在重放前被剥离避免本地与代理式 OpenAI 兼容服务器收到reasoning、reasoning_content等前轮 reasoning 字段当前同轮的工具调用延续tool-call continuation在工具结果重放完成前保留附着在工具调用上的 assistant reasoning 块自定义/自托管模型中reasoning: true的条目保留重放的 reasoning 元数据当其 wire 协议要求重放 reasoning 元数据时Provider 持有的例外可以退出剥离opt out。10.3 GoogleGenerative AI / Gemini CLI / Antigravity工具调用 ID 清理严格字母数字strict alphanumeric工具结果配对修复与合成工具结果轮次校验Gemini 风格轮次交替validateGeminiTurnsGoogle 轮次排序修复历史以 assistant 开头时前置一个极小的 user 引导回合bootstrapAntigravity Claude归一化 thinking 签名丢弃未签名的 thinking 块。10.4 Anthropic / MinimaxAnthropic-compatible前缀绑定prefix-bindingClaude 模型如 Fable 5.1会把运行时上下文载体持久化为紧接其 user 回合的隐藏自定义消息并在重放时原位回放旧 user 回合上的内联入站元数据也会保留。这一「按模型作用域的追加策略」覆盖 Bedrock、Vertex、Foundry 路由。载体只包含定界上下文体共享指令只存在于稳定的 system prompt 中一次载体保持 user 角色不进入聊天历史也不参与压缩摘要。其他 Claude 模型与 Anthropic 兼容模型则使用瞬时载体避免在没有前缀绑定时为旧载体反复支付缓存读取费用与上下文占用工具结果配对修复与合成工具结果轮次校验合并连续 user 回合以满足严格交替。但对前缀绑定模型的 Messages API追加式重放会保持连续 user 回合分离命令回合后接提示回合按各自时间戳重放Bedrock Converse 仍会合并它们对应shouldMergeConsecutiveUserTurns仅appendOnlyRuntimeContext modelApi anthropic-messages时不合并启用 thinking 时尾部 assistant prefill 回合会从出站 Anthropic Messages payload 中剥离包括 Cloudflare AI Gateway 路由压缩compaction后的 pre-compaction assistant thinking 签名会被剥离再重放压缩改变了被签名前缀摘要内容取代原文回放原签名会导致 Anthropic 以 “Invalid signature in thinking block” 拒绝请求。思维文本保留为无符号块交给下一条规则处理签名缺失/为空/为空白blank的 thinking 块在 Provider 转换前被剥离若因此清空某 assistant 回合OpenClaw 用非空 omitted-reasoning 文本保持回合形状必须被剥离的旧 thinking-only assistant 回合会被替换为非空 omitted-reasoning 文本避免 Provider 适配器丢弃重放回合。10.5 Amazon BedrockConverse API从内存重放副本中丢弃空的 assistant 流错误回合与旧式 fallback 占位符避免产生非法空 ContentBlocks 与合成 assistant prefill同时不改写存储转录零 usage 的空 stop 回合也被丢弃已计费的静默回复与带真实 assistant 内容的错误回合保留原有重放处理与 Anthropic 相同的原因压缩后的 pre-compaction thinking 签名在 Converse 重放前被剥离签名缺失/为空/为空白的 Claude thinking 块在 Converse 重放前被剥离清空回合时用非空 omitted-reasoning 文本保持轮次形状必须剥离的旧 thinking-only assistant 回合替换为非空 omitted-reasoning 文本保持 Converse 严格轮次形状重放会过滤 OpenClaw 的 delivery-mirror 与 gateway 注入的 assistant 回合图片清理经由全局规则生效。10.6 Mistral含基于 model-id 的检测工具调用 ID 清理strict9字母数字长度固定为 9。10.7 OpenRouter Gemini思考签名清理剥离非 base64 的thought_signature值保留 base64 值。10.8 OpenRouter Anthropic对已验证的 OpenRouter OpenAI 兼容 Anthropic 模型在启用 reasoning 时剥离尾部 assistant prefill 回合与直连 Anthropic 和 Cloudflare Anthropic 的重放行为保持一致。10.9 其他一切 Provider仅做图片清理image sanitization only。十一、重放清理管道全景sanitizeSessionHistory 内部顺序把上述规则落到代码上sanitizeSessionHistoryreplay-history.ts的执行顺序即一次完整的内存投影流水线解析策略未显式传入时调用resolveTranscriptPolicy注入 inter-session 标记annotateInterSessionUserMessages规范化 assistant/user 重放内容normalizeAssistantReplayContent空文本、静默回复、流错误占位、reasoning-only 回合、mirror 重复等图片清理sanitizeSessionMessagesImages受sanitizeMode与图片尺寸限制控制压缩导致的过期 thinking 签名剥离stripStaleThinkingSignaturesForCompactionReplay仅签名 Provider 或preserveSignatures时无效 thinking 签名剥离stripInvalidThinkingSignatures保留最新 assistant thinking按策略剥离 reasoningdropReasoningFromHistory与 thinking 块dropThinkingBlocks工具调用入参清理sanitizeToolCallInputsOpenAI Responses 分支配对修复 → 剥离过期 reasoning → 归一化工具调用 ID → 降级 function-call reasoning 对sanitizeToolUseResultPairingForModeldropStaleOpenAIReasoningnormalizeOpenAIResponsesToolCallIdsdowngradeOpenAIFunctionCallReasoningPairs非 Responses 分支通用配对修复工具调用 ID 清理sanitizeToolCallIdsForCloudCodeAssist按toolCallIdMode工具结果细节剥离stripToolResultDetails与 usage 快照归一化ensureAssistantUsageSnapshots保留 Provider 计费的totalOriginProvider 插件重放钩子sanitizeProviderReplayHistoryWithPlugin钩子后重新断言配对策略与 Responses 不变式assertOpenAIResponsesToolUseResultInvariant模型切换快照记录appendModelSnapshotMODEL_SNAPSHOT_CUSTOM_TYPE需要时执行 Google 轮次排序修复sanitizeGoogleTurnOrdering严格 OpenAI 兼容的 vLLM/Gemma 等同样会拒绝 assistant 开头的对话Responses 分支最后再做一次不变式断言。与管道并行的还有validateReplayTurnsreplay-history.ts先尝试 Provider 插件的轮次校验钩子否则按策略执行validateGeminiTurns与validateAnthropicTurns连续 user 回合是否合并由shouldMergeConsecutiveUserTurns决定。十二、历史行为2026.1.22 之前与架构收敛在 2026.1.22 版本之前OpenClaw 的转录卫生存在多层叠加一个transcript-sanitize 扩展在每次上下文构建时运行能修复工具使用/结果配对、清理工具调用 ID包括保留_/-的非严格模式运行器同时做 Provider 专属清理与扩展职责重复在 Provider 策略之外还有额外变更持久化前剥离 assistant 文本中的final标签、丢弃空 assistant 错误回合、在工具调用后裁剪 assistant 内容。这套复杂度引发了跨 Provider 回归最典型的是openai-responses的call_id|fc_id配对问题。2026.1.22 的清理动作是移除该扩展、把逻辑集中到运行器、并让 OpenAI 在图片清理之外变成 no-touch。这一历史沿革解释了为什么现在所有修复都收敛在sanitizeSessionHistory单一管道中、并由resolveTranscriptPolicy统一裁决。十三、排查实践建议与相关文档根据原文档的read_when指引以下场景应优先查阅本机制正在调试「Provider 因转录形状而拒绝请求」先确认resolveTranscriptPolicy对该 provider/modelApi/modelId 解析出的TranscriptPolicy尤其是sanitizeMode、validateAnthropicTurns、dropThinkingBlocks、sanitizeToolCallIds正在修改转录清理或工具调用修复逻辑以 replay-history.ts 的sanitizeSessionHistory管道为主入口新增规则应保持「内存投影、不改写存储」的边界正在排查跨 Provider 的工具调用 ID 不匹配对照「全局规则四」的回合内配对语义、ID 修剪规则以及 OpenAI Responses 的assertOpenAIResponsesToolUseResultInvariant不变式遇到 Anthropic 的 “Invalid signature in thinking block”优先检查是否经过压缩前缀已变以及 thinking 签名是否缺失/为空/为空白——这两类都是设计内会被剥离的场景。相关纵深阅读Session management、Session pruning、Session management compaction。如果你还负责排查压缩与签名问题thinking-signatures.ts 中的stripStaleThinkingSignaturesForCompactionReplay是定位签名过期的直接入口。【免费下载链接】openclawThe AI that really does things. Any OS. Any Platform. The lobster way. 项目地址: https://gitcode.com/GitHub_Trending/cl/openclaw创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询