Skip to content

fix(claude-code): pass configured model to the spawned CLI (#2881) - #7

Closed
chethanuk wants to merge 2 commits into
mainfrom
fix/issue-2881-claudecode-provider-never-passes-the-configured
Closed

fix(claude-code): pass configured model to the spawned CLI (#2881)#7
chethanuk wants to merge 2 commits into
mainfrom
fix/issue-2881-claudecode-provider-never-passes-the-configured

Conversation

@chethanuk

Copy link
Copy Markdown
Owner

Fixes the behaviour reported in vectorize-io#2881.

Problem

With HINDSIGHT_API_*_LLM_PROVIDER=claude-code, the model resolved from config — global (HINDSIGHT_API_LLM_MODEL), per-scope (..._RETAIN_/_REFLECT_/_CONSOLIDATION_LLM_MODEL), or the provider default — was accepted, stored on the provider as self.model, and reported in metrics/traces, but the spawned claude CLI ignored it and ran its own default model. Cost/latency attribution was wrong and per-scope model tuning silently did nothing.

Root cause

ClaudeCodeLLM.call() and ClaudeCodeLLM.call_with_tools() in hindsight-api-slim/hindsight_api/engine/providers/claude_code_llm.py built ClaudeAgentOptions(...) without model=. ClaudeAgentOptions.model is the only field the Claude Agent SDK transport turns into the CLI's --model flag, so the configured model never reached the subprocess.

Fix

  • Pass model=self.model at both ClaudeAgentOptions sites (unconditional — the SDK transport already skips a falsy model).
  • Move the claude-code provider default from the dated claude-sonnet-4-5-20250929 to the undated alias claude-sonnet-4-5 (an id the Claude Agent SDK documents as a model example and the "full name" form the CLI accepts). The dated id was previously inert; now that it becomes a real --model argument, the undated form avoids breaking provider-only setups such as the shipped docker-compose claude-code profile. Aligned across config.py, hindsight-docs/src/data/llmProviders.json, and the configuration docs; skills/ references regenerated.
  • Added the model field to the _FakeOptions stand-ins in the two existing claude-code test modules so they keep constructing options once model= is passed.

Test evidence

New parametrized regression test tests/test_claude_code_llm_model.py mocks the SDK and asserts the configured model lands on ClaudeAgentOptions for both call and call_with_tools (rows: claude-haiku-4-5, sonnet, claude-sonnet-4-5). It fails 6/6 before the fix (AssertionError: assert None == '<model>') and passes after.

uv run pytest tests/test_claude_code_llm_model.py tests/test_claude_code_llm_isolation.py \
  tests/test_claude_code_llm_error_result.py tests/test_provider_default_models.py \
  tests/test_llm_wrapper.py -p xdist -n0
======================== 64 passed, 2 warnings in 6.26s ========================
  • ruff check . — All checks passed
  • ruff format --check (touched files) — already formatted
  • ty check (provider + config) — All checks passed
  • ./scripts/generate-docs-skill.sh — regenerated skills/ in sync (no diff)

Note: ./scripts/hooks/lint.sh ESLint step could not run in the QA environment (@eslint/js not installed — control-plane node_modules absent). This branch changes zero JS/TS files, so ESLint has nothing of this change to check.

Refs vectorize-io#2881

…ectorize-io#2881)

Red test: both call() and call_with_tools() must place self.model on the
ClaudeAgentOptions handed to the Claude Agent SDK, since that field is what the
SDK transport turns into the CLI --model flag. Currently the model is dropped,
so the spawned claude CLI runs its own default while metrics report self.model.
…-io#2881)

ClaudeCodeLLM.call() and call_with_tools() built ClaudeAgentOptions without
model=, so the model resolved by config (global, per-scope, or the provider
default) was stored on self.model and reported in metrics/traces but never
reached the spawned `claude` CLI — it silently ran its own default model.
ClaudeAgentOptions.model is the only field the SDK transport turns into the
CLI's --model flag; add model=self.model at both option sites (unconditional,
the transport already skips a falsy model).

Move the claude-code provider default from the dated claude-sonnet-4-5-20250929
to the undated alias claude-sonnet-4-5 (one of the ids the Claude Agent SDK
documents as a model example, and the "full name" form the CLI accepts). The
dated id was previously inert; now that it becomes a real --model argument, an
undated form avoids breaking provider-only setups such as the shipped
docker-compose claude-code profile. Aligned across config.py,
llmProviders.json, and the configuration docs; skills/ references regenerated.

Add the model field to the _FakeOptions stand-ins in the two existing
claude-code test modules so they keep constructing options once model= is
passed.
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@codeant-ai

codeant-ai Bot commented Jul 26, 2026

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Reviewed your PR b0158a9 Jul 26, 2026 · 03:42 03:45

@codeant-ai

codeant-ai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d880e5f5-6ad8-4cb5-a4c2-e63efe317eb6

📥 Commits

Reviewing files that changed from the base of the PR and between dd6766c and b0158a9.

📒 Files selected for processing (9)
  • hindsight-api-slim/hindsight_api/config.py
  • hindsight-api-slim/hindsight_api/engine/providers/claude_code_llm.py
  • hindsight-api-slim/tests/test_claude_code_llm_error_result.py
  • hindsight-api-slim/tests/test_claude_code_llm_isolation.py
  • hindsight-api-slim/tests/test_claude_code_llm_model.py
  • hindsight-docs/docs/developer/configuration.md
  • hindsight-docs/src/data/llmProviders.json
  • skills/hindsight-docs/references/developer/configuration.md
  • skills/hindsight-docs/references/developer/models.md

📝 Walkthrough

Walkthrough

The Claude Code provider now passes its configured model explicitly to the Claude Agent SDK for regular and tool-enabled calls. Default model references and documentation use claude-sonnet-4-5, with regression coverage for model propagation.

Changes

Claude Code model selection

Layer / File(s) Summary
Update Claude Code model defaults
hindsight-api-slim/hindsight_api/config.py, hindsight-docs/..., skills/hindsight-docs/...
The Claude Code default model and configuration references now use claude-sonnet-4-5.
Forward configured models to the SDK
hindsight-api-slim/hindsight_api/engine/providers/claude_code_llm.py
Both call() and call_with_tools() pass self.model into ClaudeAgentOptions.
Validate model propagation
hindsight-api-slim/tests/test_claude_code_llm_model.py, hindsight-api-slim/tests/test_claude_code_llm_error_result.py, hindsight-api-slim/tests/test_claude_code_llm_isolation.py
Regression tests verify model forwarding and update SDK option fakes to accept the new field.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested labels: size:L

Suggested reviewers: nicoloboschi, sanderhoff-alt, cdbartholomew

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main fix: forwarding the configured model to the spawned Claude Code CLI.
Description check ✅ Passed The description accurately explains the model-forwarding fix, default-model change, and related tests/docs updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chethanuk chethanuk closed this Jul 31, 2026
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