/home/home/p/g/n/claude_agent_sdk does not own active model policy.
That authority lives in:
/home/home/p/g/n/cli_subprocess_core/lib/cli_subprocess_core/model_registry.ex/home/home/p/g/n/cli_subprocess_core/priv/models/claude.json
The Claude SDK consumes the resolved payload from core and only turns that payload into Claude CLI arguments and env.
Core-Owned Resolution
The authoritative core surface is:
CliSubprocessCore.ModelRegistry.resolve/3CliSubprocessCore.ModelRegistry.validate/2CliSubprocessCore.ModelRegistry.default_model/2CliSubprocessCore.ModelRegistry.build_arg_payload/3CliSubprocessCore.ModelInput.normalize/3
ClaudeAgentSDK.Options.new/1 routes mixed raw input or explicit
model_payload through CliSubprocessCore.ModelInput.normalize/3.
That means:
- explicit
model_payloadstays authoritative when supplied - conflicting raw attrs fail immediately
- repo-local env defaults are only consulted when no payload was supplied
Native Claude Backend
The default backend is the normal Claude catalog path.
Canonical Claude model names include:
opussonnethaikuopus[1m]sonnet[1m]
Example:
options =
ClaudeAgentSDK.Options.new(
model: "sonnet",
max_turns: 1
)That resolves through cli_subprocess_core before the SDK emits claude ....
Ollama Backend
The SDK now supports an explicit Claude :ollama backend.
This still runs the normal claude binary.
The difference is that the core payload carries:
- the resolved external model id
ANTHROPIC_AUTH_TOKEN=ollamaANTHROPIC_API_KEY=""ANTHROPIC_BASE_URL=http://localhost:11434or your override
Direct external model id
options =
ClaudeAgentSDK.Options.new(
provider_backend: :ollama,
anthropic_base_url: "http://localhost:11434",
model: "llama3.2"
)Canonical Claude name mapped to an Ollama model
options =
ClaudeAgentSDK.Options.new(
provider_backend: :ollama,
anthropic_base_url: "http://localhost:11434",
external_model_overrides: %{"haiku" => "llama3.2"},
model: "haiku"
)In that case:
- the requested Claude name stays
haiku - the core payload resolves the transport model to
llama3.2 - the SDK emits
claude --model llama3.2
Environment-Driven Backend Selection
The same Ollama path can be configured from env.
Relevant variables:
CLAUDE_AGENT_PROVIDER_BACKENDCLAUDE_AGENT_EXTERNAL_MODEL_OVERRIDESANTHROPIC_BASE_URLANTHROPIC_AUTH_TOKENANTHROPIC_API_KEY
Example:
export CLAUDE_AGENT_PROVIDER_BACKEND=ollama
export CLAUDE_AGENT_EXTERNAL_MODEL_OVERRIDES='{"haiku":"llama3.2","sonnet":"llama3.2","opus":"llama3.2"}'
export ANTHROPIC_AUTH_TOKEN=ollama
export ANTHROPIC_API_KEY=""
export ANTHROPIC_BASE_URL=http://localhost:11434
That is the path used by /home/home/p/g/n/claude_agent_sdk/examples/run_all.sh
when you set CLAUDE_EXAMPLES_BACKEND=ollama.
Effort Gating
Effort is still a Claude-native feature.
For native Claude models:
haikudoes not support effortsonnetsupports:low,:medium,:highopussupports:low,:medium,:high,:max
For external Claude/Ollama runs, the SDK does not emit --effort.
That is deliberate. Once the resolved payload is an external backend model, the SDK stops pretending the external model supports Claude-native effort semantics.
Settings And Env From The Payload
The SDK now reads these payload fields from core:
resolved_modelenv_overridessettings_patchmodel_sourceprovider_backend
That means:
- model policy stays in core
- backend env is merged in one place
- future Claude backend settings can also be attached by the core payload
Examples
Run the live example suite against the native Claude backend:
./examples/run_all.sh
Run the live example suite against Ollama:
CLAUDE_EXAMPLES_BACKEND=ollama \
CLAUDE_EXAMPLES_OLLAMA_MODEL=llama3.2 \
./examples/run_all.sh
The runner maps the common Claude names used by the examples onto the selected Ollama model. Claude-only effort examples are skipped in that mode because the external backend does not support Claude-native effort semantics.