Skip to content

feat(agent): wire optional reasoningEffort through session and strategy - #91

Merged
davideast merged 3 commits into
mainfrom
feat/reasoning-effort-wiring
Jul 25, 2026
Merged

feat(agent): wire optional reasoningEffort through session and strategy#91
davideast merged 3 commits into
mainfrom
feat/reasoning-effort-wiring

Conversation

@davideast

Copy link
Copy Markdown
Owner

Adds optional reasoningEffort to AgentSessionConfig and StrategyRunInput in @inbrowser/agent, allowing callers to configure Gemini thinking levels and stream thought summaries without infinite reasoning loops.

import { createAgentSession, createReactLoopStrategy } from '@inbrowser/agent';
import { createFirebaseAiLogicModelClient } from '@inbrowser/model/providers/firebase';
import { getAI } from 'firebase/ai';

const llm = createFirebaseAiLogicModelClient(getAI(), { id: 'gemini-3.5-flash' });
const session = createAgentSession({
  llm,
  strategy: createReactLoopStrategy(),
  reasoningEffort: 'medium',
  tools: { execute: async () => ({ ok: true }) },
  toolContext: () => ({}),
  systemPromptBuilder: () => 'You are a concise coding assistant.',
  metrics: { recordTurn: () => ({}) as any },
  history: [],
});

for await (const ev of session.submit('Explain ReAct looping', new AbortController().signal)) {
  if (ev.kind === 'thinking') {
    console.log('Thought summary:', ev.chunk);
  } else if (ev.kind === 'text') {
    process.stdout.write(ev.chunk);
  }
}

Risk

  • Provider model compatibility: Passing reasoningEffort to model endpoints that do not support thinking (such as legacy Gemini 1.5 models or non-reasoning OpenRouter endpoints) may result in upstream provider rejection if the underlying adapter does not strip unsupported reasoning configurations.

Session configuration forwards reasoning effort directly into strategy run inputs

When reasoningEffort is present on AgentSessionConfig, session.ts attaches the value to the StrategyRunInput object handed to config.strategy.run().

// In packages/agent/src/session.ts
const runInput: StrategyRunInput = {
  prompt,
  history: priorHistory,
  workspace,
  runtime,
  llm: config.llm,
  tools: tools.dispatch,
  toolList: tools.toolList,
  toolContext: config.toolContext,
  systemPrompt,
  turnId,
};
const hasReasoningEffort = config.reasoningEffort !== undefined && config.reasoningEffort !== null;
if (hasReasoningEffort) {
  runInput.reasoningEffort = config.reasoningEffort;
}

ReAct loop strategy attaches reasoning effort to chat and critique requests

createReactLoopStrategy() checks input.reasoningEffort and attaches it to both the primary chatRequest and any post-turn critiqueRequest sent to input.llm.

// In packages/agent/src/strategy.ts
const chatRequest: ModelRequest = {
  messages,
  tools,
  toolUseEnabled: tools.length > 0 && input.llm.supportsTools,
};
const hasReasoningEffort = input.reasoningEffort !== undefined && input.reasoningEffort !== null;
if (hasReasoningEffort) {
  chatRequest.reasoningEffort = input.reasoningEffort;
}
Implementation notes and verification
  • Refactored strictly without ternary operators (? :), nullish coalescing (??), or unnamed boolean conditions in if statements.
  • Ran core unit test suite across packages/model and packages/agent (bun test packages/model/test packages/agent/test/*.test.ts): 341 passed, 0 failed across 40 files in 4.84s.
  • Did not modify packages/model, preserving the explicit test contract (it('omits thought summaries when reasoningEffort is omitted')).

@davideast
davideast merged commit f0e4c5e into main Jul 25, 2026
1 check passed
@davideast
davideast deleted the feat/reasoning-effort-wiring branch July 25, 2026 05:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant