How OpenCode Keeps Model Choice Flexible

This chapter explains how OpenCode chooses a model without making the Session understand every provider’s endpoint, credential scheme, and wire format. The useful judgment is to keep four levels separate: a catalog record describes a possible provider or model, availability says whether it can be used now, an executable model binds that choice to a route, and an adapter translates the route into a provider request. That separation is what lets OpenCode vary model choice while keeping its orchestration loop stable.

A model is more than an identifier

It is tempting to treat a model as a string such as provider/model. OpenCode’s source treats that string as only the beginning of a model reference. A provider can expose many models, and a model identifier is meaningful within that provider’s namespace. The V2 catalog consequently stores provider records and their model records together rather than assuming that one global model name is enough.

A provider record describes the connection side of the relationship: its identity, API or endpoint shape, request headers and body defaults, and any integration that supplies access. A model record describes the selected deployment: its API identity, capabilities, input and output modalities, context and output limits, pricing metadata, release/status information, variants, and enabled state. The distinction reflects two kinds of change. A provider’s endpoint or authentication setup may apply to many models, while a model’s context window or reasoning capability may differ from its neighbors on the same service.

The catalog is therefore an execution input, not a display database. If a model does not support tool calls, the agent cannot assume that a tool-heavy turn will work. If its context limit is smaller than the current Session request, compaction may be needed earlier. If it accepts images or PDFs, the prompt assembly path can preserve those modalities; if it does not, the runtime needs a different representation or an explicit failure. If pricing metadata is present, OpenCode can estimate usage, but the catalog’s estimate is not a provider billing guarantee.

Variants add another layer. A variant is a named change to request behavior for one model, such as a reasoning setting or other provider option. In the V2 model resolver, the selected variant is applied as an overlay to the model’s request headers and body. It remains separate from the model reference because appending a variant to a slash-delimited provider/model string would make parsing ambiguous when model IDs themselves contain slashes. In practical use, a model can stay the same while a Session chooses a different supported behavior for a turn.

Availability is also not identical to existence. The catalog can know about a provider from its metadata even when the user has no credential or active account. A provider can be configured but disabled. A model can be present but unavailable because its provider is unavailable or its own enabled state is false. OpenCode’s V2 catalog checks provider availability through credentials or integrations and then filters models accordingly. This prevents the model picker from implying that every catalog entry is a usable deployment.

The catalog also has to resolve ownership when provider and model settings overlap.