Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Ai Cloudflare Message Store Laravel Package

symfony/ai-cloudflare-message-store

Cloudflare KV-backed message store for Symfony AI Chat. Persist and retrieve chat messages in Cloudflare Workers KV, with support for KV namespace operations like bulk get and bulk update, enabling scalable storage for AI conversation history.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup for Laravel

  1. Install the Package (via Composer):

    composer require symfony/ai-cloudflare-message-store
    

    Note: Requires Symfony AI Chat (symfony/ai-chat). If not using Symfony, see Implementation Patterns for Laravel-native workarounds.

  2. Configure Cloudflare KV:

    • Create a KV namespace in Cloudflare Dashboard.
    • Generate an API token with Editor permissions for the namespace.
    • Add credentials to .env:
      CLOUDFLARE_ACCOUNT_ID=your_account_id
      CLOUDFLARE_KV_NAMESPACE_ID=your_namespace_id
      CLOUDFLARE_API_TOKEN=your_api_token
      
  3. Bind the Store in Laravel:

    // config/services.php
    'cloudflare_kv' => [
        'account_id' => env('CLOUDFLARE_ACCOUNT_ID'),
        'namespace_id' => env('CLOUDFLARE_KV_NAMESPACE_ID'),
        'api_token' => env('CLOUDFLARE_API_TOKEN'),
    ],
    
  4. First Use Case: Persist a Chat Message

    use Symfony\Component\Ai\Chat\MessageStoreInterface;
    use Symfony\Component\Ai\Chat\Message;
    
    // Bind the store to Laravel's container (if using Symfony AI Chat)
    $container->set(MessageStoreInterface::class, fn() => new \Symfony\Ai\CloudflareMessageStore\CloudflareKvMessageStore(
        config('services.cloudflare_kv')
    ));
    
    // Example usage
    $store = $container->get(MessageStoreInterface::class);
    $message = new Message('user', 'Hello, AI!');
    $store->save($message, 'chat_123'); // 'chat_123' is a conversation ID
    

Implementation Patterns

Workflow: AI Chat Message Persistence

  1. Conversation Initialization:

    // Start a new chat (generate a UUID for the conversation ID)
    $conversationId = Str::uuid()->toString();
    
  2. Saving Messages:

    $store = app(MessageStoreInterface::class);
    $store->save(new Message('user', 'What is Laravel?'), $conversationId);
    $store->save(new Message('ai', 'Laravel is a PHP framework...'), $conversationId);
    
  3. Loading a Chat History:

    $messages = $store->findAll($conversationId);
    // $messages = [Message, Message, ...]
    
  4. Bulk Operations (Edge-Optimized):

    // Fetch all messages for multiple conversations at once
    $conversationIds = ['chat_123', 'chat_456'];
    $messages = $store->bulkFindAll($conversationIds);
    
    // Update multiple messages in a single request
    $updates = [
        'chat_123' => [new Message('ai', 'Updated response...')],
        'chat_456' => [new Message('user', 'New question?')],
    ];
    $store->bulkSave($updates);
    

Integration Tips

  • Hybrid Storage for Metadata: Use KV for message content and a database (e.g., MySQL) for metadata (e.g., conversations table with id, user_id, created_at).

    // Example: Store conversation metadata in DB, messages in KV
    $conversation = Conversation::create(['user_id' => auth()->id()]);
    $store->save(new Message('user', 'Hello'), $conversation->id);
    
  • Fallback for Offline Use: Implement a local cache (e.g., Redis) as a fallback:

    use Illuminate\Support\Facades\Cache;
    
    $messages = $store->findAll($conversationId) ?? Cache::get("offline_chat_{$conversationId}");
    
  • Event-Driven Workflows: Dispatch Laravel events after saving messages to trigger side effects (e.g., analytics, notifications):

    $store->save($message, $conversationId);
    event(new ChatMessageSaved($conversationId, $message));
    
  • Serialization for Complex Objects: Override serialization for Eloquent models or custom objects:

    use Symfony\Component\Serializer\SerializerInterface;
    
    $serializer = app(SerializerInterface::class);
    $messageData = $serializer->serialize($message, 'json');
    $store->saveFromString($messageData, $conversationId);
    

Gotchas and Tips

Pitfalls

  1. Symfony Dependency:

    • The package requires Symfony AI Chat. If your Laravel app doesn’t use Symfony, you’ll need to:
      • Fork the package and replace MessageStoreInterface with Laravel’s Message facade or Illuminate\Queue.
      • Example workaround:
        // In a Laravel service
        class CloudflareKvMessageStore implements \Illuminate\Contracts\Queue\ShouldBeQueued
        {
            public function store($message, $conversationId) {
                // Use Cloudflare KV client directly
            }
        }
        
  2. Key Collisions:

    • KV uses string keys. Poor key design (e.g., message_{id}) can lead to collisions. Use a structured format:
      // Good: user:{id}:conversation:{id}:message:{id}
      $key = "user:{$userId}:conversation:{$conversationId}:message:{$messageId}";
      
  3. Bulk Operation Limits:

    • Cloudflare KV’s bulk_get/bulk_update has a 100-key limit per request. For large datasets:
      • Implement pagination or batch processing.
      • Example:
        $batchSize = 50;
        $batches = array_chunk($conversationIds, $batchSize);
        foreach ($batches as $batch) {
            $store->bulkFindAll($batch);
        }
        
  4. Cold Starts:

    • KV may have higher latency on first request after inactivity. Mitigate with:
      • A warm-up request in your app’s bootstrapping.
      • Local caching for frequently accessed chats.
  5. Cost Monitoring:

    • Cloudflare KV charges per operation. Monitor usage in the Cloudflare Dashboard and set alerts for:
      • Unexpected spikes in reads/writes.
      • Approaching the 10MB value size limit (compress large messages).

Debugging Tips

  • Enable Cloudflare KV Logging: Add this to your .env to debug API calls:

    CLOUDFLARE_KV_DEBUG=true
    

    Logs will appear in Laravel’s storage/logs/laravel.log.

  • Handle API Errors Gracefully: Cloudflare KV may return 429 Too Many Requests or 401 Unauthorized. Implement retries:

    use Symfony\Component\Ai\Exception\MessageStoreException;
    
    try {
        $store->save($message, $conversationId);
    } catch (MessageStoreException $e) {
        if ($e->getCode() === 429) {
            sleep(1); // Retry after delay
            retry();
        }
        throw $e;
    }
    
  • Test Locally with Mock KV: Use the Cloudflare KV Emulator for local testing:

    docker run -p 25000:25000 cloudflare/cloudflare-kv-emulator
    

    Update .env to point to the emulator:

    CLOUDFLARE_KV_URL=http://localhost:25000
    

Extension Points

  1. Custom Key Generator: Override the default key format:

    $store->setKeyGenerator(fn($conversationId, $messageId) => "custom_prefix:{$conversationId}_{$messageId}");
    
  2. Add TTL for Ephemeral Messages: Use KV’s expiration feature:

    $store->save($message, $conversationId, 3600); // Expires in 1 hour
    
  3. Integrate with Laravel Queues: For async operations, wrap the store in a queue job:

    use Illuminate\Bus\Queueable;
    use Illuminate\Queue\SerializesModels;
    
    class SaveChatMessage implements Queueable, SerializesModels
    {
        public function handle() {
            $store = app(MessageStoreInterface::class);
            $store->save($this->message, $this->conversationId);
        }
    }
    
  4. Add Analytics Middleware: Track message operations:

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky