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); }