Laravel Daily's

Build a Streaming Chat API with Laravel AI SDK and Claude: A Production Guide

hero image

Static responses are no longer enough for modern AI applications. Users expect the typewriter effect: the immediate, rhythmic flow of tokens as they are generated.

Laravel provides a first-class developer experience for this through the Laravel AI SDK. By combining our php web framework with Anthropic’s Claude 3.5 Sonnet, you can ship production-ready streaming interfaces in minutes.

This guide covers building a robust, streaming chat endpoint using the official SDK.

Configuration: Setting the Anthropic Driver

The Laravel AI SDK uses a provider-based architecture. You manage your credentials and model defaults within the config/ai.php file. This centralizes your php developer tools configuration.

First, ensure your .env contains your Anthropic API key:

ANTHROPIC_API_KEY=sk-ant-xxx

Next, define the provider in config/ai.php:

return [
    'default' => 'anthropic',

    'providers' => [
        'anthropic' => [
            'driver' => 'anthropic',
            'api_key' => env('ANTHROPIC_API_KEY'),
            'default_model' => 'claude-3-5-sonnet-latest',
        ],
    ],
];

This setup allows the framework to inject the correct client whenever you resolve an agent.

The Agent: Defining Logic with Attributes

Conceptual flow of streaming data between Laravel and Claude

Agents are the heart of the Laravel AI SDK. They encapsulate system prompts, model choice, and available tools. Using PHP 8 attributes makes these definitions clean and declarative.

Generate your agent using the Artisan command:

php artisan make:ai-agent SupportAgent

Apply the #[Agent] attribute to define its identity. Use the #[Tool] attribute to give Claude the ability to perform actions, like checking order statuses or querying a database.

namespace App\Ai\Agents;

use Laravel\Ai\Attributes\Agent;
use Laravel\Ai\Attributes\Tool;

#[Agent(
    prompt: 'You are a helpful customer support assistant for a high-end furniture brand.',
    model: 'claude-3-5-sonnet-latest'
)]
class SupportAgent
{
    #[Tool(description: 'Retrieve the status of a specific order.')]
    public function getOrderStatus(string $orderId): string
    {
        // Query your database
        return "Order {$orderId} is currently out for delivery.";
    }
}

This approach keeps your business logic separate from your AI orchestration.

Streaming: Building the API Endpoint

To build rest api with php that supports streaming, you must use Server-Sent Events (SSE). The Laravel AI SDK simplifies this with the stream() method.

Return the stream directly from your controller. The framework handles the necessary headers, including Content-Type: text/event-stream.

namespace App\Http\Controllers;

use App\Ai\Agents\SupportAgent;
use Illuminate\Http\Request;
use Laravel\Ai\Facades\Ai;

class ChatController extends Controller
{
    public function __invoke(Request $request)
    {
        $message = $request->input('message');

        return Ai::agent(SupportAgent::class)
            ->stream($message);
    }
}

The stream() method returns a StreamableAgentResponse. It manages the chunking of Claude’s response and pushes events to the client in real-time.

Handling Events: TextDelta and ToolCalls

A Laravel toolbox showing tools and functions being used by AI

During a stream, the SDK emits specific event types. Your frontend or intermediate logic needs to handle these.

  1. TextDelta: Represents a small snippet of text (a token).
  2. ToolCall: Indicates Claude wants to execute a function.

If you need to perform actions after the stream completes: like logging the full response: use the then() method.

return Ai::agent(SupportAgent::class)
    ->stream($message)
    ->then(function ($response) {
        // $response contains the full aggregated text and usage stats
        Log::info('Chat completed', ['tokens' => $response->usage()]);
    });

For teams using the Vercel AI SDK on the frontend, call usingVercelDataProtocol() to ensure compatibility with their standard event format.

Production: Timeouts and Performance

A professional monitoring dashboard representing production stability

Streaming connections often stay open for 30 to 60 seconds. Standard PHP execution limits will kill these processes prematurely.

In your streaming controller, increase the time limit:

public function __invoke(Request $request)
{
    set_time_limit(120); 
    
    // ... logic
}

If your agent performs heavy background tasks during a tool call, offload them. Use broadcastOnQueue() to handle events asynchronously. This prevents the HTTP worker from blocking while waiting for secondary processes.

Forward Motion

The Laravel AI SDK turns complex LLM integration into a standard Laravel workflow. By treating agents as first-class citizens, we maintain the elegance of the framework while embracing the power of Claude.

Start building your first streaming interface today. We would love to see what you ship to the community.


Previous
Building Real-Time Dashboards with Laravel, Vue 3, and Inertia 3.x
Next
Optimistic UI: Building Instant-Feedback Interfaces with Laravel, Vue 3, and Inertia 3.x