Skip to content

fix(openai): strip status from replayed input items for custom openai-responses endpoints#100831

Merged
steipete merged 2 commits into
openclaw:mainfrom
chenxiaoyu209:fix/openai-responses-custom-input-status-strip
Jul 6, 2026
Merged

fix(openai): strip status from replayed input items for custom openai-responses endpoints#100831
steipete merged 2 commits into
openclaw:mainfrom
chenxiaoyu209:fix/openai-responses-custom-input-status-strip

Conversation

@chenxiaoyu209

Copy link
Copy Markdown
Contributor

What Problem This Solves

Fixes #100657 — when using a custom provider configured with api: "openai-responses", OpenClaw replays prior Responses items into the next request's input[] with a status field (e.g. "completed"). Strict OpenAI-compatible endpoints reject this output-only field with HTTP 400, causing OpenClaw to misclassify the primary model as having a format error and triggering unnecessary fallback.

Why This Change Was Made

The status field on replayed message items (input[n].status) is an output-only field that OpenAI's native API silently accepts but strict third-party compatible endpoints reject. This change strips status from all input[] items specifically for non-native (custom/compatible) openai-responses providers, matching the existing pattern used for shouldStripDisabledReasoningPayload.

User Impact

Custom openai-responses providers no longer see 400 Unknown parameter: 'input[n].status' errors when OpenClaw replays conversation history. The primary model is correctly used instead of being unnecessarily fallen back.

Evidence

  • pnpm test src/agents/openai-responses-payload-policy.test.ts: 12 passed, 0 failed

Changes:

🤖 Generated with Claude Code

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling size: S labels Jul 6, 2026
@clawsweeper

clawsweeper Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 6, 2026, 7:23 AM ET / 11:23 UTC.

Summary
The PR adds a non-native OpenAI Responses payload policy that strips status from replayed input[] items, plus focused policy tests for custom versus native OpenAI routes.

PR surface: Source +33, Tests +70. Total +103 across 2 files.

Reproducibility: yes. at source level, not live: current main constructs replayed Responses input items with status, and the linked issue has strict-endpoint 400 logs plus a local sanitizer success. I did not rerun the private endpoint in this read-only review.

Review metrics: none identified.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #100657
Summary: This PR is the direct candidate fix for the linked strict custom Responses endpoint input[].status issue; the older null-content strict-provider report is adjacent but distinct.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🐚 platinum hermit
Result: blocked until real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add redacted real behavior proof from the custom endpoint or a representative strict Responses-compatible endpoint showing the after-fix request succeeds.
  • Keep the focused policy test evidence in the PR body, but do not rely on unit tests as the only proof for the reported runtime failure.

Proof guidance:

  • [P1] Needs real behavior proof before merge: Missing: the PR body reports only a unit test, so the contributor should add redacted terminal/log proof or a runtime transcript showing the strict endpoint succeeds after the fix; updating the PR body should trigger re-review, or a maintainer can ask @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] The PR body lists only unit-test output, not a redacted after-fix run against the strict custom endpoint or a representative real setup.
  • [P1] Native OpenAI is more permissive than the strict compatible endpoint, so the sanitizer should stay scoped to non-native Responses routes as the PR does.

Maintainer options:

  1. Decide the mitigation before merge
    Merge a scoped non-native Responses sanitizer after contributor real behavior proof or an explicit maintainer proof override, keeping native OpenAI/Azure replay behavior unchanged.
  2. Pause or close
    Do not merge this PR until maintainers decide whether the risk is worth taking.

Next step before merge

  • [P1] The remaining blocker is contributor real behavior proof or maintainer override, not a narrow automated code repair.

Security
Cleared: The diff only changes provider payload sanitation logic and tests; it does not touch dependencies, workflows, secrets, package resolution, or code execution surfaces.

Review details

Best possible solution:

Merge a scoped non-native Responses sanitizer after contributor real behavior proof or an explicit maintainer proof override, keeping native OpenAI/Azure replay behavior unchanged.

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

Yes at source level, not live: current main constructs replayed Responses input items with status, and the linked issue has strict-endpoint 400 logs plus a local sanitizer success. I did not rerun the private endpoint in this read-only review.

Is this the best way to solve the issue?

Yes, the existing Responses payload policy boundary is the narrowest maintainable fix location. The remaining gap is proof quality, not a different code direction.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 2a741bebb54f.

Label changes

Label changes:

  • add P2: This is a scoped provider payload compatibility fix for custom OpenAI Responses routes with reported 400 failures and fallback.
  • add rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🐚 platinum hermit.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: Missing: the PR body reports only a unit test, so the contributor should add redacted terminal/log proof or a runtime transcript showing the strict endpoint succeeds after the fix; updating the PR body should trigger re-review, or a maintainer can ask @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Label justifications:

  • P2: This is a scoped provider payload compatibility fix for custom OpenAI Responses routes with reported 400 failures and fallback.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🐚 platinum hermit.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: Missing: the PR body reports only a unit test, so the contributor should add redacted terminal/log proof or a runtime transcript showing the strict endpoint succeeds after the fix; updating the PR body should trigger re-review, or a maintainer can ask @clawsweeper re-review. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +33, Tests +70. Total +103 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 33 0 +33
Tests 1 70 0 +70
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 103 0 +103

What I checked:

  • PR diff: The branch adds shouldStripInputStatus, a recursive input sanitizer, and two tests that strip status for a custom openai-responses route while preserving it for native OpenAI. (src/agents/openai-responses-payload-policy.ts:326, d53472ab025b)
  • Current main behavior: Current main constructs replayed assistant Responses message items with status: "completed", matching the linked issue's rejected field. (src/agents/openai-transport-stream.ts:1260, 2a741bebb54f)
  • Runtime boundary: The managed Responses path already applies applyOpenAIResponsesPayloadPolicy immediately before returning request params, so the PR places the sanitizer at the existing payload mutation boundary. (src/agents/openai-transport-stream.ts:2438, 2a741bebb54f)
  • Wrapper sibling path: The plugin/provider stream wrapper applies the same payload policy through onPayload, so the chosen helper can cover the shared wrapper surface as well as the managed transport. (src/llm/providers/stream-wrappers/openai.ts:468, 2a741bebb54f)
  • Linked issue evidence: The linked issue reports strict endpoint 400 Unknown parameter: 'input[48].status' logs and a local sanitizer success with a later 200 response, while withholding private payloads appropriately.
  • Upstream API context: The OpenAI SDK documents and examples now include manual Responses state replay via toResponseInputItems, so this PR is best understood as compatibility sanitation for stricter custom endpoints rather than a universal native OpenAI schema correction. (github.com)

Likely related people:

  • vincentkoc: PR metadata and git history show vincentkoc authored and merged the provider transport adapter seam that introduced the replayed assistant item shape, plus nearby provider detection work. (role: introduced behavior and recent area contributor; confidence: high; commits: 4798e125f40c, 66825c09699a, bd4f7458338b; files: src/agents/openai-transport-stream.ts, packages/ai/src/providers/openai-responses-shared.ts, src/agents/openai-responses-payload-policy.ts)
  • obviyus: obviyus authored the later Responses API capability detection unification that touches the same policy/classification boundary used by this PR. (role: recent adjacent owner; confidence: medium; commits: 685f9903ec38; files: src/agents/openai-responses-payload-policy.ts, src/agents/provider-attribution.ts)
  • steipete: Recent OpenAI strict-mode hardening work by Peter Steinberger touched the same OpenAI transport compatibility area implicated by strict endpoint payload handling. (role: recent adjacent owner; confidence: medium; commits: 8cd9007ec196; files: src/agents/openai-transport-stream.ts, src/llm/providers/stream-wrappers/openai.ts)
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.

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.

@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. labels Jul 6, 2026
@steipete steipete self-assigned this Jul 6, 2026
@steipete
steipete force-pushed the fix/openai-responses-custom-input-status-strip branch from d53472a to 536355f Compare July 6, 2026 15:51
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Maintainer repair is land-ready at 536355f9fc967da3f86fdbcb58e567d3268e3c74.

  • Before: replayed top-level Responses input items could retain status metadata rejected by strict compatible endpoints.
  • After: only top-level input[] item status is removed for non-native compatible routes; nested values and native OpenAI/Azure payloads remain unchanged.
  • Repair: replaced the recursive sanitizer with endpoint-scoped one-level normalization and added builder/request regressions.
  • Local lightweight checks: git diff --check; targeted formatting was verified with oxfmt.
  • Exact-head proof: full hosted CI is green: https://github.com/openclaw/openclaw/actions/runs/28804525532
  • Fresh autoreview: no accepted/actionable findings.

Known gap: the reporter's private strict endpoint was unavailable; the managed transport regression exercises the exact outbound JSON boundary.

@steipete
steipete merged commit f28e0d6 into openclaw:main Jul 6, 2026
96 checks passed
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 7, 2026
…-responses endpoints (openclaw#100831)

* fix(openai): strip status from replayed input items for custom openai-responses endpoints

* fix(openai): narrow replay status stripping

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
@chenxiaoyu209
chenxiaoyu209 deleted the fix/openai-responses-custom-input-status-strip branch July 8, 2026 07:56
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
…-responses endpoints (openclaw#100831)

* fix(openai): strip status from replayed input items for custom openai-responses endpoints

* fix(openai): narrow replay status stripping

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: S status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

openai-responses custom provider sends input[].status, rejected by strict compatible endpoints

2 participants