Models
A model definition specifies which Large Language Model (LLM) to use for inference and how to connect to it. Models are referenced by name from prompt definitions and serve as the foundation of the agent system.
1. Model Definition
1.1 Required Properties
A model definition MUST include the following properties:
| Property | Type | Description |
|---|---|---|
name | string | Unique identifier for this model. Used when referencing from prompts. |
provider | ProviderFactory | Factory function that creates a provider instance. |
model | string | The model identifier sent to the provider API. |
1.2 Optional Properties
A model definition MAY include the following properties:
| Property | Type | Description |
|---|---|---|
fallbacks | string[] | Names of fallback models to try if this model fails. |
includedProviders | string[] | Provider routing preferences for multi-provider gateways. |
inputPrice | number | Cost per 1 million input tokens in USD. |
outputPrice | number | Cost per 1 million output tokens in USD. |
cachedPrice | number | Cost per 1 million cached input tokens in USD. |
capabilities | ModelCapabilities | Feature support and limits for this model. |
providerOptions | InferProviderOptions<P> | Provider-specific default options for this model. Type is inferred from the provider’s schema. |
providerTools | string[] | Provider-embedded tools available for this model. |
2. Provider Reference
The provider property accepts a provider factory function imported from a provider package. See the Providers specification for the provider interface.
3. Fallback Chains
3.1 Fallback Behavior
When a model definition includes fallbacks, implementations SHOULD:
- Attempt the primary model first
- If the primary model fails after exhausting retries, try each fallback in order
- Continue until a model succeeds or all fallbacks are exhausted
3.2 Fallback References
Fallback model names MUST reference other defined models by their name property. Implementations SHOULD validate that all referenced fallback models exist at startup.
4. Pricing Configuration
4.1 Token Pricing
Pricing properties are used for cost tracking and reporting. All prices are expressed in USD per 1 million tokens.
| Property | Description |
|---|---|
inputPrice | Cost for input/prompt tokens |
outputPrice | Cost for output/completion tokens |
cachedPrice | Cost for cached input tokens (when provider supports caching) |
4.2 Pricing Priority
Pricing configuration is optional. Providers MAY return pricing information per-request (e.g., in response headers or metadata). When provider pricing is available:
- Provider-reported pricing SHOULD take priority over static model configuration
- Static pricing serves as a fallback when provider pricing is unavailable
- Pricing information SHOULD NOT be exposed to end users without appropriate access controls
5. Capabilities
5.1 Capability Properties
The capabilities object describes features and limits for the model:
| Property | Type | Description |
|---|---|---|
reasoningLevels | Record<number, string | null> | Maps 0-100 scale to model’s native reasoning values. |
supportsImages | boolean | Whether the model accepts image inputs. |
supportsToolCalls | boolean | Whether the model supports tool/function calling. |
supportsStreaming | boolean | Whether the model supports streaming responses. |
supportsJsonMode | boolean | Whether the model supports JSON response format. |
maxContextTokens | number | Maximum input context window size. |
maxOutputTokens | number | Maximum output tokens per response. |
5.2 Reasoning Levels
The reasoningLevels property maps the 0-100 reasoning scale to model-specific values:
// OpenAI o-series models
reasoningLevels: { 0: null, 33: 'low', 66: 'medium', 100: 'high' }
// Binary reasoning (on/off)
reasoningLevels: { 0: null, 100: 'enabled' }
// No reasoning support
reasoningLevels: { 0: null }
5.3 Default Capabilities
When capabilities is not specified or a property is omitted:
supportsImages: Defaults tofalsesupportsToolCalls: Defaults totruesupportsStreaming: Defaults totruesupportsJsonMode: Defaults tofalsereasoningLevels: Defaults to{ 0: null }(no reasoning)
6. Validation
Implementations MUST validate that:
nameis non-empty, unique, and does not contain spacesprovideris a valid provider factory functionmodelis not an empty string
Implementations SHOULD validate that all fallbacks entries reference valid model names.
7. TypeScript Reference
import type { z, ZodTypeAny } from 'zod';
interface ProviderFactoryConfig {
apiKey: string;
baseUrl?: string;
timeout?: number;
}
/**
* Provider factory with optional typed providerOptions schema.
* The schema property allows type inference and runtime validation.
*/
interface ProviderFactoryWithOptions<TOptions extends ZodTypeAny = ZodTypeAny> {
(config: ProviderFactoryConfig): Provider;
/** Zod schema for provider-specific options */
providerOptions?: TOptions;
}
// ProviderFactory is an alias for backward compatibility
type ProviderFactory = ProviderFactoryWithOptions<ZodTypeAny>;
/**
* Extract providerOptions type from a provider factory.
* Returns the inferred input type from the provider's Zod schema.
*/
type InferProviderOptions<P> =
P extends ProviderFactoryWithOptions<infer S>
? S extends ZodTypeAny
? z.input<S>
: Record<string, unknown>
: Record<string, unknown>;
interface ModelCapabilities {
reasoningLevels?: Record<number, string | null>;
supportsImages?: boolean;
supportsToolCalls?: boolean;
supportsStreaming?: boolean;
supportsJsonMode?: boolean;
maxContextTokens?: number;
maxOutputTokens?: number;
}
interface ModelDefinition<
N extends string = string,
P extends ProviderFactoryWithOptions<ZodTypeAny> = ProviderFactoryWithOptions<ZodTypeAny>
> {
name: N;
provider: P;
model: string;
includedProviders?: string[];
fallbacks?: string[];
inputPrice?: number;
outputPrice?: number;
cachedPrice?: number;
capabilities?: ModelCapabilities;
providerOptions?: InferProviderOptions<P>;
providerTools?: string[];
}
function defineModel<N extends string, P extends ProviderFactoryWithOptions<ZodTypeAny>>(
options: ModelDefinition<N, P>
): ModelDefinition<N, P>;
8. Typed Provider Options
8.1 Overview
Provider packages can export a Zod schema that defines the shape of their providerOptions. This enables:
- TypeScript autocomplete: IDE suggestions for valid options
- Type checking: Compile-time errors for invalid options
- Runtime validation: Errors thrown if options don’t match schema
8.2 How It Works
Provider factories can attach a providerOptions property containing a Zod schema:
// Inside @standardagents/openai
import { z } from 'zod';
export const openaiProviderOptions = z.object({
service_tier: z.enum(['auto', 'default', 'flex']).optional(),
user: z.string().optional(),
seed: z.number().int().optional(),
frequency_penalty: z.number().min(-2).max(2).optional(),
presence_penalty: z.number().min(-2).max(2).optional(),
}).passthrough();
export const openai: ProviderFactoryWithOptions<typeof openaiProviderOptions> =
Object.assign(
(config) => new OpenAIProvider(config),
{ providerOptions: openaiProviderOptions }
);
When you use this provider with defineModel, TypeScript automatically infers the correct type for providerOptions:
import { defineModel } from '@standardagents/builder';
import { openai } from '@standardagents/openai';
export default defineModel({
name: 'gpt-4o',
provider: openai,
model: 'gpt-4o',
providerOptions: {
service_tier: 'flex', // TypeScript knows this is valid
// typo_field: 'x', // TypeScript ERROR: unknown property
},
});
8.3 Runtime Validation
When defineModel is called, if the provider has a schema and providerOptions are provided, the options are validated at runtime:
// This throws an error at runtime:
defineModel({
name: 'test',
provider: openai,
model: 'gpt-4o',
providerOptions: {
service_tier: 'invalid', // Error: Invalid enum value
},
});
// Error: Invalid providerOptions for model 'test': service_tier: Invalid enum value
8.4 Provider Schema Examples
OpenAI (@standardagents/openai):
providerOptions: {
service_tier: 'default' | 'auto' | 'flex',
user: string,
seed: number,
frequency_penalty: number, // -2.0 to 2.0
presence_penalty: number, // -2.0 to 2.0
logprobs: boolean,
top_logprobs: number, // 0-20
store: boolean,
metadata: Record<string, string>,
}
OpenRouter (@standardagents/openrouter):
providerOptions: {
provider: {
order: string[], // Provider slugs to try in order
allow_fallbacks: boolean,
require_parameters: boolean,
data_collection: 'allow' | 'deny',
zdr: boolean, // Zero Data Retention
only: string[], // Restrict to these providers
ignore: string[], // Skip these providers
sort: 'price' | 'throughput' | 'latency',
max_price: {
prompt: number,
completion: number,
request: number,
image: number,
},
quantizations: string[],
preferred_min_throughput: number,
preferred_max_latency: number,
},
}
8.5 Backward Compatibility
- Providers without a schema still work (accept
Record<string, unknown>) - Existing model definitions continue to work without changes
- Schema validation is opt-in (only runs if provider exports a schema)
9. Examples
9.1 Basic Model Definition
import { defineModel } from '@standardagents/builder';
import { openai } from '@standardagents/openai';
export default defineModel({
name: 'gpt-4o',
provider: openai,
model: 'gpt-4o',
});
9.2 Model with Pricing and Capabilities
import { defineModel } from '@standardagents/builder';
import { openai } from '@standardagents/openai';
export default defineModel({
name: 'gpt-4o',
provider: openai,
model: 'gpt-4o',
inputPrice: 2.5,
outputPrice: 10,
capabilities: {
supportsImages: true,
supportsToolCalls: true,
supportsJsonMode: true,
maxContextTokens: 128000,
},
});
9.3 Model with Reasoning Levels
import { defineModel } from '@standardagents/builder';
import { openai } from '@standardagents/openai';
export default defineModel({
name: 'o3',
provider: openai,
model: 'o3',
inputPrice: 10,
outputPrice: 40,
capabilities: {
reasoningLevels: { 0: null, 33: 'low', 66: 'medium', 100: 'high' },
supportsImages: true,
supportsToolCalls: true,
},
});
9.4 Model with Fallback Chain
import { defineModel } from '@standardagents/builder';
import { openai } from '@standardagents/openai';
export default defineModel({
name: 'primary-model',
provider: openai,
model: 'gpt-4o',
fallbacks: ['gpt-4-turbo', 'gpt-3.5-turbo'],
inputPrice: 2.5,
outputPrice: 10,
});
9.5 OpenRouter with Typed Provider Options
import { defineModel } from '@standardagents/builder';
import { openrouter } from '@standardagents/openrouter';
export default defineModel({
name: 'claude-3-opus',
provider: openrouter,
model: 'anthropic/claude-3-opus',
inputPrice: 15,
outputPrice: 75,
capabilities: {
supportsImages: true,
supportsToolCalls: true,
},
providerOptions: {
provider: {
zdr: true, // TypeScript knows this is boolean
only: ['anthropic'], // TypeScript knows this is string[]
max_price: {
prompt: 1, // TypeScript autocompletes this structure
completion: 5,
},
},
},
});
9.6 OpenAI with Typed Provider Options
import { defineModel } from '@standardagents/builder';
import { openai } from '@standardagents/openai';
export default defineModel({
name: 'gpt-4o-flex',
provider: openai,
model: 'gpt-4o',
inputPrice: 2.5,
outputPrice: 10,
providerOptions: {
service_tier: 'flex', // TypeScript knows: 'auto' | 'default' | 'flex'
seed: 42, // TypeScript knows this is number
frequency_penalty: 0.5, // TypeScript validates: -2.0 to 2.0
},
});
9.7 Model with Provider Tools
import { defineModel } from '@standardagents/builder';
import { openai } from '@standardagents/openai';
export default defineModel({
name: 'gpt-4o-with-tools',
provider: openai,
model: 'gpt-4o',
inputPrice: 2.5,
outputPrice: 10,
providerTools: ['web_search', 'file_search', 'code_interpreter'],
capabilities: {
supportsImages: true,
supportsToolCalls: true,
},
});
Provider tools are built-in capabilities embedded in the provider (e.g., OpenAI’s web search, file search, code interpreter). See the Providers specification for how providers expose tools.