Skip to main content

ModelConfig

Struct ModelConfig 

Source
#[non_exhaustive]
pub struct ModelConfig { pub id: String, pub name: String, pub api: ApiProtocol, pub provider: String, pub base_url: String, pub reasoning: bool, pub context_window: u32, pub max_tokens: u32, pub cost: CostConfig, pub headers: HashMap<String, String>, pub compat: Option<OpenAiCompat>, pub anthropic: Option<AnthropicCompat>, }
Expand description

Full model configuration. Knows everything needed to make API calls.

Marked #[non_exhaustive]: fields may be added in minor releases (e.g. the anthropic compat flags, slated for 0.9.0). Construct via the ModelConfig::* preset constructors — or ModelConfig::custom for protocols without a preset — and mutate fields to customize. Note that downstream struct literals and functional-record-update (ModelConfig { .. }) no longer compile; field mutation is the supported pattern. New fields must carry #[serde(default)] so previously persisted configs keep deserializing.

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§id: String

Model identifier sent to the API (e.g. “gpt-4o”, “claude-sonnet-4-20250514”).

§name: String

Human-friendly name.

§api: ApiProtocol

Which API protocol to use.

§provider: String

Provider name (e.g. “openai”, “anthropic”, “xai”).

§base_url: String

Base URL for API requests (without trailing slash).

§reasoning: bool

Whether this model supports reasoning/thinking. When false and a thinking_level is requested, the Agent wrapper logs a warning; sub-agents and direct agent_loop calls do not. The request is still sent either way — gate behavior stays with the caller.

§context_window: u32

Context window size in tokens.

§max_tokens: u32

Default max output tokens.

§cost: CostConfig

Cost configuration.

§headers: HashMap<String, String>

Additional headers to send with requests.

May carry credentials (Authorization, x-api-key). Debug prints header names with redacted values, but Serialize is intentionally lossless so configs round-trip — do not serialize a ModelConfig into logs or telemetry.

§compat: Option<OpenAiCompat>

OpenAI-compat quirk flags (only for OpenAiCompletions protocol).

§anthropic: Option<AnthropicCompat>

Anthropic Messages quirk flags (only for AnthropicMessages protocol). None behaves like AnthropicCompat::default() (current generation).

Implementations§

Source§

impl ModelConfig

Source

pub fn mock() -> Self

A minimal config for tests. provider is "mock", cost rates are all zero, and base_url points at a non-routable host.

Use it only with Agent::from_provider / SubAgentTool::from_provider and a MockProvider: those take the provider explicitly, so the config’s protocol is never consulted.

Do not pass it to Agent::from_config — that dispatches on the protocol (here AnthropicMessages) and would build the real Anthropic provider pointed at the non-routable base_url, so the first prompt fails with a network error instead of returning a mock response.

Source

pub fn custom( api: ApiProtocol, provider: impl Into<String>, base_url: impl Into<String>, model_id: impl Into<String>, name: impl Into<String>, ) -> Self

Create a config for any protocol without a dedicated preset (Bedrock, Vertex, Azure, or future protocols).

Since ModelConfig is #[non_exhaustive], this is the construction path when no ModelConfig::* preset fits. Defaults: 128K context, 16K max output, no compat flags — mutate fields to adjust.

Source

pub fn anthropic(id: impl Into<String>, name: impl Into<String>) -> Self

Create a new Anthropic model config.

Source

pub fn claude_fable_5() -> Self

Claude Fable 5 — Anthropic’s most capable model. 1M context; defaults to 64K of the model’s 128K max output.

Rates verified against https://platform.claude.com/docs/en/about-claude/pricing on 2026-08-19. See CostConfig — they are a snapshot, not an authority.

Source

pub fn claude_opus_5() -> Self

Claude Opus 5. 1M context; defaults to 64K of the model’s 128K max output.

Opus 5 thinks whenever a request omits thinking, so ThinkingLevel::Off does not disable thinking here — the provider omits the field rather than sending {"type": "disabled"}, and those tokens still count against max_tokens. Any other level takes the adaptive path that AnthropicCompat::default() selects, which Opus 5 accepts unchanged.

Rates verified against https://platform.claude.com/docs/en/about-claude/pricing on 2026-08-19. See CostConfig — they are a snapshot, not an authority.

Source

pub fn claude_opus_4_8() -> Self

Claude Opus 4.8. 1M context; defaults to 64K of the model’s 128K max output.

Rates verified against https://platform.claude.com/docs/en/about-claude/pricing on 2026-08-19. See CostConfig — they are a snapshot, not an authority.

Source

pub fn claude_sonnet_5() -> Self

Claude Sonnet 5. 1M context; defaults to 64K of the model’s 128K max output.

Rates verified against https://platform.claude.com/docs/en/about-claude/pricing on 2026-08-19. See CostConfig — they are a snapshot, not an authority.

Source

pub fn claude_haiku_4_5() -> Self

Claude Haiku 4.5. 200K context; defaults to 32K of the model’s 64K max output.

Rates verified against https://platform.claude.com/docs/en/about-claude/pricing on 2026-08-19. See CostConfig — they are a snapshot, not an authority.

Source

pub fn gpt_5_5() -> Self

GPT-5.5. ~1M context; defaults to 64K of the model’s 128K max output. Uses the Chat Completions API.

Rates verified against https://developers.openai.com/api/docs/pricing on 2026-08-19. See CostConfig — they are a snapshot, not an authority.

Deliberately flat, over a contested tier claim. models.dev records a 272K tier for this model at $10/$45 with $1.00 cache reads. The preset does not, because the evidence does not survive checking:

  • OpenAI’s pricing page does publish a >272K input tokens schedule, as a second column group beside ≤272K. But gpt-5.5 has no row in that table. Across all four Flagship tiers it appears only as gpt-5.5 (<272K context length) — Standard $5/$0.50/$30, Batch and Flex $2.50/$15, Fast $12.50/$75 — with no long-context cell.
  • The one gpt-5.5 row that is in a long-context table, gpt-5.5-cyber, has all four long-context cells set to -, and the page hides that row by default.
  • $10/$1/$45 does appear on the page verbatim — as gpt-5.6-sol’s long-context rates. Its short-context rates are identical to gpt-5.5’s, which is a plausible route for the number to have been copied onto the wrong model.
  • models.dev’s own entry contradicts itself: tiers[0].tier.size is 272000 while the sibling key carrying the same rates is named context_over_200k.

Tiering this preset on that would have doubled the input rate every caller is charged above 272K prompt tokens. If OpenAI publishes a gpt-5.5 long-context row, the machinery is ready — CostConfig::with_context_tier. Until then, flat.

Rates verified against https://developers.openai.com/api/docs/pricing on 2026-08-20, both column groups read. See CostConfig.

Source

pub fn openai(id: impl Into<String>, name: impl Into<String>) -> Self

Create a new OpenAI model config.

Source

pub fn local(base_url: impl Into<String>, model_id: impl Into<String>) -> Self

Create a config for a local OpenAI-compatible server (LM Studio, Ollama, etc.). No API key required — sends an empty Bearer token.

Source

pub fn opencode_zen(model_id: impl Into<String>) -> Self

Create a config for a model served by OpenCode Zen (https://opencode.ai/docs/zen), OpenCode’s pay-per-use gateway.

Zen serves each model family over a different protocol; the protocol is selected from the model id:

  • gpt-* → OpenAI Responses API (pair with OpenAiResponsesProvider)
  • claude-*, qwen* → Anthropic Messages API (pair with AnthropicProvider)
  • everything else (DeepSeek, MiniMax, GLM, Kimi, …) → Chat Completions (pair with OpenAiCompatProvider)

Gemini models are not supported — Zen serves them over a Google-native endpoint shape yoagent does not target. A gemini-* id falls through to Chat Completions (with a warning) and will likely fail at request time.

The routing mirrors the Zen endpoint tables as of mid-2026; if a model errors, verify its protocol against https://opencode.ai/zen/v1/models.

Context window and max output default conservatively (128K / 16K); override the fields for models with larger limits.

Source

pub fn opencode_go(model_id: impl Into<String>) -> Self

Create a config for a model served by OpenCode Go (https://opencode.ai/docs/go), OpenCode’s subscription gateway for open models.

Protocol is selected from the model id:

  • qwen*, minimax-* → Anthropic Messages API (pair with AnthropicProvider)
  • everything else (GLM, Kimi, DeepSeek, MiMo, …) → Chat Completions (pair with OpenAiCompatProvider)
Source

pub fn openai_compat( base_url: impl Into<String>, model_id: impl Into<String>, provider: impl Into<String>, compat: OpenAiCompat, ) -> Self

Create a config for a custom OpenAI-compatible endpoint with explicit compat flags.

Source

pub fn ollama(base_url: impl Into<String>, model_id: impl Into<String>) -> Self

Create a config for Ollama’s OpenAI-compatible API.

Default local base URL: http://localhost:11434/v1.

Source

pub fn zai(id: impl Into<String>, name: impl Into<String>) -> Self

Create a new Z.ai (Zhipu AI) model config.

Models: glm-4.7, glm-4.5-air, glm-5, etc.

Source

pub fn meta(id: impl Into<String>, name: impl Into<String>) -> Self

Create a new Meta Model API config (Muse Spark).

Models: muse-spark-1.1 — 1,048,576-token context; 128K max output per Meta’s integration examples (no official model card yet). US-only public preview as of July 2026. OpenAI-compatible endpoint at https://api.meta.ai/v1. Key resolves from META_API_KEY, then Meta’s documented MODEL_API_KEY.

Reasoning: Meta’s endpoint defaults to reasoning_effort: medium server-side. Set a ThinkingLevel to tune it; Off omits the field, which means Meta’s default (medium) applies — not “no reasoning”.

Rates are Muse Spark 1.1/1.2, verified 2026-08-19. This constructor is generic over the model id, so a different tier needs config.cost overridden: the contributor tier runs 12x lower on input, 21x on output and 75x on cache reads, so ModelConfig::meta("muse-spark-1.2-contributor", ..) overstates cost badly. See CostConfig.

Source

pub fn minimax(id: impl Into<String>, name: impl Into<String>) -> Self

Create a new MiniMax model config.

Models: MiniMax-Text-01, MiniMax-M1, etc.

Source

pub fn qwen(id: impl Into<String>, name: impl Into<String>) -> Self

Create a new Qwen / DashScope model config.

Models: qwen3.6-plus, qwen3.5-plus, qwen-plus, qwen-flash, etc.

Source

pub fn xai(id: impl Into<String>, name: impl Into<String>) -> Self

Create a new xAI (Grok) model config.

Models: grok-4-1-fast, grok-4-1, etc.

Source

pub fn groq(id: impl Into<String>, name: impl Into<String>) -> Self

Create a new Groq model config.

Models: llama-3.3-70b-versatile, mixtral-8x7b-32768, etc.

Source

pub fn deepseek(id: impl Into<String>, name: impl Into<String>) -> Self

Create a new DeepSeek model config.

Models: deepseek-v4-flash, deepseek-v4-pro, etc.

Legacy aliases deepseek-chat and deepseek-reasoner are accepted by DeepSeek for now, but are scheduled for deprecation on 2026-07-24.

Source

pub fn mistral(id: impl Into<String>, name: impl Into<String>) -> Self

Create a new Mistral model config.

Models: mistral-large-latest, mistral-small-latest, etc.

Source

pub fn google(id: impl Into<String>, name: impl Into<String>) -> Self

Create a new Google Generative AI (Gemini) model config.

Trait Implementations§

Source§

impl Clone for ModelConfig

Source§

fn clone(&self) -> ModelConfig

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ModelConfig

Redacts header values. Headers routinely carry credentials, and a derived Debug would print them into any log line or panic message.

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for ModelConfig

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for ModelConfig

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more