The simplest way to use streaming is with the respondStreamed method:
Copy
$agent = WeatherAgent::for('user-123');$stream = $agent->respondStreamed('What\'s the weather like in Boston and Los Angeles?');foreach ($stream as $chunk) { if ($chunk instanceof \LarAgent\Messages\StreamedAssistantMessage) { echo $chunk->getLastChunk(); // Output each new piece of content }}
You can also provide a callback function to process each chunk:
Copy
$agent = WeatherAgent::for('user-123');$stream = $agent->respondStreamed( 'What\'s the weather like in Boston and Los Angeles?', function ($chunk) { if ($chunk instanceof \LarAgent\Messages\StreamedAssistantMessage) { echo $chunk->getLastChunk(); // Flush output buffer to send content to the browser immediately ob_flush(); flush(); } });// Consume the stream to ensure it completesforeach ($stream as $_) { // The callback handles the output}
Tool call messages (handled internally by LarAgent)
Array
Final chunk when structured output is enabled
For most use cases, you only need to handle StreamedAssistantMessage chunks as shown in the examples above. Tool calls are processed automatically by LarAgent.
For Laravel applications, LarAgent provides the streamResponse method that returns a Laravel StreamedResponse, making it easy to integrate with your controllers:
Copy
// In a controllerpublic function chat(Request $request){ $message = $request->input('message'); $agent = WeatherAgent::for(auth()->id()); // Return a streamable response return $agent->streamResponse($message, 'plain');}
The streamResponse method supports three formats:
Copy
// Simple text outputreturn $agent->streamResponse($message, 'plain');
Frontend implementation (JavaScript):
Copy
fetch('/chat?message=What is the weather in Boston?') .then(response => { const reader = response.body.getReader(); const decoder = new TextDecoder(); function read() { return reader.read().then(({ done, value }) => { if (done) return; const text = decoder.decode(value); document.getElementById('output').textContent += text; return read(); }); } return read(); });
Copy
// Simple text outputreturn $agent->streamResponse($message, 'plain');
Frontend implementation (JavaScript):
Copy
fetch('/chat?message=What is the weather in Boston?') .then(response => { const reader = response.body.getReader(); const decoder = new TextDecoder(); function read() { return reader.read().then(({ done, value }) => { if (done) return; const text = decoder.decode(value); document.getElementById('output').textContent += text; return read(); }); } return read(); });
Copy
// Structured JSON with delta and contentreturn $agent->streamResponse($message, 'json');
When using structured output with streaming, you’ll receive text chunks during generation, and the final structured data at the end:
Copy
$agent = ProfileAgent::for('user-123');$stream = $agent->respondStreamed('Generate a profile for John Doe');$finalStructuredData = null;foreach ($stream as $chunk) { if ($chunk instanceof \LarAgent\Messages\StreamedAssistantMessage) { echo $chunk->getLastChunk(); // Part of JSON } elseif (is_array($chunk)) { // This is the final structured data $finalStructuredData = $chunk; }}// Now $finalStructuredData is array which contains the structured output// For example: ['name' => 'John Doe', 'age' => 30, 'interests' => [...]]
When using SSE format with structured output, you’ll receive a special event: