From 3a761fbcf83735af9be5f222b33bb1fc6f8a0495 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 7 Mar 2026 22:47:41 +0000 Subject: [PATCH] fix(agents): strip unsupported responses store payloads (#39219, thanks @ademczuk) Co-authored-by: ademczuk --- CHANGELOG.md | 1 + .../pi-embedded-runner-extraparams.test.ts | 25 +++++++++++++++++-- src/agents/pi-embedded-runner/extra-params.ts | 12 ++++++++- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 945b5c4f9eb..6d4581bdadd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -295,6 +295,7 @@ Docs: https://docs.openclaw.ai - Gateway/webchat route safety: block webchat/control-ui clients from inheriting stored external delivery routes on channel-scoped sessions (while preserving route inheritance for UI/TUI clients), preventing cross-channel leakage from scoped chats. (#39175) Thanks @widingmarcus-cyber. - Telegram error-surface resilience: return a user-visible fallback reply when dispatch/debounce processing fails instead of going silent, while preserving draft-stream cleanup and best-effort thread-scoped fallback delivery. (#39209) Thanks @riftzen-bit. - Gateway/password auth startup diagnostics: detect unresolved provider-reference objects in `gateway.auth.password` and fail with a specific bootstrap-secrets error message instead of generic misconfiguration output. (#39230) Thanks @ademczuk. +- Agents/OpenAI-responses compatibility: strip unsupported `store` payload fields when `supportsStore=false` (including OpenAI-compatible non-OpenAI providers) while preserving server-compaction payload behavior. (#39219) Thanks @ademczuk. ## 2026.3.2 diff --git a/src/agents/pi-embedded-runner-extraparams.test.ts b/src/agents/pi-embedded-runner-extraparams.test.ts index 0ebe9ffbafa..a9280aff934 100644 --- a/src/agents/pi-embedded-runner-extraparams.test.ts +++ b/src/agents/pi-embedded-runner-extraparams.test.ts @@ -1387,7 +1387,7 @@ describe("applyExtraParamsToAgent", () => { expect(payload.store).toBe(false); }); - it("does not force store for models that declare supportsStore=false", () => { + it("strips store from payload for models that declare supportsStore=false", () => { const payload = runResponsesPayloadMutationCase({ applyProvider: "azure-openai-responses", applyModelId: "gpt-4o", @@ -1405,7 +1405,28 @@ describe("applyExtraParamsToAgent", () => { compat: { supportsStore: false }, } as unknown as Model<"openai-responses">, }); - expect(payload.store).toBe(false); + expect(payload).not.toHaveProperty("store"); + }); + + it("strips store from payload for non-OpenAI responses providers with supportsStore=false", () => { + const payload = runResponsesPayloadMutationCase({ + applyProvider: "custom-openai-responses", + applyModelId: "gemini-2.5-pro", + model: { + api: "openai-responses", + provider: "custom-openai-responses", + id: "gemini-2.5-pro", + name: "gemini-2.5-pro", + baseUrl: "https://gateway.ai.cloudflare.com/v1/account/gateway/openai", + reasoning: false, + input: ["text"], + cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, + contextWindow: 1_000_000, + maxTokens: 65_536, + compat: { supportsStore: false }, + } as unknown as Model<"openai-responses">, + }); + expect(payload).not.toHaveProperty("store"); }); it("auto-injects OpenAI Responses context_management compaction for direct OpenAI models", () => { diff --git a/src/agents/pi-embedded-runner/extra-params.ts b/src/agents/pi-embedded-runner/extra-params.ts index 78dffcd9cbe..cfd71760cb4 100644 --- a/src/agents/pi-embedded-runner/extra-params.ts +++ b/src/agents/pi-embedded-runner/extra-params.ts @@ -305,7 +305,14 @@ function createOpenAIResponsesContextManagementWrapper( return (model, context, options) => { const forceStore = shouldForceResponsesStore(model); const useServerCompaction = shouldEnableOpenAIResponsesServerCompaction(model, extraParams); - if (!forceStore && !useServerCompaction) { + // Strip `store` from the payload when the model declares supportsStore=false. + // pi-ai upstream hardcodes `store: false` for Responses API; strict + // OpenAI-compatible endpoints (e.g. Gemini via Cloudflare) reject it. + const stripStore = + !forceStore && + OPENAI_RESPONSES_APIS.has(String(model.api ?? "")) && + (model as { compat?: { supportsStore?: boolean } }).compat?.supportsStore === false; + if (!forceStore && !useServerCompaction && !stripStore) { return underlying(model, context, options); } @@ -321,6 +328,9 @@ function createOpenAIResponsesContextManagementWrapper( if (forceStore) { payloadObj.store = true; } + if (stripStore) { + delete payloadObj.store; + } if (useServerCompaction && payloadObj.context_management === undefined) { payloadObj.context_management = [ {