Skip to content

Fix agent-host Claude sending reasoning effort to models that reject it#321698

Merged
TylerLeonhardt merged 1 commit into
mainfrom
fix/agent-host-claude-haiku-effort
Jun 17, 2026
Merged

Fix agent-host Claude sending reasoning effort to models that reject it#321698
TylerLeonhardt merged 1 commit into
mainfrom
fix/agent-host-claude-haiku-effort

Conversation

@TylerLeonhardt

@TylerLeonhardt TylerLeonhardt commented Jun 17, 2026

Copy link
Copy Markdown
Member

Summary

Fixes https://github.com/microsoft/vscode-internalbacklog/issues/8031

Fresh agent-host Claude sessions on claude-haiku-4.5 failed with:

400 output_config.effort "high" was provided, but model claude-haiku-4.5 does not support reasoning effort

Root cause: the agent host passed the CAPI/endpoint model id (dotted, claude-haiku-4.5) straight to the Claude SDK/CLI, but the CLI keys its internal model table by the SDK format (dashed, claude-haiku-4-5). Given an id it doesn't recognize, the CLI falls back to a generic full-feature request — thinking: { type: "adaptive" } + output_config: { effort: "high" } — which CAPI rejects for models that don't support reasoning effort. Our own Options.effort was already undefined; the effort came entirely from the CLI's unknown-model fallback.

Fix

  • Add toSdkModelId() and normalize the model id to SDK format at every SDK seam (buildOptions startup, runtime setModel, pipeline seed). Codename / non-Claude ids pass through unchanged.
  • Document the dotted (CAPI/endpoint) vs dashed (SDK) format boundary at the id origin (claudeAgent.toAgentModelInfo) and the proxy round-trip (/v1/messages rewrite).
  • Clear stale runtime effort when switching to a no-effort model (setEffort(undefined)applyFlagSettings({ effortLevel: null })).

Validation

  • Standalone repro (Claude Agent SDK + a fake /v1/messages capture endpoint, no CAPI): dotted id → output_config.effort: "high"; dashed id → no output_config, correct thinking: { type: "enabled" }.
  • 23 unit tests pass (toSdkModelId normalization + ClaudeSdkPipeline effort suite); clean tsgo type-check.

Test plan

  • In an Agents window with chat.agents.claude.preferAgentHost: true, start a Claude session on Haiku 4.5 and send a message → no 400, model responds.
  • Repeat on an effort-capable model (Opus/Sonnet) → reasoning effort still applied as before.
  • Switch model mid-session from an effort model to Haiku and back → no stale-effort 400.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings June 17, 2026 00:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes Claude Agent SDK sessions failing on models that reject reasoning effort (e.g. claude-haiku-4.5) by normalizing Claude model IDs to the SDK/CLI’s dashed format at all SDK seams and ensuring stale effort is explicitly cleared when switching to no-effort models.

Changes:

  • Add toSdkModelId() and use it when passing model IDs into the Claude Agent SDK (startup options, runtime setModel, pipeline seeding), while preserving endpoint-format IDs elsewhere.
  • Explicitly clear runtime reasoning effort when switching to a model that resolves to undefined effort via applyFlagSettings({ effortLevel: null }).
  • Add/extend unit tests covering model-id normalization and effort-clearing behavior.
Show a summary per file
File Description
src/vs/platform/agentHost/test/node/claudeSdkPipeline.test.ts Adds a recorder warm/query double and new setEffort tests to validate effort clearing/pushing behavior.
src/vs/platform/agentHost/test/node/claudeModelId.test.ts Adds standalone unit coverage for toSdkModelId() normalization and passthrough behavior.
src/vs/platform/agentHost/node/claude/claudeSdkPipeline.ts Updates setEffort to treat undefined as “clear” via effortLevel: null.
src/vs/platform/agentHost/node/claude/claudeSdkOptions.ts Normalizes Options.model to SDK format at startup using toSdkModelId().
src/vs/platform/agentHost/node/claude/claudeProxyService.ts Documents and performs SDK→endpoint model-id rewrite for /v1/messages requests.
src/vs/platform/agentHost/node/claude/claudeModelId.ts Introduces toSdkModelId() helper to normalize endpoint-format IDs to SDK format.
src/vs/platform/agentHost/node/claude/claudeAgentSession.ts Normalizes model IDs for pipeline seeding/runtime setModel, and always calls setEffort (including undefined) to clear stale effort.
src/vs/platform/agentHost/node/claude/claudeAgent.ts Documents that ModelSelection.id is canonicalized in endpoint (dotted) format and must be normalized at SDK seams.

Copilot's findings

  • Files reviewed: 8/8 changed files
  • Comments generated: 1

Comment thread src/vs/platform/agentHost/test/node/claudeSdkPipeline.test.ts
@TylerLeonhardt TylerLeonhardt force-pushed the fix/agent-host-claude-haiku-effort branch 2 times, most recently from 7e14b0e to a09d81c Compare June 17, 2026 00:38
@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Base: 7dd4002e Current: 82542208

No screenshot changes.

The agent host passed the CAPI/endpoint model id (dotted, e.g.
`claude-haiku-4.5`) to the Claude SDK/CLI, which keys its model table by the
SDK format (dashed, `claude-haiku-4-5`). Given an unrecognized id the CLI
falls back to a generic request shape (adaptive thinking + reasoning effort
`high`); CAPI then 400s for models that don't support effort
(`output_config.effort "high" ... does not support reasoning effort`).

Normalize the id to SDK format via `toSdkModelId` at every SDK seam (startup
options, runtime setModel, seed), and document the dotted/dashed boundary at
the origin and the proxy round-trip. Also clear stale runtime effort when
switching to a no-effort model.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
@TylerLeonhardt TylerLeonhardt force-pushed the fix/agent-host-claude-haiku-effort branch from a09d81c to 6648b83 Compare June 17, 2026 03:19
@TylerLeonhardt TylerLeonhardt marked this pull request as ready for review June 17, 2026 03:50
@TylerLeonhardt TylerLeonhardt enabled auto-merge (squash) June 17, 2026 03:50
@TylerLeonhardt TylerLeonhardt merged commit 271b150 into main Jun 17, 2026
39 of 40 checks passed
@TylerLeonhardt TylerLeonhardt deleted the fix/agent-host-claude-haiku-effort branch June 17, 2026 04:31
@vs-code-engineering vs-code-engineering Bot added this to the 1.126.0 milestone Jun 17, 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.

3 participants