saifulferoz / laravel-ai-realtime
Realtime speech-to-speech voice sessions and WebRTC ephemeral credentials for Laravel AI
Package info
github.com/saifulferoz/laravel-ai-realtime
pkg:composer/saifulferoz/laravel-ai-realtime
v0.1.0
2026-08-24 16:15 UTC
Requires
- php: ^8.2
- illuminate/contracts: ^11.0|^12.0
- illuminate/http: ^11.0|^12.0
- illuminate/support: ^11.0|^12.0
- laravel/ai: ^0.11|^0.12|^0.13
Requires (Dev)
- laravel/pint: ^1.18
- orchestra/testbench: ^9.0|^10.0
- pestphp/pest: ^3.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is not auto-updated.
Last update: 2026-11-03 15:58:00 UTC
README
Realtime speech-to-speech voice sessions and WebRTC ephemeral credential generation for Laravel AI (laravel/ai).
Supports OpenAI (POST /v1/realtime/client_secrets) and Azure OpenAI (POST /openai/v1/realtime/client_secrets) GA APIs.
๐ Architecture
[ Frontend / Mobile App ]
โ
โ 1. Request session credentials
โผ
[ Laravel App (Control Plane) ] โโ (laravel-ai-realtime) โโโบ [ OpenAI / Azure ]
โ (Mints Ephemeral Token)
โ 2. Returns short-lived client_secret (token)
โผ
[ Frontend / Mobile App ]
โ
โ 3. Direct bidirectional audio stream (WebRTC / Data Plane)
โผ
[ OpenAI / Azure Realtime Server ] (< 300ms latency, zero PHP server load)
- Security: Your master API key remains private on your backend server. Laravel mints a short-lived ephemeral client token (
client_secret). - Performance: Voice media streaming connects directly from client (browser/native app) to OpenAI/Azure via WebRTC, bypassing PHP processes and avoiding proxy bottlenecks.
๐ฆ Installation
composer require saifulferoz/laravel-ai-realtime
๐ ๏ธ Usage
1. Using the realtime(...) Helper
use function Laravel\Ai\agent; use function LaravelAi\Realtime\realtime; $agent = agent( instructions: 'You are a warm customer service agent for ACME.', tools: [new LookupOrderTool], ); // Generate ephemeral session credentials for WebRTC client $session = realtime($agent, voice: 'alloy'); return response()->json([ 'client_secret' => $session->clientSecret(), 'expires_at' => $session->expiresAt(), 'session_id' => $session->id(), ]);
2. Using the Realtime Facade
use LaravelAi\Realtime\Facades\Realtime; $session = Realtime::createSession( provider: 'openai', model: 'gpt-realtime', instructions: 'You are an airline customer support voice agent.', voice: 'marin', modalities: ['text', 'audio'], options: [ 'turn_detection' => ['type' => 'server_vad'], 'output_audio_format' => 'pcm16', ] ); return response()->json([ 'token' => $session->clientSecret(), 'expires_at' => $session->expiresAt(), ]);
3. Using the HasRealtimeSession Trait in Class Agents
namespace App\Ai\Agents; use Laravel\Ai\Contracts\Agent; use Laravel\Ai\Promptable; use LaravelAi\Realtime\Concerns\HasRealtimeSession; class SupportAgent implements Agent { use Promptable; use HasRealtimeSession; public function instructions(): string { return 'You are an intelligent support assistant.'; } } // In Controller: $agent = new SupportAgent(); $session = $agent->realtime(voice: 'alloy');
๐งช Testing and Fakes
Testing real-time voice credential endpoints is simple with Realtime::fake():
use LaravelAi\Realtime\Facades\Realtime; test('voice session controller returns ephemeral credentials', function () { Realtime::fake([ 'id' => 'sess_fake_123', 'value' => 'ek_fake_secret_token', 'expires_at' => 1790000000, ]); $response = $this->postJson('/api/voice/session'); $response->assertOk() ->assertJson([ 'client_secret' => 'ek_fake_secret_token', ]); Realtime::assertCreated(function ($prompt, $provider) { return $provider === 'openai'; }); });
๐ License
The MIT License (MIT). Please see LICENSE.md for more information.