symfony/ai-session-message-store
Symfony AI Session Message Store integrates Symfony Session as a message store for Symfony AI Chat, letting you persist and retrieve chat conversation messages across requests using standard Symfony session handling.
composer require symfony/ai-session-message-store symfony/ai-chat symfony/http-foundation
.env uses a supported driver (Redis recommended for production):
SESSION_DRIVER=redis
app/Providers/AppServiceProvider.php:
use Symfony\Component\Ai\Chat\MessageStoreInterface;
use Illuminate\Support\Facades\Session;
public function register()
{
$this->app->singleton(MessageStoreInterface::class, function () {
return new class implements MessageStoreInterface {
public function load(string $sessionId): array
{
Session::setId($sessionId);
return Session::get('ai_messages', []);
}
public function save(string $sessionId, array $messages): void
{
Session::setId($sessionId);
Session::put('ai_messages', $messages);
}
};
});
}
routes/web.php:
use Symfony\Component\Ai\Chat\AiChat;
use Symfony\Component\Ai\Chat\MessageStoreInterface;
Route::post('/ai/chat', function () {
$aiChat = new AiChat(app(MessageStoreInterface::class));
$response = $aiChat->chat('Hello!');
return response()->json(['response' => $response]);
});
MessageStoreInterface implementation in src/MessageStore.php (if provided by the package).// Store messages in session
$store->save($request->session()->getId(), $messages);
// Load messages for continuation
$messages = $store->load($request->session()->getId());
public function load(string $sessionId): array
{
$sessionMessages = parent::load($sessionId);
$archivedMessages = DB::table('ai_messages')->where('session_id', $sessionId)->get();
return array_merge($sessionMessages, $archivedMessages->toArray());
}
FlashBag for AI notifications:
$this->session->getFlashBag()->add('ai_notification', 'Your chat is saved!');
$this->app->bind(MessageStoreInterface::class, function ($app) {
return new LaravelSessionMessageStore($app->make('session'));
});
Route::middleware(['web', 'share_session_data'])->group(function () {
Route::post('/ai/chat', [AiController::class, 'handle']);
});
$store = Mockery::mock(MessageStoreInterface::class);
$store->shouldReceive('load')->andReturn([...]);
$store->shouldReceive('save')->once();
use Illuminate\Support\Facades\Cache;
public function save(string $sessionId, array $messages): void
{
Cache::remember("ai_messages_{$sessionId}", now()->addHours(1), function () use ($messages) {
return $messages;
});
}
public function load(string $sessionId): array
{
return Session::namespace("tenant_{$tenantId}")->get('ai_messages', []);
}
event(new AiMessagesSaved($sessionId, $messages));
$request->session()->setId($sessionId); // Ensure consistency
FlashBag may not align with Laravel’s flash().public function getFlash(string $key): array
{
return $this->session->getFlashBag()->get($key, []);
}
SESSION_DRIVER=redis
SESSION_REDIS_PREFIX=ai_chat_
public function load(string $sessionId, int $limit = 100): array
{
return array_slice(parent::load($sessionId), -$limit);
}
\Log::debug('AI Messages:', ['session_id' => $sessionId, 'messages' => $messages]);
dd($store->load($request->session()->getId()));
dd() to compare method signatures:
dd(method_exists($store, 'load')); // Verify interface compliance
public function save(string $sessionId, array $messages): void
{
$serialized = json_encode($messages);
$this->session->put('ai_messages', $serialized);
}
use Illuminate\Cache\RateLimiting\Limit;
Route::middleware(['throttle:10,1'])->group(function () {
Route::post('/ai/chat', [AiController::class, 'handle']);
});
\Log::channel('ai')->info('Chat interaction', [
'session_id' => $sessionId,
'user_id' => auth()->id(),
'timestamp' => now(),
]);
config/database.php:
'redis' => [
'client' => 'predis',
'options' => [
'prefix' => 'laravel_ai_',
],
],
SESSION_LIFETIME in .env to match AI chat needs:
SESSION_LIFETIME=1440 # 24 hours
config/cors.php:
'paths' => ['api/ai/*', 'sanctum/csrf-cookie'],
How can I help you explore Laravel packages today?