Symfony Session Persistence
packages/symfony owns the framework-facing persistence seam for native Cognesy\Agents sessions.
The boundary is:
Cognesy\Agents\Session\Contracts\CanStoreSessionsremains the storage contractCognesy\Agents\Session\SessionRepositoryandCognesy\Agents\Session\Contracts\CanManageAgentSessionsremain the runtime-facing servicespackages/symfonyowns which built-in adapter is selected by config and where persisted state lives by default
CanStoreSessions with their own service if they want Doctrine, Redis, or another backend later.
Config Model
The package now defines an explicitinstructor.sessions subtree:
memory: process-local and ephemeral, useful for tests and simple CLI flowsfile: JSON-backed persisted sessions with per-session file locking and optimistic version checks
driver->storesession_store->store- top-level
directory->file.directory
Why The First Persisted Adapter Is File-Based
Symfony needs a persistence baseline that is:- zero-dependency
- portable across CLI, HTTP, and Messenger workers
- explicit about where state lives
- compatible with resumable workflows immediately
packages/agents, includes lock files plus version checks, and avoids forcing Doctrine-specific schema or bundle assumptions into the first supported Symfony path.
That makes the current ownership split clean:
packages/agentskeeps the reusable session model and storage contractpackages/symfonyselects and wires the supported framework default
Storage Conventions
Withstore: file, the package persists one JSON payload per session:
- session payload:
<session-id>.json - lock file:
<session-id>.lock
Resume Flow
The package-owned Messenger entrypoint already composes with persisted sessions:Conflict Semantics
Persisted session writes use optimistic concurrency semantics. That means:- create requires version
0 - each successful save increments the stored version
- stale writes fail with
SessionConflictExceptioninstead of silently winning