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
1---2name: laravel-ai-sdk3description: Build AI-powered features in Laravel applications using the official Laravel AI SDK (laravel/ai) — agents, tools, structured output, streaming, tool approval, image/audio/transcription generation, embeddings, vector stores, reranking, and testing. Use this skill whenever the user is working in a Laravel/PHP codebase and wants to integrate OpenAI, Anthropic, Gemini, or other AI providers; build chatbots or AI agents; add RAG/similarity search; generate images, audio, or transcripts; create vector embeddings; or asks about `laravel/ai`, `make:agent`, `make:tool`, or similar. Also use when reviewing, debugging, or extending existing Laravel AI SDK code (agent classes, tool classes, middleware). Do NOT use for non-Laravel PHP AI integrations or for the generic Anthropic API outside a Laravel context.4---56# Laravel AI SDK78Reference and implementation guide for `laravel/ai`, Laravel's official package for interacting with AI9providers (OpenAI, Anthropic, Gemini, Azure, Bedrock, Groq, xAI, DeepSeek, Mistral, Ollama, OpenRouter,10Cohere, ElevenLabs, Jina, VoyageAI, and OpenAI-compatible endpoints).1112## When to consult which reference file1314This SKILL.md covers installation, configuration, and the core **Agent** workflow (the most common use15case). For other features, read the matching reference file before writing code — each is self-contained16and includes full working code samples:1718| Reference file | Covers |19|---|---|20| `references/tools.md` | Custom tools, `SimilaritySearch`, `ToolSearch` (deferred loading), `FileStorage`, MCP tools, provider tools (`WebSearch`, `WebFetch`, `FileSearch`), sub-agents, human tool approval flow |21| `references/media-embeddings.md` | `Image`, `Audio`, `Transcription`, `Str::summarize()`, `Embeddings` (incl. multimodal), pgvector querying, `Reranking` |22| `references/files-vectorstores.md` | Storing files with providers, referencing stored files in prompts, Vector Stores (RAG) |23| `references/testing-events.md` | `fake()` + assertions for every SDK class, `preventStray*()`, and the full list of dispatched events |2425Read the relevant file(s) fully before implementing — don't guess at method signatures.2627## Installation2829```bash30composer require laravel/ai31php artisan vendor:publish --provider="Laravel\Ai\AiServiceProvider"32php artisan migrate33```3435The migration creates `agent_conversations` and `agent_conversation_messages` tables, used for36conversation persistence (`RemembersConversations` trait) and human tool approval flows.3738## Configuration (`config/ai.php` + `.env`)3940Provider credentials go in `.env`:4142```43ANTHROPIC_API_KEY=44OPENAI_API_KEY=45GEMINI_API_KEY=46AZURE_OPENAI_API_KEY=47GROQ_API_KEY=48DEEPSEEK_API_KEY=49MISTRAL_API_KEY=50OLLAMA_API_KEY=51OPENROUTER_API_KEY=52COHERE_API_KEY=53ELEVENLABS_API_KEY=54JINA_API_KEY=55VOYAGEAI_API_KEY=56XAI_API_KEY=57OPENAI_COMPATIBLE_API_KEY=58OPENAI_COMPATIBLE_URL=59```6061Default models per feature (text/images/audio/transcription/embeddings) are set in `config/ai.php`.6263### Custom base URLs (proxies/gateways)6465Supported for OpenAI, Anthropic, Gemini, Groq, Cohere, DeepSeek, xAI, OpenRouter:6667```php68'anthropic' => [69 'driver' => 'anthropic',70 'key' => env('ANTHROPIC_API_KEY'),71 'url' => env('ANTHROPIC_BASE_URL'), // e.g. LiteLLM or a corporate gateway72],73```7475### OpenAI-compatible providers (LM Studio, vLLM, Together, Fireworks, local models)7677```php78'local' => [79 'driver' => 'openai-compatible',80 'url' => env('LOCAL_AI_URL'), // required81 'key' => env('LOCAL_AI_API_KEY'), // optional, sent as bearer token82 'headers' => ['X-Tenant-Id' => env('LOCAL_AI_TENANT_ID')], // optional83 'models' => [84 'text' => ['default' => env('LOCAL_AI_MODEL')],85 'embeddings' => ['default' => 'text-embedding-qwen3-embedding-0.6b', 'dimensions' => 1024],86 'transcription' => ['default' => 'whisper-1'],87 ],88],89```9091Use it like any other provider: `agent()->prompt('...', provider: 'local', model: 'local-model')`.92Supports text, streaming, tools, structured output, image attachments, embeddings, transcription (not93diarization — neither `openai-compatible` nor `groq` support `diarize()`).9495### Feature/provider support matrix9697| Feature | Providers |98|---|---|99| Text | OpenAI, OpenAI Compatible, Anthropic, Gemini, Azure, Bedrock, Groq, xAI, DeepSeek, Mistral, Ollama, OpenRouter |100| Images | OpenAI, Gemini, xAI, Azure, Bedrock, OpenRouter |101| TTS | OpenAI, ElevenLabs, Gemini |102| STT | OpenAI, OpenAI Compatible, ElevenLabs, Groq, Mistral, Gemini |103| Embeddings | OpenAI, OpenAI Compatible, Gemini, Azure, Bedrock, Cohere, Mistral, Jina, VoyageAI, Ollama, OpenRouter |104| Reranking | Cohere, Jina, VoyageAI |105| Files | OpenAI, Anthropic, Gemini, Azure |106107Use `Laravel\Ai\Enums\Lab` instead of plain strings when referencing providers in code (`Lab::Anthropic`,108`Lab::OpenAI`, `Lab::Gemini`, etc.).109110## Agents — the core building block111112An agent is a PHP class that encapsulates instructions, conversation context, tools, and output schema.113Generate one with:114115```bash116php artisan make:agent SalesCoach117php artisan make:agent SalesCoach --structured # scaffolds HasStructuredOutput too118```119120```php121<?php122123namespace App\Ai\Agents;124125use App\Ai\Tools\RetrievePreviousTranscripts;126use App\Models\History;127use App\Models\User;128use Illuminate\Contracts\JsonSchema\JsonSchema;129use Laravel\Ai\Contracts\Agent;130use Laravel\Ai\Contracts\Conversational;131use Laravel\Ai\Contracts\HasStructuredOutput;132use Laravel\Ai\Contracts\HasTools;133use Laravel\Ai\Messages\Message;134use Laravel\Ai\Promptable;135use Stringable;136137class SalesCoach implements Agent, Conversational, HasTools, HasStructuredOutput138{139 use Promptable;140141 public function __construct(public User $user) {}142143 public function instructions(): Stringable|string144 {145 return 'You are a sales coach, analyzing transcripts and providing feedback and an overall sales strength score.';146 }147148 public function messages(): iterable149 {150 return History::where('user_id', $this->user->id)151 ->latest()->limit(50)->get()->reverse()152 ->map(fn (m)=>newMessage(m->role, $m->content))->all();153 }154155 public function tools(): iterable156 {157 return [new RetrievePreviousTranscripts];158 }159160 public function schema(JsonSchema $schema): array161 {162 return [163 'feedback' => $schema->string()->required(),164 'score' => $schema->integer()->min(1)->max(10)->required(),165 ];166 }167}168```169170### Prompting171172```php173$response = (new SalesCoach)->prompt('Analyze this sales transcript...');174return (string) $response;175176// or resolve via container with constructor args177$agent = SalesCoach::make(user: $user);178179// override provider/model/timeout per call180$response = (new SalesCoach)->prompt(181 'Analyze this sales transcript...',182 provider: Lab::Anthropic,183 model: 'claude-sonnet-5',184 timeout: 120,185);186```187188Every text response exposes the raw provider HTTP response via `$response->raw` (null when streaming, on189Bedrock, or on unconfigured fakes). Each tool-call step keeps its own raw response too:190`foreach ($response->steps as $step) { $step->raw?->header(...); }`.191192### Conversation memory193194Simplest option — add the trait, don't define `messages()` yourself (it takes precedence and disables the195trait if present):196197```php198class SalesCoach implements Agent, Conversational199{200 use Promptable, RemembersConversations;201202 public function instructions(): string { return 'You are a sales coach...'; }203}204205response=(newSalesCoach)->forUser(user)->prompt('Hello!');206$conversationId = $response->conversationId;207208// later209response=(newSalesCoach)->continue(conversationId, as: $user)->prompt('Tell me more.');210```211212Add `HasConversations` to a model to query `user->conversations()`.Use`forParticipant(model)` /213`continueLastConversation($model)` for non-user participants (e.g. `Team`) — `forUser` is just an alias.214**`continue()` does not verify the participant owns the conversation** — authorize access yourself.215216### Structured output217218Implement `HasStructuredOutput` + `schema(JsonSchema $schema)`. Access the response like an array:219`response['score']`.Supportsnested`object(fn(schema) => [...])`, `array()->items(...)`, and220`anyOf([...])` for polymorphic fields. See `references/media-embeddings.md` for embeddings-adjacent221patterns and `references/testing-events.md` for faking structured responses.222223### Attachments224225```php226use Laravel\Ai\Files;227228$response = (new SalesCoach)->prompt('Analyze the attached transcript...', attachments: [229 Files\Document::fromStorage('transcript.pdf'),230 Files\Document::fromPath('/home/laravel/transcript.md'),231 $request->file('transcript'),232]);233// Files\Image::fromStorage()/fromPath() for images234```235236### Streaming237238```php239Route::get('/coach', fn () => (new SalesCoach)->stream('Analyze this sales transcript...'));240241// react when done242(new SalesCoach)->stream('...')->then(function (StreamedAgentResponse $response) {243 // $response->text, $response->events, $response->usage244});245246// or iterate manually247foreach ((new SalesCoach)->stream('...') as $event) { /* ... */ }248249// Vercel AI SDK protocol250(new SalesCoach)->stream('...')->usingVercelDataProtocol();251```252253### Broadcasting254255```php256foreach ((new SalesCoach)->stream('...') as $event) {257 $event->broadcast(new Channel('channel-name'));258}259// or queue + broadcast as events arrive260(new SalesCoach)->broadcastOnQueue('...', new Channel('channel-name'));261```262263Exclude oversized events (e.g. large tool results, >~10KB WebSocket limits) from broadcast while still264persisting them to the DB:265266```php267#[WithoutBroadcasting(ToolCall::class, ToolResult::class)]268class SearchAgent implements Agent, HasTools { use Promptable; }269```270271### Queueing272273```php274(new SalesCoach)->queue($transcript)275 ->then(fn (AgentResponse $response) => /* ... */)276 ->catch(fn (Throwable $e) => /* ... */);277```278279### Sub-agents, middleware, anonymous agents280281Covered in `references/tools.md` (sub-agents) — a short summary:282283- **Middleware**: `php artisan make:agent-middleware Name`, implement `HasMiddleware`, `handle(AgentPrompt $prompt, Closure next)`.Canwrap`next($prompt)->then(...)` to run logic after generation.284- **Anonymous agents**: `agent(instructions: '...', messages: [], tools: [])->prompt('...')` for ad-hoc use without a dedicated class; supports `schema:` too.285286### Agent configuration attributes287288```php289#[Provider(Lab::Anthropic)]290#[Model('claude-sonnet-5')]291#[MaxSteps(10)]292#[MaxTokens(4096)]293#[Temperature(0.7)]294#[Timeout(120)]295#[TopP(0.9)]296class SalesCoach implements Agent { use Promptable; }297```298299`#[UseCheapestModel]` / `#[UseSmartestModel]` auto-select a model without naming one — note the actual300model may change between SDK releases, so use `#[Model(...)]` explicitly if you need pricing/behavior301stability.302303### Provider options (per-provider extras)304305```php306class SalesCoach implements Agent, HasProviderOptions307{308 use Promptable;309310 public function providerOptions(Lab|string $provider): array311 {312 return match ($provider) {313 Lab::OpenAI => ['reasoning' => ['effort' => 'low'], 'frequency_penalty' => 0.5],314 Lab::Anthropic => ['thinking' => ['budget_tokens' => 1024], 'cache_control' => ['type' => 'ephemeral']],315 default => [],316 };317 }318}319```320321### Failover322323```php324$response = (new SalesCoach)->prompt('...', provider: [Lab::OpenAI, Lab::Anthropic]);325326// per-provider model (must key by ->value since enums can't be array keys)327$response = (new SalesCoach)->prompt('...', provider: [328 Lab::Gemini->value => 'gemini-3-flash-preview',329 Lab::DeepSeek->value => 'deepseek-v4-pro',330]);331```332333Only triggers on `RateLimitedException`, `ProviderOverloadedException`, `InsufficientCreditsException` —334not on validation/bad-request errors.335336## Quick decision guide337338- Need the agent to **use tools, call APIs, search docs, or take approvable actions** → `references/tools.md`339- Need to **generate images/audio/transcripts, summarize text, or build RAG with embeddings** → `references/media-embeddings.md`340- Need to **persist files with a provider or build a searchable vector store** → `references/files-vectorstores.md`341- Writing **tests** for any AI feature, or want to **hook lifecycle events** → `references/testing-events.md`342343Always check the feature/provider support matrix above before implementing — not every provider supports344every feature (e.g., only Anthropic/Gemini/OpenRouter support `WebFetch`; only OpenAI/Gemini/xAI support345`FileSearch`).346347
Full transparency — inspect the skill content before installing.