GuardedChatBundle
A protection layer for public AI chats in Symfony: prompt-injection filter, rate limits, budget stop and retention.
Release v1.1.0 · last active Oct 22, 2026
Source: GitHub API, as of Oct 24, 2026, 14:15
What it does
GuardedChatBundle is a protection layer for public AI chats in Symfony applications. It builds on Symfony AI and complements it instead of replacing it: Symfony AI talks to the model, while everything around a public, anonymous chat endpoint is left to the application.
A pre-filter detects obvious prompt-injection phrasing before the model is called. Rate limits per client, a message limit per session and a budget stop keep a bot from draining the token budget. Signed session tokens with a lifetime and an idle timeout decide who may continue a conversation.
Prompts are versioned in the database and can be changed without a deploy. A two-stage kill switch turns the chat off during an incident, and retention periods delete old conversations on a schedule. A ready-to-use chat widget with a notice that the visitor is talking to an AI is included.
In production on jacomeit.de
The bundle protects the public chat on jacomeit.de. Its routes are mounted under the prefix /chat, and the platform is a LiteLLM gateway through the Generic bridge of Symfony AI.
The rate limits are 5 sessions per hour, plus 8 messages per minute and 50 per day. Conversations are deleted after 90 days, and the prune runs daily at 03:30. The chat uses a knowledge base with PostgreSQL full-text search.
The extension points of the bundle are filled with custom classes: a runtime switch backed by the site settings, a check through Cloudflare Turnstile, client detection behind Cloudflare and detection of an exhausted LiteLLM budget. The form of address "Sie" and plain-text output are set as pinned instructions.
Installation
Install the bundle with composer require stejac/guarded-chat-bundle. With Symfony Flex the recipe creates the configuration files and the variable GUARDED_CHAT_ENABLED.
In config/packages/guarded_chat.yaml, set the keys platform and model, plus the fallback prompt under prompt.default. Configure the platform itself as described in the Symfony AI documentation. Mount the routes in config/routes/guarded_chat.yaml with the resource @GuardedChatBundle/config/routes.php and a prefix such as /chat.
Add the widget to your base template with {{ include('@GuardedChat/widget.html.twig') }}. It requires AssetMapper and the StimulusBundle. The bundle ships no migrations: generate them with bin/console doctrine:migrations:diff and review the result.