Weave 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 Doctrine Message Store Laravel Package

symfony/ai-doctrine-message-store

symfony/ai-doctrine-message-store integrates Doctrine DBAL with Symfony AI Chat to provide database-backed message storage. It lets AI chat applications persist conversation messages through Doctrine, with resources and contributions handled in the main Symfony AI repository.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

symfony/ai-doctrine-message-store is a narrow bridge package: a DoctrineDBALMessageStore implementing Symfony AI's MessageStoreInterface on top of a Doctrine DBAL Connection. It is a read-only split of the symfony/ai monorepo (issues and PRs route back to symfony/ai), so the code surface is small and the maintenance surface effectively sits upstream. Functionally it does one thing: persist and retrieve chat messages in a relational table so conversation history survives across requests.

For a Laravel product this is an indirect fit. Laravel ships doctrine/dbal for schema introspection and column-change operations, and many teams already have a live DBAL connection, so the persistence substrate is available. What is not available is the consumer: the store implements the Symfony AI contract, not a Laravel contract. Note that the interface is Symfony AI's own MessageStoreInterface — earlier internal write-ups describing it as "PSR-15" are incorrect; PSR-15 is HTTP server middleware and is unrelated. The integration work is therefore contract adoption, not protocol bridging, which is cheaper than the PSR-15 framing implied, but still requires pulling in symfony/ai-* contracts or writing a mirrored interface plus an adapter.

Integration feasibility

Feasible for a spike, moderate for production. The realistic path is: keep the package as the storage implementation, wrap it behind a first-party Laravel interface (MessageStore contract bound in a service provider), and never let Symfony AI types leak into controllers or jobs. That preserves an exit to an Eloquent/query-builder implementation if the upstream package stalls.

The v0.7.0 changelog entry ("adding support for databases with other existing tables") is the most informative artifact here: it tells us the store creates and manages its own table, and that coexistence with a pre-existing schema was a real defect. For a Laravel app sharing a database with tenant, audit, or job tables, that is precisely the failure class to test before committing.

Technical risk

  • Maturity: 1 star, 0 dependents, all releases in the 0.x line, and multiple releases with "no significant changes." No stable API guarantee. The listed last release date (2026-10-26) is in the future relative to normal release metadata — treat the maturity signal as unverified until confirmed against Packagist.
  • Documentation: README is three sentences plus contributing links. No schema documentation, no message payload shape, no retention guidance, no migration tooling.
  • Abstraction cost: DBAL-only is a genuine benefit (no ORM coupling, any supported RDBMS), but it also means no model events, no Eloquent observers, no soft deletes, and no automatic timestamps — all of which a Laravel team would otherwise get for free.
  • Vendor coupling: small, but asymmetric. Adopting the contract is cheap; adopting the schema is the lock-in, since any replacement store must reconcile with rows the bridge wrote.
  • Build-vs-buy: a Laravel-native equivalent (a messages table, a repository, a pruning command) is roughly a day or two of work and removes the dependency entirely. The package's value is mostly conformance to a Symfony contract you may not otherwise need.

Key questions

  1. Are we actually running Symfony AI Chat components, or is this package being considered in isolation? If isolated, the contract gives us little.
  2. Does the store create its table via DBAL directly, and how does that interact with Laravel migrations as the source of truth for schema?
  3. What is the message record shape (roles, tool calls, token metadata, attachments) and does it meet our audit/PII-retention obligations?
  4. What is the retention policy — is pruning our responsibility, and is there a supported API for it?
  5. Is there a supported DBAL version range (3.x vs 4.x) and PHP floor that matches our Laravel version?
  6. Who owns this if symfony/ai reorganizes the monorepo again?

Integration Approach

Stack fit

Concern Fit in a Laravel stack Action
Doctrine DBAL Native; already a transitive dependency in most apps Reuse existing connection, do not add a second
MessageStoreInterface Not Laravel-native Wrap in an app-owned contract + adapter
Schema DBAL-managed table vs Laravel migrations Make Laravel migrations authoritative; disable/verify auto-DDL
Symfony AI Chat runtime Not required if we only use the store Avoid pulling the full symfony/ai runtime
Observability None built in Instrument the adapter, not the package

Migration path

  1. Spike (2–3 days). Install doctrine/dbal and the bridge, point it at a scratch SQLite/Postgres database, and dump the generated schema. Confirm table naming, column types, index coverage on conversation identifier, and behaviour when sibling tables already exist.
  2. Contract extraction (3–5 days). Define an application-level MessageStore interface, implement an adapter delegating to DoctrineDBALMessageStore, and bind it in a service provider. Every call site depends on the interface only.
  3. Schema ownership (2 days). Hand-author the Laravel migration to match the store's expectations exactly, then verify the store operates against the pre-created table rather than attempting its own DDL. This is the step that determines whether the package is usable in a shared database.
  4. Feature wiring (1–2 weeks). Route chat persistence through the adapter; add the pruning command and retention configuration at the same time, not later.
  5. Exit rehearsal (1 day). Write a second implementation of the interface against the Laravel query builder and run the contract test suite against both. If the swap is not a one-line binding change, the abstraction is wrong.

Compatibility

Pin the exact 0.x version and treat upgrades as code changes, not patch bumps — the "no significant changes" releases give no signal about internal refactors. Verify PHP and DBAL constraints against the target Laravel version before the spike; a DBAL 3 vs 4 mismatch will surface as an install conflict and is the most likely early blocker. There is no first-party Laravel service provider, so package discovery will not help.

Sequencing

Do the schema-coexistence test before the contract work. If the store cannot share a database with existing tables cleanly, the whole evaluation collapses to "build the twenty-line version ourselves," and the remaining steps are wasted.

Operational Impact

Maintenance

Low code volume, high process dependency. Because this is a monorepo split, patches arrive only when symfony/ai cuts a release; there is no independent maintenance lane. MIT licensing and the Symfony organisational backing reduce abandonment risk relative to a 1-star third-party package, but the 0.x cadence means breaking changes are permitted at any minor. Budget a recurring review of upstream changelogs, and pin versions in composer.json with a policy that upgrades happen on our schedule.

Support

Community-only. Issues and PRs are triaged in the parent repository, so our tickets compete with the entire Symfony AI backlog. There is no vendor SLA, no security-announcement channel specific to this package, and no documented compatibility matrix. For a regulated or customer-facing product, that means the internal team is the de facto maintainer.

Scaling

Relational message storage scales adequately for typical chat volumes (thousands to low millions of rows) provided the conversation identifier is indexed and reads are paginated. Two risks: unbounded growth, since nothing in the package appears to prune, and write amplification if every turn is a separate round trip. Plan for a scheduled retention job, an index on (conversation_id, created_at), and read routing to a replica if conversation replay becomes a hot path. Above roughly 10K messages/second, or for real-time streaming transcripts, a relational store is the wrong substrate regardless of this package.

Failure modes

  • Database unavailability becomes chat unavailability. There is no in-memory fallback; a DBAL exception surfaces as a failed conversation unless the adapter degrades gracefully.
  • Schema drift. If the store assumes a table shape and we evolve it via Laravel migrations, failures appear at write time, not deploy time. Add a schema assertion to CI.
  • Auto-DDL in production. Any implicit table creation against a shared database is an operational hazard; verify and disable.
  • Silent history loss. Without retention metrics, a misconfigured prune or a failed write is invisible until a user notices missing context.
  • Data-protection exposure. Chat transcripts are among the highest-PII artifacts a system holds; the package offers no encryption, redaction, or access control. That burden is entirely ours.

Ramp-up

Genuinely small — a mid-level engineer can read the implementation in an hour. The learning cost is not the package but the surrounding decisions: the Symfony AI message model, the DBAL connection lifecycle inside Laravel, and the retention/PII policy. Estimate one engineer-week to competent ownership including the adapter and the pruning job. The more important ramp-up is organisational: whoever owns this must also own the upstream-watch process, because nobody else will.

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.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle