resources/boost/skills/ai-sdk-development/SKILL.md
TRIGGER when working with ai-sdk which is Laravel official first-party AI SDK. Activate when building, editing AI agents, chatbots, text generation, image generation, audio/TTS, transcription/STT, embeddings, RAG, vector stores, reranking, structured output, streaming, conversation memory, tools, queueing, broadcasting, and provider failover across OpenAI, Anthropic, Gemini, Azure, Groq, xAI, DeepSeek, Mistral, Ollama, ElevenLabs, Cohere, Jina, and VoyageAI. Invoke when the user references ai-sdk, the `Laravel\Ai\` namespace, or this project's AI features — not for other AI packages used directly.
npx skillsauth add laravel/ai ai-sdk-developmentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The Laravel AI SDK (laravel/ai) is the official AI package for Laravel, providing a unified API for agents, images, audio, transcription, embeddings, reranking, vector stores, and file management across multiple AI providers.
This package is new. Always search the documentation before implementing any feature. Never guess at APIs — the documentation is the single source of truth.
test agent fake, not laravel ai test agent fake.Use these section headings as query terms for accurate results:
Determine the right entry point before writing code:
Text generation or chat? → Agent class with Promptable trait
Chat with conversation history? → Agent + Conversational interface (manual) or RemembersConversations trait (automatic)
Structured JSON output? → Agent + HasStructuredOutput interface
Image generation? → Image::of()->generate()
Audio synthesis? → Audio::of()->generate()
Transcription? → Transcription::fromPath()->generate()
Embeddings? → Embeddings::for()->generate()
Reranking? → Reranking::of()->rerank()
File storage? → Document::fromPath()->put()
Vector stores? → Stores::create()
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Enums\Lab;
use Laravel\Ai\Promptable;
class SalesCoach implements Agent
{
use Promptable;
public function instructions(): string
{
return 'You are a sales coach.';
}
}
// Prompting
$response = (new SalesCoach)->prompt('Analyze this transcript...');
echo $response->text;
// Container resolution with dependency injection
$agent = SalesCoach::make(user: $user);
// Override provider, model, or timeout per-prompt
$response = (new SalesCoach)->prompt(
'Analyze this transcript...',
provider: Lab::Anthropic,
model: 'claude-haiku-4-5-20251001',
timeout: 120,
);
// Streaming (returns SSE response from a route)
return (new SalesCoach)->stream('Analyze this transcript...');
// Queueing
(new SalesCoach)->queue('Analyze this transcript...')
->then(fn ($response) => /* ... */);
// Anonymous agents
use function Laravel\Ai\{agent};
$response = agent(instructions: 'You are a helpful assistant.')->prompt('Hello');
Manual conversation history via the Conversational interface:
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\Conversational;
use Laravel\Ai\Messages\Message;
use Laravel\Ai\Promptable;
class SalesCoach implements Agent, Conversational
{
use Promptable;
public function __construct(public User $user) {}
public function instructions(): string { return 'You are a sales coach.'; }
public function messages(): iterable
{
return History::where('user_id', $this->user->id)
->latest()->limit(50)->get()->reverse()
->map(fn ($m) => new Message($m->role, $m->content))
->all();
}
}
Automatic conversation persistence via the RemembersConversations trait:
use Laravel\Ai\Concerns\RemembersConversations;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\Conversational;
use Laravel\Ai\Promptable;
class SalesCoach implements Agent, Conversational
{
use Promptable, RemembersConversations;
public function instructions(): string { return 'You are a sales coach.'; }
}
// Start a new conversation
$response = (new SalesCoach)->forUser($user)->prompt('Hello!');
$conversationId = $response->conversationId;
// Continue an existing conversation
$response = (new SalesCoach)->continue($conversationId, as: $user)->prompt('Tell me more.');
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasStructuredOutput;
use Laravel\Ai\Promptable;
class Reviewer implements Agent, HasStructuredOutput
{
use Promptable;
public function instructions(): string { return 'Review and score content.'; }
public function schema(JsonSchema $schema): array
{
return [
'feedback' => $schema->string()->required(),
'score' => $schema->integer()->min(1)->max(10)->required(),
];
}
}
$response = (new Reviewer)->prompt('Review this...');
echo $response['score']; // Access like an array
use Laravel\Ai\Image;
$image = Image::of('A sunset over mountains')
->landscape()
->quality('high')
->generate();
$path = $image->store(); // Store to default disk
use Laravel\Ai\Audio;
$audio = Audio::of('Hello from Laravel.')
->female()
->instructions('Speak warmly')
->generate();
$path = $audio->store();
use Laravel\Ai\Transcription;
$transcript = Transcription::fromStorage('audio.mp3')
->diarize()
->generate();
echo (string) $transcript;
use Laravel\Ai\Embeddings;
use Illuminate\Support\Str;
$response = Embeddings::for(['Text one', 'Text two'])
->dimensions(1536)
->cache()
->generate();
// Single string via Stringable
$embedding = Str::of('Napa Valley has great wine.')->toEmbeddings();
use Laravel\Ai\Reranking;
$response = Reranking::of(['Django is Python.', 'Laravel is PHP.', 'React is JS.'])
->limit(5)
->rerank('PHP frameworks');
$response->first()->document; // "Laravel is PHP."
use Laravel\Ai\Files\Document;
use Laravel\Ai\Stores;
// Store a file with the provider
$file = Document::fromPath('/path/to/doc.pdf')->put();
// Create a vector store and add files
$store = Stores::create('Knowledge Base');
$store->add($file->id);
$store->add(Document::fromStorage('manual.pdf')); // Store + add in one step
use Laravel\Ai\Attributes\{Provider, Model, MaxSteps, MaxTokens, Temperature, Timeout};
use Laravel\Ai\Enums\Lab;
#[Provider(Lab::Anthropic)]
#[Model('claude-haiku-4-5-20251001')]
#[MaxSteps(10)]
#[MaxTokens(4096)]
#[Temperature(0.7)]
#[Timeout(120)]
class MyAgent implements Agent
{
use Promptable;
// ...
}
The #[UseCheapestModel] and #[UseSmartestModel] attributes are also available for automatic model selection.
Implement the HasTools interface and scaffold tools with php artisan make:tool:
use Laravel\Ai\Contracts\HasTools;
class MyAgent implements Agent, HasTools
{
use Promptable;
public function tools(): iterable
{
return [new MyCustomTool];
}
}
use Laravel\Ai\Providers\Tools\{WebSearch, WebFetch, FileSearch};
public function tools(): iterable
{
return [
(new WebSearch)->max(5)->allow(['laravel.com']),
new WebFetch,
new FileSearch(stores: ['store_id']),
];
}
use Laravel\Ai\Concerns\RemembersConversations;
use Laravel\Ai\Contracts\Conversational;
class ChatBot implements Agent, Conversational
{
use Promptable, RemembersConversations;
// ...
}
$response = (new ChatBot)->forUser($user)->prompt('Hello!');
$response = (new ChatBot)->continue($conversationId, as: $user)->prompt('More...');
$response = (new MyAgent)->prompt('Hello', provider: [Lab::OpenAI, Lab::Anthropic]);
Each capability supports fake() with assertions:
use App\Ai\Agents\SalesCoach;
use Laravel\Ai\{Image, Audio, Transcription, Embeddings, Reranking, Files, Stores};
// Agents
SalesCoach::fake(['Response 1', 'Response 2']);
SalesCoach::assertPrompted('query');
SalesCoach::assertNotPrompted('query');
SalesCoach::assertNeverPrompted();
SalesCoach::fake()->preventStrayPrompts();
// Images
Image::fake();
Image::assertGenerated(fn ($prompt) => $prompt->contains('sunset'));
Image::assertNothingGenerated();
// Audio
Audio::fake();
Audio::assertGenerated(fn ($prompt) => $prompt->contains('Hello'));
// Transcription
Transcription::fake(['Transcribed text.']);
Transcription::assertGenerated(fn ($prompt) => $prompt->isDiarized());
// Embeddings
Embeddings::fake();
Embeddings::assertGenerated(fn ($prompt) => $prompt->contains('Laravel'));
// Reranking
Reranking::fake();
Reranking::assertReranked(fn ($prompt) => $prompt->contains('PHP'));
// Files
Files::fake();
Files::assertStored(fn ($file) => $file->mimeType() === 'text/plain');
// Stores
Stores::fake();
Stores::assertCreated('Knowledge Base');
$store = Stores::get('id');
$store->assertAdded('file_id');
Laravel\Ai\composer require laravel/aiAgent interface and use the Promptable traitHasTools, HasMiddleware, HasStructuredOutput, ConversationalImage, Audio, Transcription, Embeddings, Reranking, StoresLaravel\Ai\Enums\Lab (prefer over plain strings)php artisan make:agent, php artisan make:toolagent() for anonymous agentsThe namespace is Laravel\Ai, not Illuminate\Ai or Laravel\AI.
// Correct
use Laravel\Ai\Image;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Promptable;
// Wrong — these do not exist
use Illuminate\Ai\Image;
use Laravel\AI\Agent;
Calling a capability not supported by a provider throws a LogicException. Refer to the provider support table below.
| Feature | Providers | | ---------- | --------------------------------------------------------------- | | Text | OpenAI, Anthropic, Gemini, Azure, Groq, xAI, DeepSeek, Mistral, Ollama | | Images | OpenAI, Gemini, xAI | | TTS | OpenAI, ElevenLabs | | STT | OpenAI, ElevenLabs, Mistral | | Embeddings | OpenAI, Gemini, Azure, Cohere, Mistral, Jina, VoyageAI | | Reranking | Cohere, Jina | | Files | OpenAI, Anthropic, Gemini |
Use the Laravel\Ai\Enums\Lab enum to reference providers in code instead of plain strings:
use Laravel\Ai\Enums\Lab;
Lab::Anthropic;
Lab::OpenAI;
Lab::Gemini;
// ...
tools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
A CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.