Laravel AI SDK Documentation

repository·0.x·Indexed 21 days ago

https://github.com/laravel/ai

A unified interface for integrating AI providers like OpenAI, Anthropic, and Gemini into Laravel applications. The SDK supports agentic workflows with tool calling, structured JSON outputs, image generation, audio processing (TTS/STT), vector embeddings, and RAG workflows. It includes features for conversation memory, reranking, vector store management, and a comprehensive suite of testing fakes.

Tokens
11.1K
Snippets
45
Records
50
Agent score
76%

What's inside Laravel AI SDK

  1. Introduction to the Laravel AI SDK

    0.x

    The Laravel AI SDK provides a unified, expressive API for interacting with various AI providers (such as OpenAI, Anthropic, and Gemini) through a consistent, Laravel-friendly interface. It enables developers to implement several AI-driven capabilities within their applications, including:

    • Intelligent Agents: Building agents equipped with tools and capable of producing structured output.
    • Image Generation: Creating images via AI models.
    • Audio Processing: Synthesizing (Text-to-Speech) and transcribing (Speech-to-Text) audio.
    • Vector Embeddings: Creating embeddings for semantic search and RAG (Retrieval-Augmented Generation) workflows.
  2. How to implement an Agent

    0.x

    The primary way to interact with the Laravel AI SDK is through Agents. To create a custom agent, implement the Laravel\Ai\Contracts\Agent interface and use the Laravel\Ai\Promptable trait. This allows you to define custom instructions and use the prompt() method to generate responses.

    You can also use the agent() global helper to create Anonymous Agents for quick, one-off tasks without defining a class.

    use Laravel\Ai\Contracts\Agent;
    use Laravel\Ai\Promptable;
    
    class SalesCoach implements Agent
    {
        use Promptable;
    
        public function instructions(): string
        {
            return 'You are a sales coach.';
        }
    }
    
    // Usage
    $response = (new SalesCoach)->prompt('Analyze this transcript...');
    
    // Anonymous Agent
    use function Laravel\Ai\agent;
    $response = agent(instructions: 'You are a helpful assistant.')->prompt('Hello');
  3. Manage conversation history and memory

    0.x

    The SDK provides two ways to handle conversation context:

    1. Manual Context: Implement the Laravel\Ai\Contracts\Conversational interface. You must define a messages() method that returns an iterable of Laravel\Ai\Messages\Message objects. This gives you full control over how history is retrieved (e.g., from a database).
    2. Automatic Memory: Use the Laravel\Ai\Concerns\RemembersConversations trait alongside the Conversational interface. This automates the persistence of conversation history.

    To use automatic memory:

    • Start a conversation for a user: $agent->forUser($user)->prompt('...').
    • Continue a conversation using the ID: $agent->continue($conversationId, as: $user)->prompt('...').
    use Laravel\Ai\Concerns\RemembersConversations;
    use Laravel\Ai\Contracts\Agent;
    use Laravel\Ai\Contracts\Conversational;
    use Laravel\Ai\Promptable;
    
    class ChatBot implements Agent, Conversational
    {
        use Promptable, RemembersConversations;
    }
    
    // Usage
    $response = (new ChatBot)->forUser($user)->prompt('Hello!');
    $conversationId = $response->conversationId;
    
    $response = (new ChatBot)->continue($conversationId, as: $user)->prompt('More...');
  4. Upgrade to 0.9: Note changes to Agent::fake() behavior

    0.x

    In version 0.9, Agent::fake() responses now run through the real TextGenerationLoop. This makes faked responses more realistic but may affect tests that assert on exact message counts or streamed events:

    • Tool Calls: Faking a tool call for an unregistered tool now throws NoSuchToolException instead of being silently skipped.
    • Message Count: After a faked tool call, $response->messages includes one extra message (the final assistant reply).
    • Streaming Events: Faking an empty string no longer emits TextStart/TextEnd events. Faked tool calls now emit a ToolCall event during streaming.
  5. Upgrade to 0.10: Add approval_state column to messages

    0.x

    The human-in-the-loop tool approval flow now records pause and resolution details in a new nullable TEXT column named approval_state on the conversation messages table.

    If you have already published and run the conversation migrations, you must manually add this column via a new migration.

    return new class extends Migration
    {
        public function up(): void
        {
            Schema::table(config('ai.conversations.tables.messages', 'agent_conversation_messages'), function (Blueprint $table) {
                $table->text('approval_state')->nullable()->after('meta');
            });
        }
    
        public function down(): void
        {
            Schema::table(config('ai.conversations.tables.messages', 'agent_conversation_messages'), function (Blueprint $table) {
                $table->dropColumn('approval_state');
            });
        }
    };
  6. Upgrade to 0.10: Migrate to Polymorphic Conversation Participants

    0.x

    In version 0.10, remembered conversations transitioned from using a user_id to a polymorphic participant system. This allows conversations to be associated with models other than App\/Models\/User.

    Database Migration

    If you have already run previous migrations, you must create a new migration to rename user_id to participant_id and add the participant_type column to both the conversations and messages tables. You must also backfill the participant_type for existing rows using the morph class of your user model.

    Update Custom ConversationStore Implementations

    Custom ConversationStore implementations must update their method signatures to accept ?string $participantType before the $participantId parameter in the following methods:

    • latestConversationId
    • storeConversation
    • storeUserMessage
    • storeAssistantMessage

    Usage Changes

    Use forParticipant($participant) when starting a conversation for a non-user participant. The forUser($user) method is still available as an alias.

    // Example migration logic for polymorphic participants
    Schema::table($conversationsTable, function (Blueprint $table) {
        $table->dropIndex(['user_id', 'updated_at']);
        $table->renameColumn('user_id', 'participant_id');
        $table->string('participant_type')->nullable()->after('id');
    });
    
    $participantType = (new User)->getMorphClass();
    DB::table($conversationsTable)->whereNotNull('participant_id')->update(['participant_type' => $participantType]);
  7. Upgrade to 0.9: Use withProviderOptions instead of providerOptions

    0.x

    In version 0.9, the providerOptions() method was removed from embeddings and transcription builders. Use withProviderOptions() instead.

    Additionally, the signature for withProviderOptions() on provider tools changed. The $provider string argument was removed in favor of an array or a closure that allows varying options per provider.

    // Embeddings/Transcription builders
    Ai::embeddings('...')->withProviderOptions(['dimensions' => 256]);
    
    // Provider tools (using a closure to vary options per provider)
    $tool->withProviderOptions(fn (Lab|string $provider) => match ($provider) {
        Lab::OpenAi => ['key' => 'value'],
        default => [],
    });
  8. Configure Anthropic native structured outputs

    0.x

    As of version 0.9, Anthropic structured outputs use the native output_config.format API by default. If your application relies on the previous synthetic tool-based approach, you can disable native structured outputs in your provider configuration.

    Set use_native_structured_output to false in the anthropic config block.

    'anthropic' => [
        'use_native_structured_output' => false,
    ],
  9. Configure an OpenAI-Compatible Provider

    0.x

    You can point the SDK to any OpenAI-compatible endpoint (like LM Studio, vLLM, or Together) using the openai-compatible driver. This is configured in config/ai.php and does not require code changes to set up the driver itself.

    1. Define the driver in config/ai.php:
    'my-llm' => [
        'driver' => 'openai-compatible',
        'url' => env('MY_LLM_URL'),
        'key' => env('MY_LLM_API_KEY'),
    ],
    1. Reference the config key when prompting:
    agent()->prompt('Hello', provider: 'my-llm', model: 'some-model');

    This driver supports text, streaming, tools, structured output, and image attachments. If you need to pass extra request-body fields, implement the HasProviderOptions interface.

    // In config/ai.php
    'my-llm' => [
        'driver' => 'openai-compatible',
        'url' => env('MY_LLM_URL'),
        'key' => env('MY_LLM_API_KEY'),
    ],
    
    // In your code
    agent()->prompt('Hello', provider: 'my-llm', model: 'some-model');
  10. Avoid common namespace errors in Laravel AI SDK

    0.x

    When importing classes from the Laravel AI SDK, ensure you use the correct namespace. The SDK uses Laravel\Ai, not Illuminate\Ai or Laravel\AI (case-sensitive). Using the wrong namespace will result in class not found errors.

    // 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;
  11. Use Reranking, Files, and Vector Stores

    0.x

    For advanced retrieval and document management:

    • Reranking: Use Laravel\Ai\Reranking::of($documents) to re-order a list of documents based on a query string via ->rerank($query). This returns a collection where you can access the top results via ->first()->document.
    • Files: Use Laravel\Ai\Files\Document::fromPath($path)->put() to upload and store a file with an AI provider.
    • Vector Stores: Use Laravel\Ai\Stores::create($name) to initialize a store. You can add files to a store using $store->add($fileId) or by passing a Document object directly via $store->add(Document::fromStorage('manual.pdf')).
    // Reranking
    $response = Reranking::of(['Doc 1', 'Doc 2'])->limit(5)->rerank('PHP frameworks');
    
    // Files and Stores
    $file = Document::fromPath('/path/to/doc.pdf')->put();
    $store = Stores::create('Knowledge Base');
    $store->add($file->id);
  12. Use Decisions to resume paused Agent runs

    0.x

    In version 0.10, Agent methods such as prompt(), stream(), queue(), broadcast(), broadcastNow(), and broadcastOnQueue() now accept Decisions|string.

    A Decisions instance is used to resume a paused run by providing a map of approval decisions keyed by tool call ID.

    If you implement Laravel\Ai\Contracts\Agent directly, you must update your $prompt parameter type hints to Decisions|string.

    use Laravel\\Ai\\Approvals\Decision;
    use Laravel\\Ai\\Approvals\Decisions;
    
    $agent->prompt(Decisions::from([
        'call_abc' => true,
        'call_def' => Decision::reject('Not permitted.'),
    ]));