Laravel AI Agents: Streaming, Token Budgets &amp; Typed Output | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com) [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles  ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://msaied.com) [ Projects ](https://msaied.com/projects) [ Articles ](https://msaied.com/articles) [ Certificates ](https://msaied.com/certificates) [ Contact ](https://msaied.com#contact-section) 

  [ home ](https://msaied.com)    [ articles ](https://msaied.com/articles)    Production AI Agents in Laravel: Streaming, Token Budgets, and Structured Output Contracts        On this page       1. [  The Gap Between Demo and Production AI Agents ](#the-gap-between-demo-and-production-ai-agents)
2. [  Streaming with Server-Sent Events ](#streaming-with-server-sent-events)
3. [  Enforcing Token Budgets at the Application Layer ](#enforcing-token-budgets-at-the-application-layer)
4. [  Structured Output Contracts with Readonly DTOs ](#structured-output-contracts-with-readonly-dtos)
5. [  Prompt-Side Contract Enforcement ](#prompt-side-contract-enforcement)
6. [  Key Takeaways ](#key-takeaways)

  ![Production AI Agents in Laravel: Streaming, Token Budgets, and Structured Output Contracts](https://cdn.msaied.com/466/15db89e4226fa2eecdd82ea72f2d2c01.png)

  #laravel   #ai   #agents   #streaming   #structured-output  

 Production AI Agents in Laravel: Streaming, Token Budgets, and Structured Output Contracts 
============================================================================================

     25 Jul 2026      3 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

1. [  01   The Gap Between Demo and Production AI Agents  ](#the-gap-between-demo-and-production-ai-agents)
2. [  02   Streaming with Server-Sent Events  ](#streaming-with-server-sent-events)
3. [  03   Enforcing Token Budgets at the Application Layer  ](#enforcing-token-budgets-at-the-application-layer)
4. [  04   Structured Output Contracts with Readonly DTOs  ](#structured-output-contracts-with-readonly-dtos)
5. [  05   Prompt-Side Contract Enforcement  ](#prompt-side-contract-enforcement)
6. [  06   Key Takeaways  ](#key-takeaways)

 The Gap Between Demo and Production AI Agents
---------------------------------------------

Most Laravel AI tutorials stop at `$client->chat()`. Production agents need three things demos skip: streaming responses that don't time out, hard token budgets that protect your bill, and structured output contracts that fail loudly when a model returns garbage.

This article tackles all three with concrete, opinionated patterns.

---

Streaming with Server-Sent Events
---------------------------------

Laravel's `StreamedResponse` is the right primitive. Pair it with a generator-based OpenAI client call and you get true SSE without a WebSocket server.

```php
// routes/api.php
Route::post('/agent/stream', AgentStreamController::class);

// app/Http/Controllers/AgentStreamController.php
final class AgentStreamController
{
    public function __invoke(AgentRequest $request, AgentService $agent): StreamedResponse
    {
        return response()->stream(
            function () use ($request, $agent): void {
                foreach ($agent->stream($request->validated('prompt')) as $chunk) {
                    echo "data: " . json_encode(['text' => $chunk]) . "\n\n";
                    ob_flush();
                    flush();
                }
                echo "data: [DONE]\n\n";
            },
            headers: ['Content-Type' => 'text/event-stream', 'X-Accel-Buffering' => 'no']
        );
    }
}

```

The `X-Accel-Buffering: no` header is critical when Nginx sits in front — without it, Nginx buffers the entire response.

---

Enforcing Token Budgets at the Application Layer
------------------------------------------------

Don't rely solely on `max_tokens` in the API call. A multi-turn agent accumulates context silently. Track token usage yourself and abort before you hit a cost cliff.

```php
final class TokenBudget
{
    private int $used = 0;

    public function __construct(private readonly int $limit) {}

    public function consume(int $tokens): void
    {
        $this->used += $tokens;
        if ($this->used > $this->limit) {
            throw new TokenBudgetExceededException(
                "Budget of {$this->limit} tokens exceeded (used: {$this->used})"
            );
        }
    }

    public function remaining(): int
    {
        return max(0, $this->limit - $this->used);
    }
}

```

Inject a `TokenBudget` into your agent loop and call `consume()` after each API response using the usage object the API returns. This gives you per-request, per-user, or per-tenant budget enforcement — whichever granularity your SaaS needs.

```php
$budget = new TokenBudget(limit: 8_000);

foreach ($turns as $turn) {
    $response = $this->client->chat($turn->toMessages(), maxTokens: $budget->remaining());
    $budget->consume($response->usage->totalTokens);
    // ...
}

```

---

Structured Output Contracts with Readonly DTOs
----------------------------------------------

JSON mode is not a contract. Models hallucinate keys, change nesting, or return `null` where you expect a string. Validate every structured response against a typed DTO immediately after deserialization.

```php
readonly class SentimentResult
{
    public function __construct(
        public readonly string $sentiment,  // 'positive'|'negative'|'neutral'
        public readonly float  $confidence, // 0.0–1.0
        public readonly string $summary,
    ) {}

    public static function fromArray(array $data): self
    {
        $validated = validator($data, [
            'sentiment'  => ['required', 'string', Rule::in(['positive','negative','neutral'])],
            'confidence' => ['required', 'numeric', 'min:0', 'max:1'],
            'summary'    => ['required', 'string', 'max:500'],
        ])->validate();

        return new self(...$validated);
    }
}

```

Call `SentimentResult::fromArray(json_decode($response->content, true))` and let Laravel's validator throw a `ValidationException` on malformed output. This surfaces model regressions immediately rather than letting bad data propagate into your database.

### Prompt-Side Contract Enforcement

Include the schema in your system prompt as a JSON Schema snippet. Models with JSON mode enabled respect it more reliably than natural-language instructions alone. Store the schema alongside the DTO so they stay in sync:

```php
public static function jsonSchema(): array
{
    return [
        'type' => 'object',
        'required' => ['sentiment', 'confidence', 'summary'],
        'properties' => [
            'sentiment'  => ['type' => 'string', 'enum' => ['positive','negative','neutral']],
            'confidence' => ['type' => 'number', 'minimum' => 0, 'maximum' => 1],
            'summary'    => ['type' => 'string', 'maxLength' => 500],
        ],
    ];
}

```

---

Key Takeaways
-------------

- Use `StreamedResponse` with `X-Accel-Buffering: no` for true SSE through Nginx.
- Track token usage from API responses; enforce budgets in application code, not just `max_tokens`.
- Validate every structured model response against a typed readonly DTO using Laravel's validator.
- Co-locate the JSON Schema with the DTO so prompt and validation contracts never drift.
- Throw typed exceptions (`TokenBudgetExceededException`, `ValidationException`) so callers can handle failures explicitly.

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fmsaied.com%2Farticles%2Fproduction-ai-agents-in-laravel-streaming-token-budgets-and-structured-output-contracts-3&text=Production+AI+Agents+in+Laravel%3A+Streaming%2C+Token+Budgets%2C+and+Structured+Output+Contracts) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fmsaied.com%2Farticles%2Fproduction-ai-agents-in-laravel-streaming-token-budgets-and-structured-output-contracts-3) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  Why not just use `max\_tokens` to control costs instead of a custom TokenBudget?        `max_tokens` caps a single API call but doesn't track cumulative usage across a multi-turn conversation. A TokenBudget class aggregates usage from every turn's response object, giving you per-request or per-user cost control that `max_tokens` alone cannot provide. 

      Q02  Does JSON mode from OpenAI guarantee the response matches my DTO?        No. JSON mode guarantees valid JSON syntax, not that the keys, types, or values match your schema. Always validate the decoded array against your DTO's rules immediately after deserialization and throw on failure. 

      Q03  How do I prevent Nginx from buffering my SSE stream?        Set the `X-Accel-Buffering: no` response header. Nginx respects this header and disables proxy buffering for that response, allowing chunks to reach the client as they are flushed. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://msaied.com/articles) 

 [ ![Concurrency in Laravel: Process Pools, Fibers, and the Concurrency Facade](https://cdn.msaied.com/471/ba1a628c196e92cbb81033c865c9ad26.png) laravel concurrency php 

### Concurrency in Laravel: Process Pools, Fibers, and the Concurrency Facade

Laravel's Concurrency facade and process pools let you run independent work in parallel without reaching for a...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 26 Jul 2026     4 min read  

  Read    

 ](https://msaied.com/articles/concurrency-in-laravel-process-pools-fibers-and-the-concurrency-facade) [ ![Laravel Queues in Production: Horizon Tuning, Metrics, and Graceful Scaling](https://cdn.msaied.com/470/afd2bee56d15842d72c1c6d5c238d236.png) laravel horizon queues 

### Laravel Queues in Production: Horizon Tuning, Metrics, and Graceful Scaling

Go beyond basic queue setup. Learn how to tune Horizon supervisor processes, interpret queue metrics, handle b...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 26 Jul 2026     3 min read  

  Read    

 ](https://msaied.com/articles/laravel-queues-in-production-horizon-tuning-metrics-and-graceful-scaling) [ ![Laravel Horizon: Queue Metrics, Supervisor Tuning, and Graceful Scaling in Production](https://cdn.msaied.com/469/ebbc461b808da425a418bf6ffc998d7a.png) laravel horizon queues 

### Laravel Horizon: Queue Metrics, Supervisor Tuning, and Graceful Scaling in Production

Beyond the dashboard: how to tune Horizon supervisors, interpret queue metrics, and scale workers gracefully w...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 25 Jul 2026     3 min read  

  Read    

 ](https://msaied.com/articles/laravel-horizon-queue-metrics-supervisor-tuning-and-graceful-scaling-in-production-1) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://msaied.com)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

Explore

- [Home](https://msaied.com)
- [Projects](https://msaied.com/projects)
- [Articles](https://msaied.com/articles)
- [Certificates](https://msaied.com/certificates)
- [Contact](https://msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
