Summary
Multi-turn requests against GitHub Copilot–hosted Responses models (e.g. github-copilot/gpt-5.5, gpt-5.4, gpt-5-mini) fail on the second turn with HTTP 400 from the upstream:
The encrypted content for item rs_<…> could not be verified.
Reason: Encrypted content item_id did not match the target item id.
OpenClaw then marks the github-copilot provider as in cooldown and falls back through agents.defaults.model.fallbacks, so to the user it looks like "I picked gpt-5.5 but a different model is replying."
Repro
- Configure GitHub Copilot via device flow (must have GPT-5.x access on the account).
- Add
github-copilot/gpt-5.5 to agents.defaults.models and select it.
- Send any message that triggers reasoning (default
effort: medium is fine).
- Send a follow-up turn in the same session.
Expected: continues normally.
Actual: turn 2 returns HTTP 400, provider enters cooldown, fallback model answers.
Gateway log excerpt:
provider=github-copilot model=gpt-5.5 status=400
{"error":{"message":"The encrypted content for item rs_… could not be verified. Reason: Encrypted content item_id did not match the target item id.","type":"invalid_request_error","code":"invalid_request_error"}}
auth profile github-copilot in cooldown
Root cause
OpenClaw replays prior reasoning items by extracting their id and encrypted_content and re-sending them in the next request. Two helpers gate the id behind a startsWith("rs_") check that assumes OpenAI's direct API id format:
src/agents/openai-ws-message-conversion.ts, toReplayableReasoningId()
src/agents/pi-embedded-helpers/openai.ts, parseReasoningSignature()
Copilot's hosted Responses proxy returns opaque, base64-shaped ids that do not carry the rs_ prefix (for example cAkF5s7bPI/vmV4ynEfGnazJ076eYI+abcdef==). The id is therefore dropped before the item is re-sent. The upstream then fails to match the encrypted_content to a known item_id and rejects the continuation.
I confirmed this by directly hitting https://api.enterprise.githubcopilot.com/v1/responses with a Copilot device-flow token:
- A clean turn-1 call with
include: ["reasoning.encrypted_content"] returns the reasoning item with an opaque (non-rs_) id and encrypted_content.
- Turn-2 succeeds when I re-send the exact item with both
id and encrypted_content.
- Turn-2 fails (same 400 as above) when the id is removed.
- The endpoint also rejects
store: true (unsupported_value), so server-side continuation via previous_response_id is not an alternative for Copilot — client-side encrypted replay is the only path.
Fix
Accept any non-empty reasoning id; only drop empty/whitespace ids. PR coming next.
Environment
- OpenClaw
2026.4.23 (also reproduces on current main)
- Provider:
github-copilot (device flow), enterprise base URL
- Models:
gpt-5.5, gpt-5.4, gpt-5-mini (any reasoning-enabled Copilot model)
Summary
Multi-turn requests against GitHub Copilot–hosted Responses models (e.g.
github-copilot/gpt-5.5,gpt-5.4,gpt-5-mini) fail on the second turn with HTTP 400 from the upstream:OpenClaw then marks the
github-copilotprovider as in cooldown and falls back throughagents.defaults.model.fallbacks, so to the user it looks like "I picked gpt-5.5 but a different model is replying."Repro
github-copilot/gpt-5.5toagents.defaults.modelsand select it.effort: mediumis fine).Expected: continues normally.
Actual: turn 2 returns HTTP 400, provider enters cooldown, fallback model answers.
Gateway log excerpt:
Root cause
OpenClaw replays prior reasoning items by extracting their id and
encrypted_contentand re-sending them in the next request. Two helpers gate the id behind astartsWith("rs_")check that assumes OpenAI's direct API id format:src/agents/openai-ws-message-conversion.ts,toReplayableReasoningId()src/agents/pi-embedded-helpers/openai.ts,parseReasoningSignature()Copilot's hosted Responses proxy returns opaque, base64-shaped ids that do not carry the
rs_prefix (for examplecAkF5s7bPI/vmV4ynEfGnazJ076eYI+abcdef==). The id is therefore dropped before the item is re-sent. The upstream then fails to match theencrypted_contentto a knownitem_idand rejects the continuation.I confirmed this by directly hitting
https://api.enterprise.githubcopilot.com/v1/responseswith a Copilot device-flow token:include: ["reasoning.encrypted_content"]returns the reasoning item with an opaque (non-rs_) id andencrypted_content.idandencrypted_content.store: true(unsupported_value), so server-side continuation viaprevious_response_idis not an alternative for Copilot — client-side encrypted replay is the only path.Fix
Accept any non-empty reasoning id; only drop empty/whitespace ids. PR coming next.
Environment
2026.4.23(also reproduces on currentmain)github-copilot(device flow), enterprise base URLgpt-5.5,gpt-5.4,gpt-5-mini(any reasoning-enabled Copilot model)