Skip to content

fix(desktop): apply the configured model to Claude Code agents via ANTHROPIC_MODEL - #2695

Closed
bosoud wants to merge 1 commit into
block:mainfrom
bosoud:fix/claude-harness-model-env
Closed

fix(desktop): apply the configured model to Claude Code agents via ANTHROPIC_MODEL#2695
bosoud wants to merge 1 commit into
block:mainfrom
bosoud:fix/claude-harness-model-env

Conversation

@bosoud

@bosoud bosoud commented Jul 24, 2026

Copy link
Copy Markdown

Fixes #2692

Problem

Picking a model for a Claude Code agent in the desktop UI persists the selection but never applies it. The claude entry in KNOWN_ACP_RUNTIMES declares model_env_var: None and supports_acp_model_switching: false, so runtime_metadata_env_vars has no channel to carry the saved model into the spawned session — the agent silently runs on the user's global Claude Code default. Goose (GOOSE_MODEL) and Buzz Agent (BUZZ_AGENT_MODEL) both have this channel; claude was the only harness with a model picker but no application path behind it.

Observed in the wild: a stock agent set to Sonnet answering as claude-fable-5, across restarts, with no error anywhere.

Changes

  • discovery.rs: the claude runtime declares model_env_var: Some(ANTHROPIC_MODEL_ENV_KEY). The Claude CLI honors ANTHROPIC_MODEL as a session model override (verified: ANTHROPIC_MODEL=claude-sonnet-5 claude --print "<model id?>"claude-sonnet-5), and the ACP adapter's child claude process inherits the spawn env. provider_locked stays true, so only the model is injected — no provider env is written for this harness.
  • env_vars.rs: new ANTHROPIC_MODEL_ENV_KEY const as the single source of truth for the key — referenced by the runtime entry, the DERIVED_PROVIDER_MODEL_ENV_KEYS list (so a stale persisted copy can't shadow the structured model field after a UI edit, same treatment as the other derived keys), and the readiness provider-model mapping in readiness.rs, which already used the literal "ANTHROPIC_MODEL" for the anthropic provider. Three call sites, one definition, no drift.
  • Tests: pin the claude runtime shape (model env declared, provider locked), the derived-key classification (including case-insensitivity), and the claude-shaped runtime_metadata_env_vars injection. The tests intentionally assert the literal string so the const's value itself is pinned.

Notes for reviewers

  • Users who worked around this by setting ANTHROPIC_MODEL manually in the agent's env vars: on the next provider/model edit the derived-key rule strips the manual copy, and the structured field takes over — which is the intended convergence.
  • Local cargo test for desktop/src-tauri could not be run on my machine (Intel mac — sherpa-onnx-sys has no usable static lib here, unrelated to this change); CI's Desktop Core job is the authoritative check for this PR.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CqMxL1inNtU7icywZxbrGY

…THROPIC_MODEL

The claude runtime entry declared model_env_var: None, so the model
picked in the agent UI was persisted but never reached the spawned
session — Claude Code agents always ran on the user's global default,
with no error or warning. Goose (GOOSE_MODEL) and Buzz Agent
(BUZZ_AGENT_MODEL) already have this channel; claude was the only
harness with a model picker but no application path.

Declare ANTHROPIC_MODEL as the claude runtime's model env var — the
override the Claude CLI honors (verified: ANTHROPIC_MODEL=x claude
--print reports x), inherited by the adapter's child process, and the
same key readiness.rs already maps to the anthropic provider. Provider
stays locked, so runtime_metadata_env_vars injects the model only.

Add ANTHROPIC_MODEL to DERIVED_PROVIDER_MODEL_ENV_KEYS so a stale
persisted copy cannot shadow the structured model field after a UI
edit — the same treatment the other derived model keys get.

Fixes block#2692

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CqMxL1inNtU7icywZxbrGY
Signed-off-by: Abdulwahab <bosoud@me.com>
@bosoud

bosoud commented Jul 27, 2026

Copy link
Copy Markdown
Author

Closing in favor of #2701, which now carries the shared-const approach and the runtime-shape regression test. Thanks for folding those in @Chessing234 — one PR with everything beats two with halves. (For anyone landing here from #2692: the fix ships via #2701.)

@bosoud bosoud closed this Jul 27, 2026
wpfleger96 pushed a commit that referenced this pull request Jul 28, 2026
…itch (#2795)

## Summary

Fixes #2794. Related: #2692.

`resolve_model_switch_method()` reads the `configId` key from each
`session/new` `configOptions` entry and skips entries that lack it.
`claude-agent-acp` (v0.61.0) keys its entries with `id`, so every
model-category entry was skipped, the desired model never matched, and
Claude Code sessions fell back to the CLI default from the user's
`~/.claude/settings.json`. The only trace was a `pool::model` WARN that
never reaches the per-agent log files.

This is the ACP-side half of the symptom reported in #2692. The open
desktop-side PRs (#2695, #2701, #2696) inject `ANTHROPIC_MODEL` at
spawn, which masks the problem for spawn-time selection but leaves the
config-option switch path broken.

## Changes

- `resolve_model_switch_method()` accepts either `configId` or `id` when
extracting the config id. The set request is unchanged: the ACP SDK
schema takes `configId` as the request param and the adapter resolves it
against its `id`-keyed entries, so only the read side needed fixing.
- Regression test with an `id`-keyed `configOptions` payload mirroring
the real adapter response (including `models: null`, so the unstable
fallback path cannot rescue the match).
- Doc comment on `extract_model_config_options()` notes the key drift.

## Testing

`cargo test -p buzz-acp --lib`: 599 passed, 0 failed. The new test fails
on main and passes with this change.

Verified against the real adapter: a stdio JSON-RPC probe of the bundled
`claude-agent-acp` 0.61.0 confirms `session/new` returns `id`-keyed
config options with `opus[1m]` present as a value, and the SDK's
`SetSessionConfigOptionRequest` schema accepts `{sessionId, configId,
value}` as sent by `session_set_config_option()`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: chillerno1 <gh.chiller@pm.me>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

[Bug] Claude Code agents ignore the model set in Buzz Desktop — model picker persists but nothing applies it at spawn

1 participant