Laravel AI SDK Skill — A comprehensive reference and implementation guide for laravel/ai, Laravel's official package for building AI-powered features. Covers the full SDK surface: creating Agents with tools, structured output, and conversation memory; streaming and queued responses with broadcasting; human-in-the-loop tool approval flows; custom and provider-native tools (web search, web fetch, file search, MCP integration); sub-agent delegation; image, audio, and transcription generation; text embeddings with pgvector querying and multimodal support; document reranking; provider file storage and vector stores for RAG; and testing utilities (fake() + assertions) for every SDK class. Organized as a main SKILL.md with four topic-specific reference files (tools, media/embeddings, files/vector stores, testing/events) so only relevant detail loads into context. Supports OpenAI, Anthropic, Gemini, Azure, Bedrock, Groq, xAI, DeepSeek, Mistral, Ollama, OpenRouter, Cohere, ElevenLabs, Jina, VoyageAI, and OpenAI-compatible endpoints.
npx mdskills install /laravel-ai-sdkRelated
Reference and implementation guide for laravel/ai, Laravel's official package for interacting with AI
providers (OpenAI, Anthropic, Gemini, Azure, Bedrock, Groq, xAI, DeepSeek, Mistral, Ollama, OpenRouter,
Cohere, ElevenLabs, Jina, VoyageAI, and OpenAI-compatible endpoints).
This SKILL.md covers installation, configuration, and the core Agent workflow (the most common use case). For other features, read the matching reference file before writing code — each is self-contained and includes full working code samples:
| Reference file | Covers |
|---|---|
references/tools.md | Custom tools, SimilaritySearch, ToolSearch (deferred loading), FileStorage, MCP tools, provider tools (WebSearch, WebFetch, FileSearch), sub-agents, human tool approval flow |
references/media-embeddings.md | Image, Audio, Transcription, Str::summarize(), Embeddings (incl. multimodal), pgvector querying, Reranking |
references/files-vectorstores.md | Storing files with providers, referencing stored files in prompts, Vector Stores (RAG) |
references/testing-events.md | fake() + assertions for every SDK class, preventStray*(), and the full list of dispatched events |
Read the relevant file(s) fully before implementing — don't guess at method signatures.
composer require laravel/ai
php artisan vendor:publish --provider="Laravel\Ai\AiServiceProvider"
php artisan migrate
The migration creates agent_conversations and agent_conversation_messages tables, used for
conversation persistence (RemembersConversations trait) and human tool approval flows.
config/ai.php + .env)Provider credentials go in .env:
ANTHROPIC_API_KEY=
OPENAI_API_KEY=
GEMINI_API_KEY=
AZURE_OPENAI_API_KEY=
GROQ_API_KEY=
DEEPSEEK_API_KEY=
MISTRAL_API_KEY=
OLLAMA_API_KEY=
OPENROUTER_API_KEY=
COHERE_API_KEY=
ELEVENLABS_API_KEY=
JINA_API_KEY=
VOYAGEAI_API_KEY=
XAI_API_KEY=
OPENAI_COMPATIBLE_API_KEY=
OPENAI_COMPATIBLE_URL=
Default models per feature (text/images/audio/transcription/embeddings) are set in config/ai.php.
Supported for OpenAI, Anthropic, Gemini, Groq, Cohere, DeepSeek, xAI, OpenRouter:
'anthropic' => [
'driver' => 'anthropic',
'key' => env('ANTHROPIC_API_KEY'),
'url' => env('ANTHROPIC_BASE_URL'), // e.g. LiteLLM or a corporate gateway
],
'local' => [
'driver' => 'openai-compatible',
'url' => env('LOCAL_AI_URL'), // required
'key' => env('LOCAL_AI_API_KEY'), // optional, sent as bearer token
'headers' => ['X-Tenant-Id' => env('LOCAL_AI_TENANT_ID')], // optional
'models' => [
'text' => ['default' => env('LOCAL_AI_MODEL')],
'embeddings' => ['default' => 'text-embedding-qwen3-embedding-0.6b', 'dimensions' => 1024],
'transcription' => ['default' => 'whisper-1'],
],
],
Use it like any other provider: agent()->prompt('...', provider: 'local', model: 'local-model').
Supports text, streaming, tools, structured output, image attachments, embeddings, transcription (not
diarization — neither openai-compatible nor groq support diarize()).
| Feature | Providers |
|---|---|
| Text | OpenAI, OpenAI Compatible, Anthropic, Gemini, Azure, Bedrock, Groq, xAI, DeepSeek, Mistral, Ollama, OpenRouter |
| Images | OpenAI, Gemini, xAI, Azure, Bedrock, OpenRouter |
| TTS | OpenAI, ElevenLabs, Gemini |
| STT | OpenAI, OpenAI Compatible, ElevenLabs, Groq, Mistral, Gemini |
| Embeddings | OpenAI, OpenAI Compatible, Gemini, Azure, Bedrock, Cohere, Mistral, Jina, VoyageAI, Ollama, OpenRouter |
| Reranking | Cohere, Jina, VoyageAI |
| Files | OpenAI, Anthropic, Gemini, Azure |
Use Laravel\Ai\Enums\Lab instead of plain strings when referencing providers in code (Lab::Anthropic,
Lab::OpenAI, Lab::Gemini, etc.).
An agent is a PHP class that encapsulates instructions, conversation context, tools, and output schema. Generate one with:
php artisan make:agent SalesCoach
php artisan make:agent SalesCoach --structured # scaffolds HasStructuredOutput too
user->id)
->latest()->limit(50)->get()->reverse()
->map(fn (m)=>newMessage(m->role, $m->content))->all();
}
public function tools(): iterable
{
return [new RetrievePreviousTranscripts];
}
public function schema(JsonSchema $schema): array
{
return [
'feedback' => $schema->string()->required(),
'score' => $schema->integer()->min(1)->max(10)->required(),
];
}
}
$response = (new SalesCoach)->prompt('Analyze this sales transcript...');
return (string) $response;
// or resolve via container with constructor args
$agent = SalesCoach::make(user: $user);
// override provider/model/timeout per call
$response = (new SalesCoach)->prompt(
'Analyze this sales transcript...',
provider: Lab::Anthropic,
model: 'claude-sonnet-5',
timeout: 120,
);
Every text response exposes the raw provider HTTP response via $response->raw (null when streaming, on
Bedrock, or on unconfigured fakes). Each tool-call step keeps its own raw response too:
foreach ($response->steps as $step) { $step->raw?->header(...); }.
Simplest option — add the trait, don't define messages() yourself (it takes precedence and disables the
trait if present):
class SalesCoach implements Agent, Conversational
{
use Promptable, RemembersConversations;
public function instructions(): string { return 'You are a sales coach...'; }
}
response=(newSalesCoach)->forUser(user)->prompt('Hello!');
$conversationId = $response->conversationId;
// later
response=(newSalesCoach)->continue(conversationId, as: $user)->prompt('Tell me more.');
Add HasConversations to a model to query user->conversations().UseforParticipant(model) /
continueLastConversation($model) for non-user participants (e.g. Team) — forUser is just an alias.
continue() does not verify the participant owns the conversation — authorize access yourself.
Implement HasStructuredOutput + schema(JsonSchema $schema). Access the response like an array:
response['score'].Supportsnestedobject(fn(schema) => [...]), array()->items(...), and
anyOf([...]) for polymorphic fields. See references/media-embeddings.md for embeddings-adjacent
patterns and references/testing-events.md for faking structured responses.
use Laravel\Ai\Files;
$response = (new SalesCoach)->prompt('Analyze the attached transcript...', attachments: [
Files\Document::fromStorage('transcript.pdf'),
Files\Document::fromPath('/home/laravel/transcript.md'),
$request->file('transcript'),
]);
// Files\Image::fromStorage()/fromPath() for images
Route::get('/coach', fn () => (new SalesCoach)->stream('Analyze this sales transcript...'));
// react when done
(new SalesCoach)->stream('...')->then(function (StreamedAgentResponse $response) {
// $response->text, $response->events, $response->usage
});
// or iterate manually
foreach ((new SalesCoach)->stream('...') as $event) { /* ... */ }
// Vercel AI SDK protocol
(new SalesCoach)->stream('...')->usingVercelDataProtocol();
foreach ((new SalesCoach)->stream('...') as $event) {
$event->broadcast(new Channel('channel-name'));
}
// or queue + broadcast as events arrive
(new SalesCoach)->broadcastOnQueue('...', new Channel('channel-name'));
Exclude oversized events (e.g. large tool results, >~10KB WebSocket limits) from broadcast while still persisting them to the DB:
#[WithoutBroadcasting(ToolCall::class, ToolResult::class)]
class SearchAgent implements Agent, HasTools { use Promptable; }
(new SalesCoach)->queue($transcript)
->then(fn (AgentResponse $response) => /* ... */)
->catch(fn (Throwable $e) => /* ... */);
Covered in references/tools.md (sub-agents) — a short summary:
php artisan make:agent-middleware Name, implement HasMiddleware, handle(AgentPrompt $prompt, Closure next).Canwrapnext($prompt)->then(...) to run logic after generation.agent(instructions: '...', messages: [], tools: [])->prompt('...') for ad-hoc use without a dedicated class; supports schema: too.#[Provider(Lab::Anthropic)]
#[Model('claude-sonnet-5')]
#[MaxSteps(10)]
#[MaxTokens(4096)]
#[Temperature(0.7)]
#[Timeout(120)]
#[TopP(0.9)]
class SalesCoach implements Agent { use Promptable; }
#[UseCheapestModel] / #[UseSmartestModel] auto-select a model without naming one — note the actual
model may change between SDK releases, so use #[Model(...)] explicitly if you need pricing/behavior
stability.
class SalesCoach implements Agent, HasProviderOptions
{
use Promptable;
public function providerOptions(Lab|string $provider): array
{
return match ($provider) {
Lab::OpenAI => ['reasoning' => ['effort' => 'low'], 'frequency_penalty' => 0.5],
Lab::Anthropic => ['thinking' => ['budget_tokens' => 1024], 'cache_control' => ['type' => 'ephemeral']],
default => [],
};
}
}
$response = (new SalesCoach)->prompt('...', provider: [Lab::OpenAI, Lab::Anthropic]);
// per-provider model (must key by ->value since enums can't be array keys)
$response = (new SalesCoach)->prompt('...', provider: [
Lab::Gemini->value => 'gemini-3-flash-preview',
Lab::DeepSeek->value => 'deepseek-v4-pro',
]);
Only triggers on RateLimitedException, ProviderOverloadedException, InsufficientCreditsException —
not on validation/bad-request errors.
references/tools.mdreferences/media-embeddings.mdreferences/files-vectorstores.mdreferences/testing-events.mdAlways check the feature/provider support matrix above before implementing — not every provider supports
every feature (e.g., only Anthropic/Gemini/OpenRouter support WebFetch; only OpenAI/Gemini/xAI support
FileSearch).
Install via CLI
npx mdskills install /laravel-ai-sdkLaravel Ai sdk is a free, open-source AI agent skill. Laravel AI SDK Skill — A comprehensive reference and implementation guide for laravel/ai, Laravel's official package for building AI-powered features. Covers the full SDK surface: creating Agents with tools, structured output, and conversation memory; streaming and queued responses with broadcasting; human-in-the-loop tool approval flows; custom and provider-native tools (web search, web fetch, file search, MCP integration); sub-agent delegation; image, audio, and transcription generation; text embeddings with pgvector querying and multimodal support; document reranking; provider file storage and vector stores for RAG; and testing utilities (fake() + assertions) for every SDK class. Organized as a main SKILL.md with four topic-specific reference files (tools, media/embeddings, files/vector stores, testing/events) so only relevant detail loads into context. Supports OpenAI, Anthropic, Gemini, Azure, Bedrock, Groq, xAI, DeepSeek, Mistral, Ollama, OpenRouter, Cohere, ElevenLabs, Jina, VoyageAI, and OpenAI-compatible endpoints.
Install Laravel Ai sdk with a single command:
npx mdskills install /laravel-ai-sdkThis downloads the skill files into your project and your AI agent picks them up automatically.
Laravel Ai sdk works with Claude Code, Claude Desktop, Cursor, Vscode Copilot, Windsurf, Continue Dev, Codex, Gemini Cli, Amp, Roo Code, Goose, Opencode, Trae, Qodo, Command Code. Skills use the open SKILL.md format which is compatible with any AI coding agent that reads markdown instructions.