Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/phpaisdk/core/llms.txt

Use this file to discover all available pages before exploring further.

Provider packages ship a resources/models.json catalog that describes every known model and its capabilities. When a provider releases a new model between package versions, you don’t have to wait for an update — BaseProvider::registerModel() lets you teach the SDK about that model at runtime so capability checks, streaming, tool calling, and structured output all work correctly from the first call.

Why runtime registration matters

The SDK validates capability requirements — streaming, tool calling, image input, and so on — before sending a request to the provider API. Without a registered definition, those checks fall back to the bundled catalog. If the model isn’t in the catalog yet, text generation still works (unknown model IDs are allowed through), but capabilities like structured output or image input will be treated as unsupported until you register the model explicitly.

Registering a model

Call registerModel() on the provider class. Pass the model ID string and a capabilities array of Capability enum cases.
use AiSdk\Capability;
use AiSdk\OpenAI;

OpenAI::registerModel('gpt-4.2', capabilities: [
    Capability::TextGeneration,
    Capability::Streaming,
    Capability::ToolCalling,
    Capability::StructuredOutput,
    Capability::TextInput,
]);

$result = Generate::text('Hello')
    ->model(OpenAI::model('gpt-4.2'))
    ->run();
registerModel() accepts either a bare string ID (shown above) or a fully constructed ModelDefinition for advanced use cases where you also want to set adapted capabilities or metadata.
Model ID strings are provider-specific. 'gpt-4.2' only means something to the OpenAI provider; pass the same string to Anthropic::registerModel() and it registers a completely separate entry in Anthropic’s registry. Always use the exact identifier the provider API expects.

BaseProvider::registerModel() signature

// From AiSdk\Contracts\BaseProvider:

/**
 * @param  ModelDefinition|string  $model
 * @param  array<int, Capability>  $capabilities
 */
public function registerModel(ModelDefinition|string $model, array $capabilities = []): static
The method is defined on BaseProvider and is therefore available on every first-party provider class (OpenAI, Anthropic, etc.) that extends it. It returns static so calls can be chained.

ModelDefinition

ModelDefinition is the immutable value object the registry stores. You can create one directly when you need to express adapted capabilities or attach metadata.
use AiSdk\Capability;
use AiSdk\ModelDefinition;

$definition = new ModelDefinition(
    id: 'gpt-4.2',
    capabilities: [
        Capability::TextGeneration,
        Capability::Streaming,
        Capability::ToolCalling,
        Capability::TextInput,
        Capability::ImageInput,
    ],
    adaptedCapabilities: [
        'structured_output' => ['strategy' => 'json_schema'],
    ],
    metadata: [
        'status'        => 'ga',
        'limits'        => ['context_window' => 200_000],
        'released_at'   => '2025-05-01',
    ],
);
PropertyTypeDescription
$idstringModel identifier (e.g. 'gpt-4.2')
$capabilitiesCapability[]Capabilities the model natively supports
$adaptedCapabilitiesarray<string, array>Capabilities the provider adapter simulates, keyed by capability name
$metadataarray<string, mixed>Freeform metadata (limits, pricing, status, etc.)

Loading from a JSON array

ModelDefinition::fromArray() parses raw catalog data, which is useful when you load model definitions from a JSON file or API response.
$definition = ModelDefinition::fromArray([
    'id'           => 'gpt-4o',
    'capabilities' => ['text_generation', 'streaming', 'image_input'],
    'adapted_capabilities' => [
        'structured_output' => ['strategy' => 'json_schema'],
    ],
    'status'   => 'ga',
    'limits'   => ['context_window' => 128_000],
    'released_at' => '2024-05-13',
]);
Capability name strings recognized by fromArray():
StringCapability case
text_generationCapability::TextGeneration
streamingCapability::Streaming
tool_callingCapability::ToolCalling
structured_outputCapability::StructuredOutput
reasoningCapability::Reasoning
image_generationCapability::ImageGeneration
text_inputCapability::TextInput
image_inputCapability::ImageInput
audio_inputCapability::AudioInput
file_inputCapability::FileInput
Unrecognized strings are silently ignored.

ModelRegistry — how registration is stored

Providers that extend BaseProvider own a lazy ModelRegistry instance. The registry is a simple per-provider map: provider → modelId → ModelDefinition.
use AiSdk\ModelDefinition;
use AiSdk\Support\ModelRegistry;

$registry = new ModelRegistry();

$registry->register('openai', new ModelDefinition(
    id: 'gpt-custom',
    capabilities: [Capability::TextGeneration],
));

$definition = $registry->resolve('openai', 'gpt-custom'); // ModelDefinition
$missing    = $registry->resolve('openai', 'never-registered'); // null
Lookup is scoped to the provider name, so registering 'gpt-custom' under 'openai' does not affect the Anthropic registry.

ModelCatalog — built-in model metadata

Every provider package ships a resources/models.json file that lists its built-in models. ModelCatalog::fromFile() loads (and caches) that file, and the provider checks it as a fallback after ModelRegistry.
Lookup order for a capability check:
  1. User-registered ModelRegistry  ← registerModel() writes here
  2. Bundled ModelCatalog            ← resources/models.json
  3. Unknown-model fallback          ← text generation only; other capabilities deferred to API
You do not interact with ModelCatalog directly during normal usage — it is an internal detail of the provider’s capability resolution.

Fallback behavior for unregistered models

If you pass a model ID that is not in the registry or the bundled catalog, the SDK still allows the request to proceed for TextGeneration. The provider’s API will return a normalized error (typically a NotFoundException or InvalidRequestException) if the model doesn’t actually exist, giving you a clean error message rather than a silent wrong result.
Capabilities beyond text generation (streaming, tool calling, image input, etc.) will be reported as not supported for unregistered models. If you need those features with a newly released model, always call registerModel() before constructing it.

Passing a ModelDefinition directly

You can also pass a pre-built ModelDefinition to registerModel() when you want the full constructor:
use AiSdk\Capability;
use AiSdk\ModelDefinition;
use AiSdk\OpenAI;

OpenAI::registerModel(new ModelDefinition(
    id: 'gpt-4.2',
    capabilities: [
        Capability::TextGeneration,
        Capability::Streaming,
        Capability::ToolCalling,
        Capability::StructuredOutput,
        Capability::TextInput,
        Capability::ImageInput,
    ],
    metadata: ['status' => 'preview'],
));

Build docs developers (and LLMs) love