Skip to content

GitHub Copilot Responses (gpt-5.x): multi-turn fails with 'encrypted content item_id did not match' #71333

Description

@ottodeng

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

  1. Configure GitHub Copilot via device flow (must have GPT-5.x access on the account).
  2. Add github-copilot/gpt-5.5 to agents.defaults.models and select it.
  3. Send any message that triggers reasoning (default effort: medium is fine).
  4. 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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions