Provider packages ship aDocumentation 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.
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
CallregisterModel() on the provider class. Pass the model ID string and a capabilities array of Capability enum cases.
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
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.
| Property | Type | Description |
|---|---|---|
$id | string | Model identifier (e.g. 'gpt-4.2') |
$capabilities | Capability[] | Capabilities the model natively supports |
$adaptedCapabilities | array<string, array> | Capabilities the provider adapter simulates, keyed by capability name |
$metadata | array<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.
fromArray():
| String | Capability case |
|---|---|
text_generation | Capability::TextGeneration |
streaming | Capability::Streaming |
tool_calling | Capability::ToolCalling |
structured_output | Capability::StructuredOutput |
reasoning | Capability::Reasoning |
image_generation | Capability::ImageGeneration |
text_input | Capability::TextInput |
image_input | Capability::ImageInput |
audio_input | Capability::AudioInput |
file_input | Capability::FileInput |
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.
'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.
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 forTextGeneration. 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.
Passing a ModelDefinition directly
You can also pass a pre-built ModelDefinition to registerModel() when you want the full constructor: