From 6c7d01232041b91a31d794951c27cda2b5813d69 Mon Sep 17 00:00:00 2001 From: scoootscooob Date: Mon, 2 Mar 2026 10:52:32 -0800 Subject: [PATCH] fix(openrouter): skip reasoning.effort injection for x-ai/grok models x-ai/grok models on OpenRouter do not support the reasoning.effort parameter and reject payloads containing it with "Invalid arguments passed to the model." Skip reasoning injection for these models, the same way we already skip it for the dynamic "auto" routing model. Closes #32039 Co-Authored-By: Claude Opus 4.6 --- .../pi-embedded-runner-extraparams.test.ts | 32 +++++++++++++++++++ src/agents/pi-embedded-runner/extra-params.ts | 17 +++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/agents/pi-embedded-runner-extraparams.test.ts b/src/agents/pi-embedded-runner-extraparams.test.ts index 46e72ed89ec..985d90e0db6 100644 --- a/src/agents/pi-embedded-runner-extraparams.test.ts +++ b/src/agents/pi-embedded-runner-extraparams.test.ts @@ -317,6 +317,38 @@ describe("applyExtraParamsToAgent", () => { expect(payloads[0]).toEqual({ reasoning: { max_tokens: 256 } }); }); + it("does not inject reasoning.effort for x-ai/grok models on OpenRouter (#32039)", () => { + const payloads: Record[] = []; + const baseStreamFn: StreamFn = (_model, _context, options) => { + const payload: Record = {}; + options?.onPayload?.(payload); + payloads.push(payload); + return {} as ReturnType; + }; + const agent = { streamFn: baseStreamFn }; + + applyExtraParamsToAgent( + agent, + undefined, + "openrouter", + "x-ai/grok-4.1-fast", + undefined, + "medium", + ); + + const model = { + api: "openai-completions", + provider: "openrouter", + id: "x-ai/grok-4.1-fast", + } as Model<"openai-completions">; + const context: Context = { messages: [] }; + void agent.streamFn?.(model, context, {}); + + expect(payloads).toHaveLength(1); + expect(payloads[0]).not.toHaveProperty("reasoning"); + expect(payloads[0]).not.toHaveProperty("reasoning_effort"); + }); + it("normalizes thinking=off to null for SiliconFlow Pro models", () => { const payloads: Record[] = []; const baseStreamFn: StreamFn = (_model, _context, options) => { diff --git a/src/agents/pi-embedded-runner/extra-params.ts b/src/agents/pi-embedded-runner/extra-params.ts index 75dc4e85324..4258f758dea 100644 --- a/src/agents/pi-embedded-runner/extra-params.ts +++ b/src/agents/pi-embedded-runner/extra-params.ts @@ -620,6 +620,15 @@ function createOpenRouterWrapper( }; } +/** + * Models on OpenRouter that do not support the `reasoning.effort` parameter. + * Injecting it causes "Invalid arguments passed to the model" errors. + */ +function isOpenRouterReasoningUnsupported(modelId: string): boolean { + const id = modelId.toLowerCase(); + return id.startsWith("x-ai/"); +} + function isGemini31Model(modelId: string): boolean { const normalized = modelId.toLowerCase(); return normalized.includes("gemini-3.1-pro") || normalized.includes("gemini-3.1-flash"); @@ -807,7 +816,13 @@ export function applyExtraParamsToAgent( // which would cause a 400 on models where reasoning is mandatory. // Users who need reasoning control should target a specific model ID. // See: openclaw/openclaw#24851 - const openRouterThinkingLevel = modelId === "auto" ? undefined : thinkingLevel; + // + // x-ai/grok models do not support OpenRouter's reasoning.effort parameter + // and reject payloads containing it with "Invalid arguments passed to the + // model." Skip reasoning injection for these models. + // See: openclaw/openclaw#32039 + const skipReasoningInjection = modelId === "auto" || isOpenRouterReasoningUnsupported(modelId); + const openRouterThinkingLevel = skipReasoningInjection ? undefined : thinkingLevel; agent.streamFn = createOpenRouterWrapper(agent.streamFn, openRouterThinkingLevel); agent.streamFn = createOpenRouterSystemCacheWrapper(agent.streamFn); }