diff --git a/src/auto-reply/reply/directive-handling.levels.test.ts b/src/auto-reply/reply/directive-handling.levels.test.ts index 45797d8a0ed..be786cfcdae 100644 --- a/src/auto-reply/reply/directive-handling.levels.test.ts +++ b/src/auto-reply/reply/directive-handling.levels.test.ts @@ -121,4 +121,19 @@ describe("resolveCurrentDirectiveLevels", () => { expect(result.currentReasoningLevel).toBe("off"); }); + + it("respects agent reasoningDefault: off as explicit override", async () => { + const resolveDefaultThinkingLevel = vi.fn().mockResolvedValue("off"); + + const result = await resolveCurrentDirectiveLevels({ + sessionEntry: {}, + agentEntry: { + reasoningDefault: "off", + }, + resolveDefaultThinkingLevel, + }); + + // Agent explicitly setting "off" should be respected, not overridden by model default + expect(result.currentReasoningLevel).toBe("off"); + }); }); diff --git a/src/auto-reply/reply/get-reply-directives.ts b/src/auto-reply/reply/get-reply-directives.ts index 9dad0b76875..44ed8990d05 100644 --- a/src/auto-reply/reply/get-reply-directives.ts +++ b/src/auto-reply/reply/get-reply-directives.ts @@ -434,11 +434,16 @@ export async function resolveReplyDirectives(params: { (agentCfg?.thinkingDefault as ThinkLevel | undefined); // When neither directive nor session nor agent set reasoning, default to model capability - // (e.g. OpenRouter with reasoning: true). + // (e.g. OpenRouter with reasoning: true). Skip model default when thinking is active + // to avoid redundant Reasoning: output alongside internal thinking blocks. + const hasAgentReasoningDefault = + agentEntry?.reasoningDefault !== undefined && agentEntry?.reasoningDefault !== null; const reasoningExplicitlySet = directives.reasoningLevel !== undefined || - (sessionEntry?.reasoningLevel !== undefined && sessionEntry?.reasoningLevel !== null); - if (!reasoningExplicitlySet && resolvedReasoningLevel === "off") { + (sessionEntry?.reasoningLevel !== undefined && sessionEntry?.reasoningLevel !== null) || + hasAgentReasoningDefault; + const thinkingActive = resolvedThinkLevelWithDefault !== "off"; + if (!reasoningExplicitlySet && resolvedReasoningLevel === "off" && !thinkingActive) { resolvedReasoningLevel = await modelState.resolveDefaultReasoningLevel(); }