Skip to content
Weaveweave / docs
Get started ↗
Docs/Reference/Model Resolution

Model Resolution

How Weave handles model preferences and concrete model resolution

Weave does not resolve models by querying harness UI state. Weave records model intent in normalized config, and adapters translate that intent into concrete harness-specific model fields.

Agents and categories declare ordered model preferences. See the Agents guide and Categories guide for more information.

agent loom {
mode primary
models ["anthropic/claude-sonnet-4-5", "openai/gpt-4o"]
}
category frontend {
description "Frontend UI, styling, accessibility"
models ["openai/gpt-5", "anthropic/claude-sonnet-4-5"]
}

models [...] means: “these are the models this agent or category prefers, in order.” It is not a scalar resolved model field, and it is not a command for core Weave to inspect harness state.

mode is adapter-facing metadata:

Mode Weave meaning Adapter interpretation
primary This agent can be the main/user-facing agent for a harness session. Adapter may map it to the harness-selected/default model when that harness supports such a concept.
subagent This agent is intended for delegated/specialist work. Adapter should prefer explicit Weave model preferences before harness defaults.
all This agent can participate in both primary and delegated contexts. Adapter chooses the harness-specific mapping for each context and documents any differences.

Core Weave does not know whether a user has selected a model in a UI, whether the harness exposes that model, or whether the harness supports model inheritance at all.

Adapters own concrete model resolution because they own the harness integration. An adapter may consider:

  1. Adapter/harness-specific per-agent overrides.
  2. A UI-selected model, if the harness exposes one and the agent mode makes that appropriate.
  3. Category model preferences for generated category shuttles.
  4. Agent models [...] preferences.
  5. Harness/system defaults.
  6. A documented adapter fallback.

This priority order mirrors the useful policy from legacy OpenCode-Weave, but it is applied at the adapter boundary with explicit harness context. Core Weave must not call getSelectedModel(), getAvailableModels(), or equivalent UI/runtime APIs.

OpenCode identifies a model as provider/model, for example anthropic/claude-sonnet-4-5 or openai/gpt-5. The OpenCode adapter therefore uses only provider/model preferences:

  • Qualified preferences are used in order, after any UI-selected model that applies to the agent’s mode.
  • Bare model names are skipped, such as claude-sonnet-4-5. OpenCode would read claude-sonnet-4-5 as a provider with an empty model ID and fail with ProviderModelNotFoundError.
  • No qualified preference means no model. The adapter leaves model unset, so OpenCode uses your selected or default model.

The builtin agents declare bare model IDs (Loom prefers claude-opus-5.5, then claude-opus-5-5, then gpt-6-sol), so on OpenCode 1.x they run on your OpenCode model unless you give them a provider/model preference:

agent loom {
models ["anthropic/claude-opus-5-5"]
}

For a subagent whose first qualified preference isn’t available in OpenCode, the adapter reports an error rather than silently choosing another model.

The OpenCode 2 adapter resolves each preference against the models your OpenCode 2 host offers, in order:

  • provider/model matches that provider’s model exactly, for example anthropic/claude-opus-5-5. The provider ends at the first slash, so openrouter/anthropic/claude-opus-5.5 is provider openrouter, model anthropic/claude-opus-5.5.
  • A bare ID such as claude-opus-5-5 is used when exactly one connected provider offers a model with that ID. If several do, it is skipped; qualify it to choose one.
  • model#variant also requires that variant.

The first preference that resolves is used. If none does, the agent is still registered, without a model, so OpenCode 2 uses its own selected or default model, and Weave’s status lists the agent whose model didn’t resolve. The builtins list both the GitHub Copilot spelling (claude-opus-5.5) and the Anthropic spelling (claude-opus-5-5) so a bare ID resolves on either provider.

The builtin agents’ model lists can also come from a signed list published on tryweave.io, without upgrading Weave. It is opt-in, and your own models still come first. See Model Updates.

Categories affect the prompt/delegation graph, so Weave may generate category shuttle descriptors such as shuttle-frontend from .weave category blocks. See the Categories guide for detailed information about category shuttles and delegation topology.

Those descriptors carry category model preferences as intent. The adapter decides how those preferences map to a concrete model field for its harness.

Each generated shuttle-{categoryName} descriptor carries models from the matching category.models declaration as ordered model preferences. This is still intent only: the descriptor does not contain a concrete harness model, and the engine does not query harness UI state.

When an adapter translates a generated category shuttle, it should pass those category preferences to resolveAdapterModelIntent() as categoryModels. If the adapter also has access to the base shuttle agent preferences, it can pass those as agentModels so the helper tries category preferences before inherited/base agent preferences, after any adapter override and after any applicable UI-selected model.

Because generated category shuttles always have mode: "subagent", resolveAdapterModelIntent() skips uiSelectedModel for them and resolves directly from explicit category or agent model preferences before falling back to adapter defaults.

import { resolveAdapterModelIntent } from "@weaveio/weave-engine";
const resolved = resolveAdapterModelIntent({
agentName: "shuttle-frontend",
agentMode: categoryShuttle.mode, // always "subagent" for generated shuttles
categoryModels: categoryShuttle.models,
agentModels: baseShuttle.models,
overrideModel: adapterOverrides["shuttle-frontend"],
uiSelectedModel: harnessSelectedModel,
systemDefault: harnessDefaultModel,
availableModels: harnessAvailableModels,
});

Adapters are not required to use this helper if their harness has a stronger native model-selection mechanism, but they should preserve the same boundary: Weave provides ordered model intent, and the adapter owns concrete model translation.

Weave is intended to be reusable across OpenCode, Pi, Claude Code, Codex, and future harnesses. Some harnesses have a visible selected model; some may not. Some expose available model lists; some may rely on config-time validation or provider errors.

Keeping model UI state in adapters preserves the product architecture:

Weave = normalized prompt/config/delegation API
Adapter = harness-specific editor/plugin/runtime builder

This is the same relationship as an API layer like Neovim and the user/plugin configuration that turns that API into a concrete editor experience.

See the Architecture guide for more information about the adapter boundary and the Adapters guide for harness-specific details.