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.

The SDK draws a clear line between a provider — the company or service hosting models — and a model — a specific identifier within that provider. Providers expose factory methods that return typed model objects; those model objects implement the Model interface and carry a full capability declaration used by the SDK to validate requests before they hit the network.

The ProviderInterface

Every concrete provider implements ProviderInterface, which defines three responsibilities:
interface ProviderInterface
{
    public function name(): string;

    public function textModel(string $modelId): TextModelInterface;

    public function imageModel(string $modelId): ImageModelInterface;
}
  • name() returns a stable string identifier for the provider (e.g. 'openai', 'anthropic').
  • textModel($modelId) constructs and returns an object capable of text generation.
  • imageModel($modelId) constructs and returns an object capable of image generation.
Calling a factory for an unsupported modality throws NoSuchModelException.

BaseProvider: the default-throw pattern

Rather than forcing every provider to implement every modality, the SDK ships BaseProvider, an abstract class whose default textModel() and imageModel() implementations both throw NoSuchModelException. A concrete provider only overrides the modalities it actually supports:
use AiSdk\Contracts\BaseProvider;
use AiSdk\Contracts\TextModelInterface;

final class AcmeProvider extends BaseProvider
{
    public function name(): string
    {
        return 'acme';
    }

    public function textModel(string $modelId): TextModelInterface
    {
        // Return a concrete TextModelInterface for known IDs.
        return new AcmeTextModel($modelId);
    }

    // imageModel() is not overridden — calling it throws NoSuchModelException.
}
BaseProvider also holds a ModelRegistry that lets you register custom models at runtime (see Custom Model Registration).

The Model interface

Every model object — text or image — implements Model:
interface Model
{
    public function specificationVersion(): string;
    public function provider(): string;
    public function modelId(): string;

    public function supports(Capability $capability): bool;
    public function capability(Capability $capability): CapabilitySupport;

    public function assume(array $capabilities): static;
    public function allowUnknownCapabilities(): static;

    public function capabilities(): array;
}
MethodReturnsPurpose
specificationVersion()stringSDK contract version the model was built against ('v1').
provider()stringProvider name string.
modelId()stringModel identifier (e.g. 'gpt-4o').
supports(Capability)boolQuick boolean capability check.
capability(Capability)CapabilitySupportRich check with state, source, and strategy.
assume(array)staticReturn a clone that treats extra capabilities as supported.
allowUnknownCapabilities()staticReturn a clone that passes all capability checks.
capabilities()Capability[]Full list of declared capabilities.

BaseModel: capability resolution

BaseModel provides the full capability resolution pipeline so concrete models only need to declare provider(), modelId(), and capabilities():
use AiSdk\Contracts\BaseModel;
use AiSdk\Contracts\TextModelInterface;
use AiSdk\Capability;

final class AcmeTextModel extends BaseModel implements TextModelInterface
{
    public function __construct(private string $id) {}

    public function provider(): string { return 'acme'; }
    public function modelId(): string  { return $this->id; }

    public function capabilities(): array
    {
        return [
            Capability::TextGeneration,
            Capability::TextInput,
            Capability::Streaming,
        ];
    }

    public function generate(TextModelRequest $request): TextModelResponse { /* … */ }
    public function stream(TextModelRequest $request): Generator           { /* … */ }
}
When supports() or capability() is called, BaseModel checks (in order):
  1. Whether allowUnknownCapabilities is set — if so, every capability is considered supported.
  2. Whether the capability is in the assumedCapabilities list set via assume().
  3. Whether the capability appears in the model’s own capabilities() array.

ModelDefinition: describing a model statically

ModelDefinition is an immutable value object that describes a model without instantiating it. It is used by ModelRegistry and provider catalog files:
use AiSdk\ModelDefinition;
use AiSdk\Capability;

$definition = new ModelDefinition(
    id: 'acme-ultra-v2',
    capabilities: [
        Capability::TextGeneration,
        Capability::TextInput,
        Capability::Streaming,
        Capability::ToolCalling,
    ],
    adaptedCapabilities: [
        'structured_output' => ['strategy' => 'json_mode'],
    ],
    metadata: [
        'status' => 'ga',
        'limits' => ['max_tokens' => 128_000],
    ],
);
adaptedCapabilities holds capabilities that the provider adapter simulates rather than the model supporting natively. The capabilityNames() helper merges both into a flat string array, which is used during capability lookups.

Opting in to capabilities at the call site

When a provider releases a new model before a package update ships, you can tell the SDK to treat additional capabilities as supported using assume():
use AiSdk\Capability;

// The model object doesn't declare ToolCalling yet, but the API supports it.
$model = $provider->textModel('acme-ultra-v3')
    ->assume([Capability::ToolCalling, Capability::StructuredOutput]);

$result = Generate::text()
    ->model($model)
    ->prompt('List the top 3 planets by size.')
    ->run();
assume() returns a clone — the original model object is unchanged. The assumed capabilities appear in capability() calls with the source string 'user-assumed'.

Bypassing all capability checks

For development or when you are certain the provider supports a feature the package does not yet list, allowUnknownCapabilities() makes every supports() call return true:
$model = $provider->textModel('acme-experimental')
    ->allowUnknownCapabilities();
allowUnknownCapabilities() suppresses capability validation entirely. Use it only in controlled environments — a mismatch between what you assume and what the API actually supports will produce a runtime error from the provider rather than a clear SDK exception.
For instructions on registering completely custom models against an existing provider at runtime, see Custom Model Registration.

Build docs developers (and LLMs) love