Skip to content

fix(agents): recover invalid OpenAI Responses reasoning replay#84267

Closed
tianxiaochannel-oss88 wants to merge 5 commits into
openclaw:mainfrom
tianxiaochannel-oss88:fix/responses-thinking-signature-clean-retry
Closed

fix(agents): recover invalid OpenAI Responses reasoning replay#84267
tianxiaochannel-oss88 wants to merge 5 commits into
openclaw:mainfrom
tianxiaochannel-oss88:fix/responses-thinking-signature-clean-retry

Conversation

@tianxiaochannel-oss88

@tianxiaochannel-oss88 tianxiaochannel-oss88 commented May 19, 2026

Copy link
Copy Markdown
Contributor

Fixes the OpenAI Responses half of #84002.

This intentionally does not change Slack main/thread session routing. The issue combines two continuation failures; this PR addresses the deterministic Responses replay failure where preserved encrypted reasoning can be rejected with thinking_signature_invalid.

Root cause

OpenAI Responses can reject a replayed encrypted reasoning item when the stored rs_* content is no longer verifiable. Current history cleanup only drops replayable OpenAI reasoning when the model snapshot changes or when the reasoning block is orphaned, so a same-provider/same-model continuation can replay the stale encrypted reasoning again.

That error was also classified as a generic schema/format rejection, so terminal failures surfaced as "provider rejected the request schema" instead of a replay-state recovery error.

What changed

  • Classify thinking_signature_invalid and encrypted reasoning verification/decryption failures as replay-invalid.
  • Wrap OpenAI Responses stream calls with a one-shot recovery path:
    • if the request fails before any streamed chunk, or the current Responses transport emits a pre-start assistant error event/result with invalid encrypted reasoning, drop replayable OpenAI reasoning blocks
    • downgrade paired call|fc tool call ids after dropping reasoning
    • retry the same model call once
    • keep dropping replayable reasoning for later calls in the same session wrapper after recovery is activated
  • Do not retry if any stream chunk was already yielded, to avoid duplicate visible output/events.

User impact

A Slack or channel continuation that hits stale OpenAI Responses encrypted reasoning should get one clean retry instead of ending the turn with no visible assistant content. If the retry still fails, the user-facing error now points to invalid session/replay state instead of a generic schema rejection.

Real behavior proof

Behavior or issue addressed: OpenAI Responses continuation recovery for thinking_signature_invalid / invalid encrypted reasoning replay.

Real environment tested: Local OpenClaw checkout on this PR branch at original proof head edc7ccba2a0ab7a3f972362b5ee74753ff0fb302, then rebased/verified again at current PR head 09f8de688fbfc88e49ac7dd3c27101a0b8a16142, on macOS with Node v24.15.0. The committed proof harness uses the real OpenAI SDK HTTP transport and OpenClaw's current createOpenAIResponsesTransportStreamFn() plus wrapOpenAIResponsesStreamWithReplayRecovery() against a loopback /v1/responses endpoint. It does not mock the OpenAI SDK; the loopback endpoint returns provider-shaped HTTP 400 and SSE responses so reviewers can inspect the request/retry payload transition.

Exact steps or command run after this patch:

node --import tsx scripts/proofs/openai-responses-replay-recovery.ts

Evidence after fix:

[openai-transport] [responses] error provider=openai api=openai-responses model=gpt-5.4 name=Error status=400 code=thinking_signature_invalid type=invalid_request_error causeName=undefined causeCode=undefined message=400 The encrypted content for item rs_real_transport_proof could not be verified. Reason: Encrypted content could not be decrypted or parsed.
[agent/embedded] [session-recovery] OpenAI Responses reasoning replay rejected; retrying once without replayable reasoning: sessionId=real-http-transport-proof-session
OpenAI Responses replay recovery proof: PASS
Runtime path: real OpenAI SDK HTTP transport against loopback /v1/responses
Mocking: no vi.mock/openai SDK mock; loopback server returns provider-shaped HTTP/SSE
Requests observed: 2
Request paths: /v1/responses, /v1/responses
First response: HTTP 400 thinking_signature_invalid
First request input types: reasoning, message
Retry request input types: message
Retry dropped replayed reasoning: true
Retry preserved replayed message: true
Recovered assistant text: recovered via real http transport
Final stopReason: stop

Observed result after fix: The first real SDK HTTP request contains replayed reasoning and receives a provider-shaped thinking_signature_invalid 400. The wrapper retries once. The second real SDK HTTP request drops replayed reasoning, preserves the replayed visible message, consumes the SSE response, and returns assistant text with stopReason: stop.

Committed inspectable proof: scripts/proofs/openai-responses-replay-recovery.ts is the manual proof harness. src/agents/pi-embedded-runner/openai-responses-transport-replay-recovery.test.ts remains the regression test that locks in the mocked-SDK transport error-event path.

What was not tested: Live Slack and live OpenAI Responses were not used. Slack session routing from #84002 is intentionally out of scope for this PR.

Exact steps or command run after this patch

node --import tsx scripts/proofs/openai-responses-replay-recovery.ts
./node_modules/.bin/oxlint --tsconfig config/tsconfig/oxlint.scripts.json scripts/proofs/openai-responses-replay-recovery.ts
node scripts/run-vitest.mjs src/agents/pi-embedded-runner/openai-responses-transport-replay-recovery.test.ts
node scripts/run-vitest.mjs src/agents/pi-embedded-runner/thinking.test.ts
node scripts/run-vitest.mjs src/agents/pi-embedded-helpers.formatassistanterrortext.test.ts
node scripts/run-tsgo.mjs -p tsconfig.core.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core.tsbuildinfo
git diff --check

Rebase refresh at current PR head 09f8de688fbfc88e49ac7dd3c27101a0b8a16142:

node --import tsx scripts/proofs/openai-responses-replay-recovery.ts
./node_modules/.bin/oxlint --tsconfig config/tsconfig/oxlint.scripts.json scripts/proofs/openai-responses-replay-recovery.ts
node scripts/run-vitest.mjs src/agents/pi-embedded-runner/openai-responses-transport-replay-recovery.test.ts
node scripts/run-vitest.mjs src/agents/pi-embedded-runner/thinking.test.ts
node scripts/run-vitest.mjs src/agents/pi-embedded-helpers.formatassistanterrortext.test.ts
node scripts/run-tsgo.mjs -p tsconfig.core.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core.tsbuildinfo
git diff --check

Validation

openai-responses-replay-recovery.ts proof harness: PASS
script oxlint: 0 warnings, 0 errors
openai-responses-transport-replay-recovery.test.ts: 2 test files, 2 tests passed
thinking.test.ts: 33 passed
pi-embedded-helpers.formatassistanterrortext.test.ts: 64 passed
tsgo core: passed
git diff --check: passed
rebase refresh: proof harness PASS, oxlint 0 warnings/0 errors, transport recovery tests 2 passed, thinking tests 33 passed, format assistant error text tests 64 passed, tsgo core passed, git diff --check passed

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: M triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 19, 2026
@clawsweeper

clawsweeper Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge.

Workflow note: Future ClawSweeper reviews update this same comment in place.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

Summary
The PR adds invalid OpenAI Responses encrypted-reasoning replay classification, a one-shot retry wrapper that drops replayable reasoning before visible output starts, focused regression tests, and a loopback HTTP proof script.

Reproducibility: yes. at source level: current main preserves same-model replayable Responses reasoning and turns a pre-start provider rejection into an assistant error event with no retry. I did not run live OpenAI or Slack in this read-only review.

PR rating
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Summary: Good normal PR readiness: the implementation is focused and the terminal proof is useful, with remaining live-provider and channel-delivery uncertainty for maintainers to own.

Rank-up moves:

  • none
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Real behavior proof
Sufficient (terminal): The PR body includes terminal output from a committed proof script using the real OpenAI SDK HTTP transport against loopback /v1/responses and showing the failed request, retry payload, and recovered assistant text.

Risk before merge

  • The retry deliberately drops replayable OpenAI Responses reasoning and keeps dropping it for later calls in the same wrapper after recovery, so an overly broad error match could reduce hidden session continuity for that active wrapper.
  • The supplied proof exercises the real OpenAI SDK HTTP transport against a loopback endpoint, not live OpenAI or live Slack, so provider-specific encrypted-state behavior and channel-visible delivery remain maintainer-owned merge risk.

Maintainer options:

  1. Accept Transport-Level Proof (recommended)
    Merge after ordinary maintainer review if the committed real-SDK loopback proof and regression tests are sufficient for this Responses replay path.
  2. Ask For Live Continuation Proof
    Request redacted live OpenAI or channel logs showing one retry without duplicate or missing output if provider-backed evidence is required before merge.
  3. Keep Slack Routing Separate
    Keep this PR scoped to Responses replay recovery and continue tracking Slack main/thread session routing in the linked issue.

Next step before merge
No narrow automated repair is indicated; maintainers need to decide whether the loopback real-SDK proof is enough for the session-state and message-delivery risk.

Security
Cleared: The diff touches agent runtime recovery, focused tests, and a local proof script; I found no new dependency, workflow, permission, secret, install, or supply-chain exposure.

Review details

Best possible solution:

Land the focused Responses replay recovery after maintainers accept the transport-level proof or request live provider/channel evidence, while keeping Slack main/thread routing tracked separately in #84002.

Do we have a high-confidence way to reproduce the issue?

Yes at source level: current main preserves same-model replayable Responses reasoning and turns a pre-start provider rejection into an assistant error event with no retry. I did not run live OpenAI or Slack in this read-only review.

Is this the best way to solve the issue?

Yes: the PR uses a one-shot Responses stream wrapper, retries only before visible chunks, reuses the existing reasoning/tool-call downgrade helpers, and stays scoped to invalid replay state. Live provider or channel proof would reduce merge risk, but I did not find a better implementation path.

Label changes:

  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes terminal output from a committed proof script using the real OpenAI SDK HTTP transport against loopback /v1/responses and showing the failed request, retry payload, and recovered assistant text.

Label justifications:

  • P2: This is a normal-priority agent/session continuation bug fix with limited blast radius but real user-visible stalled-turn impact.
  • merge-risk: 🚨 session-state: The PR changes how preserved OpenAI Responses reasoning state is dropped and remembered inside the active stream wrapper after an invalid replay rejection.
  • merge-risk: 🚨 message-delivery: The PR changes pre-start retry behavior for channel-visible assistant turns, where a bad retry boundary could duplicate, suppress, or fail to deliver output.
  • rating: 🐚 platinum hermit: Current PR rating is 🐚 platinum hermit because proof is 🦞 diamond lobster, patch quality is 🐚 platinum hermit, and Good normal PR readiness: the implementation is focused and the terminal proof is useful, with remaining live-provider and channel-delivery uncertainty for maintainers to own.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes terminal output from a committed proof script using the real OpenAI SDK HTTP transport against loopback /v1/responses and showing the failed request, retry payload, and recovered assistant text.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes terminal output from a committed proof script using the real OpenAI SDK HTTP transport against loopback /v1/responses and showing the failed request, retry payload, and recovered assistant text.

Acceptance criteria:

  • node --import tsx scripts/proofs/openai-responses-replay-recovery.ts
  • ./node_modules/.bin/oxlint --tsconfig config/tsconfig/oxlint.scripts.json scripts/proofs/openai-responses-replay-recovery.ts
  • node scripts/run-vitest.mjs src/agents/pi-embedded-runner/openai-responses-transport-replay-recovery.test.ts
  • node scripts/run-vitest.mjs src/agents/pi-embedded-runner/thinking.test.ts
  • node scripts/run-vitest.mjs src/agents/pi-embedded-helpers.formatassistanterrortext.test.ts

What I checked:

  • Current main keeps same-model replayable reasoning: Current main only drops replayable OpenAI Responses reasoning when the model changed during replay-history sanitization; same-model stale encrypted reasoning can still be preserved into request assembly. (src/agents/pi-embedded-runner/replay-history.ts:751, 94ac563399b3)
  • Current main lacks targeted replay-invalid classification: Current main's replay-invalid classifier covers previous_response_id, tool-call pairing, role alternation, and connection item-id errors, but not thinking_signature_invalid or encrypted reasoning verification/decryption failures. (src/agents/pi-embedded-helpers/errors.ts:446, 94ac563399b3)
  • Current Responses transport emits pre-start error events: The Responses transport creates the provider stream before pushing the start event; if provider request creation fails, the catch block emits an error event with the provider error message and ends the stream. (src/agents/openai-transport-stream.ts:1752, 94ac563399b3)
  • PR wires recovery only for Responses-family APIs: The patch wraps the OpenAI/Azure/Codex Responses stream function after the existing orphan-reasoning and function-call pairing sanitizers, leaving non-Responses tool-call sanitization unchanged. (src/agents/pi-embedded-runner/run/attempt.ts:2820, 09f8de688fbf)
  • PR retry guard avoids duplicate visible output: The new wrapper retries only when the invalid reasoning rejection occurs before any chunk is forwarded, then drops replayable reasoning and downgrades paired OpenAI function-call ids for the retry and later calls in that wrapper. (src/agents/pi-embedded-runner/thinking.ts:550, 09f8de688fbf)
  • Regression coverage exercises request, event, result, id-downgrade, and post-chunk cases: The added thinking tests cover pre-stream rejection, pre-start transport error events, promise-wrapped streams, OpenAI function-call id downgrade after reasoning removal, persistent drop mode, and no retry after a forwarded chunk. (src/agents/pi-embedded-runner/thinking.test.ts:639, 09f8de688fbf)

Likely related people:

  • @vincentkoc: History shows prior work on the LLM transport adapter seam, OpenAI replay id preservation, and adjacent reasoning/transport fixes that this PR builds on. (role: recent agent/provider transport contributor; confidence: high; commits: 4798e125f40c, a09e228e3e8e, 707f5485b967; files: src/agents/openai-transport-stream.ts, src/agents/pi-embedded-runner/run/attempt.ts, src/agents/pi-embedded-runner/thinking.ts)
  • @steipete: History shows repeated OpenAI transport, reasoning effort, replay-state, and helper refactors in the affected area. (role: recent OpenAI transport and replay refactor contributor; confidence: high; commits: 3ead2d109060, f27d382873c1, 761b71e268a7; files: src/agents/openai-transport-stream.ts, src/agents/pi-embedded-runner/run/attempt.ts, src/agents/pi-embedded-helpers/errors.ts)
  • @jalehman: The replay-history ownership refactor moved provider replay runtime behavior into the code path that currently decides when OpenAI reasoning is dropped. (role: provider replay runtime refactor contributor; confidence: medium; commits: 799c6f40aa69; files: src/agents/pi-embedded-runner/replay-history.ts, src/plugins/provider-runtime.ts)
  • @roshanasingh4: The OpenAI Responses model-switch transcript repair introduced the helper surface that the PR reuses to drop replayable reasoning and downgrade paired function-call ids. (role: original OpenAI Responses transcript repair contributor; confidence: medium; commits: 202d7af85594; files: src/agents/pi-embedded-helpers/openai.ts)

Codex review notes: model gpt-5.5, reasoning high; reviewed against 94ac563399b3.

@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 19, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels May 19, 2026
@tianxiaochannel-oss88

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Added committed transport-level proof in src/agents/pi-embedded-runner/openai-responses-transport-replay-recovery.test.ts and updated the PR body with the command/results. The new test exercises createOpenAIResponsesTransportStreamFn() directly with a mocked OpenAI SDK, verifies the first Responses call rejects with thinking_signature_invalid, then verifies the retry drops replayed reasoning while preserving replayed message and recovers assistant text.

@clawsweeper

clawsweeper Bot commented May 19, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@openclaw-barnacle openclaw-barnacle Bot added the scripts Repository scripts label May 20, 2026
@tianxiaochannel-oss88

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Added committed real-HTTP transport proof in scripts/proofs/openai-responses-replay-recovery.ts and updated the PR body with the terminal output. This proof uses the real OpenAI SDK HTTP transport plus the current OpenClaw Responses transport/recovery wrapper against a loopback /v1/responses endpoint: first request receives provider-shaped thinking_signature_invalid, retry drops replayed reasoning, preserves replayed message, consumes SSE, and returns assistant text.

@clawsweeper

clawsweeper Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels May 20, 2026
@clawsweeper

clawsweeper Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper PR egg

✨ Hatched: 🌱 uncommon Brave Shellbean

Hatch command

Comment @clawsweeper hatch when this PR is hatchable.

Hatchability rules:

  • Merged PRs are hatchable.
  • Open PRs are hatchable when they are status: 👀 ready for maintainer look, status: 🚀 automerge armed, or labeled clawsweeper:automerge.
  • Closed unmerged PRs are hatchable only when one of those hatchable labels is still present in the durable record.

Rarity: 🌱 uncommon.
Trait: guards the happy path.
Image traits: location review cove; accessory lint brush; palette rose quartz and slate; mood determined; pose sitting proudly on a smooth stone; shell soft speckled shell; lighting gentle morning glow; background miniature CI buoys.
Share on X: post this hatch
Copy: My PR egg hatched a 🌱 uncommon Brave Shellbean in ClawSweeper.

What is this egg doing here?
  • Eggs appear after the PR passes real-behavior proof. It is here for vibes, not verdicts: it does not change labels, ratings, merge decisions, or automation.
  • The shell reacts to review momentum: open follow-up work warms it up, re-review makes it wobble, and a clean final review lets it hatch.
  • Hatchability usually comes from sufficient real-behavior proof, no blocking P0/P1/P2 findings, no security attention needed, and clean correctness. A merged PR is already final, so merge makes the egg hatchable independently.
  • The hatch is seeded from this repository and PR number, so the same PR keeps the same creature; the reviewed head SHA can only change safe visual details.
  • Rarity is just collectible sparkle: 🥚 common, 🌱 uncommon, 💎 rare, ✨ glimmer, and 🌈 legendary.

@tianxiaochannel-oss88
tianxiaochannel-oss88 marked this pull request as ready for review May 20, 2026 01:10
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 20, 2026
@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 20, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 20, 2026
@tianxiaochannel-oss88
tianxiaochannel-oss88 force-pushed the fix/responses-thinking-signature-clean-retry branch from 8481adf to 09f8de6 Compare May 20, 2026 11:06
@tianxiaochannel-oss88

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Rebased onto current origin/main (3c8050c44ca5e5eeb9ecc5bdce2fb412312e2b7e) and refreshed the PR body proof for current head 09f8de688fbfc88e49ac7dd3c27101a0b8a16142.

The previous CI failure was from upstream src/cli/update-cli/update-command.ts / src/infra/update-runner.ts type errors outside this PR diff. After rebasing, local validation passed:

node --import tsx scripts/proofs/openai-responses-replay-recovery.ts
# PASS

./node_modules/.bin/oxlint --tsconfig config/tsconfig/oxlint.scripts.json scripts/proofs/openai-responses-replay-recovery.ts
# 0 warnings, 0 errors

node scripts/run-vitest.mjs src/agents/pi-embedded-runner/openai-responses-transport-replay-recovery.test.ts
# 2 passed

node scripts/run-vitest.mjs src/agents/pi-embedded-runner/thinking.test.ts
# 33 passed

node scripts/run-vitest.mjs src/agents/pi-embedded-helpers.formatassistanterrortext.test.ts
# 64 passed

node scripts/run-tsgo.mjs -p tsconfig.core.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core.tsbuildinfo
# passed

git diff --check
# passed

@clawsweeper

clawsweeper Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@clawsweeper clawsweeper Bot added the proof: sufficient ClawSweeper judged the real behavior proof convincing. label May 20, 2026
@latensified

Copy link
Copy Markdown
Contributor

Cross-linking the Responses item-id coordination note from #85277:
#85277 (comment)

For this PR, the proposed final layering is that the retry still preserves visible assistant message content/phase, but after dropped/pruned reasoning it should not preserve a signed assistant message.id whose paired reasoning item is no longer replayed. With #85277 layered in, the retry payload should replay the visible message while omitting that stale signed id.

Suggested merge order from the coordination pass: #84904 -> #85277 -> #84267 -> #85362. When rebasing with #85362, the clean combined shape should keep one exported isOpenAIResponsesReasoningReplayInvalidErrorMessage helper and include invalid_encrypted_content in that helper so transport retry and session-reset classification share the same OpenAI Responses encrypted-content error contract.

@tianxiaochannel-oss88

Copy link
Copy Markdown
Contributor Author

Update from a fresh local validation on v2026.5.27:

The latest release appears to improve the operational failure mode: after this class of Responses failure, the Slack lane no longer remains stuck in processing. In my local repro, Gateway stayed healthy, Slack stayed connected/healthy, the run returned to idle, queueDepth=0, and there was no stale session lock.

The remaining user-visible gap still reproduces, though: the turn terminates before producing a reply instead of rebuilding context and retrying the same user message.

Sanitized signatures from the repro:

[responses] error ... status=400 code=thinking_signature_invalid
The encrypted content for item rs_… could not be verified. Reason: Encrypted content could not be decrypted or parsed.
Embedded agent failed before reply: LLM request failed: provider rejected the request schema or tool payload.
session.state outcome=idle reason=message_completed queueDepth=0

So v2026.5.27 appears to have moved this from “stuck lane” to “cleanly released failed turn”, but it still does not provide the bounded recovery behavior this PR is aiming at: detect stale Responses continuation state, drop stale replay/encrypted reasoning items for a replay-safe turn, rebuild from the visible transcript, and retry once so the user gets the final answer.

One local trigger that still makes this easy to reproduce is an OpenAI-compatible proxy with session affinity where a pinned auth can become temporarily unavailable and the proxy reselects auth. That can leave OpenClaw replaying encrypted reasoning / rs_* state that no longer verifies under the new upstream auth context. This comment is only about the OpenClaw-side recovery layer; no proxy/account/session identifiers are included.

@steipete

Copy link
Copy Markdown
Contributor

Superseded by #92941, landed as 2a6eeceb40.

The landed fix handles thinking_signature_invalid at the owning OpenAI Responses transport boundary by reusing the existing bounded pre-stream encrypted-content retry. It strips only rejected encrypted_content while preserving replayed reasoning/message/function-call identifiers and ordering, rather than adding a second session-level stream wrapper and persistent recovery mode.

Proof included 367 focused OpenAI/Anthropic regressions, six official provider tool-call tests, an official GPT-5.5 encrypted-reasoning replay, AWS Crabbox check:changed, clean autoreview, and green exact-SHA CI. Thanks @tianxiaochannel-oss88 for isolating the error code and providing the provider-shaped proof that made the narrow fix possible.

@steipete steipete closed this Jun 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. scripts Repository scripts size: L status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants