PHP code example of swisnl / ag-ui-server

1. Go to this page and download the library: Download swisnl/ag-ui-server library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

swisnl / ag-ui-server example snippets




use Swis\AgUiServer\AgUiState;
use Swis\AgUiServer\Transporter\SseTransporter;

// Initialize state
$state = new AgUiState();

// Start a conversation run
$threadId = 'thread_' . uniqid();
$runId = 'run_' . uniqid();
$state->startRun($threadId, $runId);

// Simple message
$state->addMessage('Hello! How can I help you?');

// Streaming message from LLM
$state->addMessage(function() {
    return $this->llm->streamCompletion($prompt); // Returns iterable
});

// Tool call
$state->addToolCall('web_search', '{"query": "weather today"}');

// Finish the run
$state->finishRun();

// String content - sent as single message
$state->addMessage('Complete response here');

// Closure returning string
$state->addMessage(function() {
    return $this->llm->complete($prompt);
});

// Closure returning iterable - streamed as deltas
$state->addMessage(function() {
    return $this->llm->streamCompletion($prompt);
};

// Direct iterable
$state->addMessage(['Hello ', 'world', '!']);

// Manual control for complex scenarios
$messageId = $state->startMessage();
foreach ($complexStream as $chunk) {
    $state->addMessageContent($messageId, $chunk);
}
$state->finishMessage($messageId);

// Server-Sent Events (default)
$transporter = new SseTransporter();
$transporter->initialize(); // Sends headers

// Custom headers
$transporter = new SseTransporter([
    'Access-Control-Allow-Origin' => 'https://yourapp.com',
    'Cache-Control' => 'no-cache',
]);
$transporter->initialize(); // Sends headers

// Future: WebSocket support
// $transporter = new WebSocketTransporter($connection);

public function handleChatRequest(Request $request)
{
    $userMessage = $request->input('message');
    $threadId = $request->input('threadId') ?? 'thread_' . uniqid();
    $runId = 'run_' . uniqid();
    
    $state = new AgUiState();
    $state->startRun($threadId, $runId);
    
    try {
        // Step 1: Analyze query
        $state->startStep('analyzing_query');
        // ... analysis logic ...
        $state->finishStep();
        
        // Step 2: Retrieve context
        $state->startStep('retrieving_context');
        $state->addToolCall(null, 'vector_search', json_encode([
            'query' => $userMessage,
            'top_k' => 5
        ]));
        $documents = $this->vectorSearch($userMessage);
        $state->finishStep();
        
        // Step 3: Generate response
        $state->startStep('generating_response');
        $state->addMessage(null, function() use ($userMessage, $documents) {
            return $this->llm->streamWithContext($userMessage, $documents);
        }, 'assistant');
        $state->finishStep();
        
        $state->finishRun();
        
    } catch (\Exception $e) {
        $state->errorRun($e->getMessage());
    }
}

use Swis\AgUiServer\Events\TextMessageStartEvent;
use Swis\AgUiServer\Events\TextMessageContentEvent; 
use Swis\AgUiServer\Events\TextMessageEndEvent;
use Swis\AgUiServer\Transporter\SseTransporter;
use Psr\EventDispatcher\EventDispatcherInterface;

// Set up event dispatcher and transporter
$dispatcher = $container->get(EventDispatcherInterface::class);
$transporter = new SseTransporter();
$transporter->initialize(); // Sends headers
$transporter->setEventDispatcher($dispatcher);

// Now trigger events from your application
$messageId = 'msg_' . uniqid();

// The transporter will automatically listen for these events and send them
$dispatcher->dispatch(new TextMessageStartEvent(
    messageId: $messageId,
    role: 'assistant'
));

$dispatcher->dispatch(new TextMessageContentEvent(
    messageId: $messageId,
    content: 'Hello from my custom application!'
));

$dispatcher->dispatch(new TextMessageEndEvent(
    messageId: $messageId
));

$transporter = new SseTransporter();
$transporter->initialize();

// Send events directly
$event = new TextMessageStartEvent( 
    messageId: 'msg_123',
    role: 'assistant'
);

$transporter->send($event);
$transporter->close();

// Without delta buffering (default)
$state = new AgUiState();

// With delta buffering for optimized streaming
$state = (new AgUiState())->withDeltaBuffering(
    deltaBufferThreshold: 150,  // chars
    deltaFlushInterval: 0.3     // seconds
);

use Psr\EventDispatcher\EventDispatcherInterface;

// Your existing PSR-14 dispatcher
$dispatcher = $container->get(EventDispatcherInterface::class);

// Listen to AG-UI events
$dispatcher->addListener(TextMessageStartEvent::class, function($event) {
    // Log message start
    $this->logger->info('Message started', ['messageId' => $event->messageId]);
});

class WebSocketTransporter implements TransporterInterface
{
    public function __construct(private $connection) {}
    
    public function initialize(): void
    {
        // Setup WebSocket connection
    }
    
    public function send(AgUiEvent $event): void
    {
        $this->connection->send($event->toJson());
    }
    
    public function sendComment(string $comment): void
    {
        // WebSocket doesn't need comments
    }
    
    public function close(): void
    {
        $this->connection->close();
    }
}