Storage
Storage
Storage adapters provide Effect services for thread history and accepted work. Choose where that state lives, then connect the stores to your agent runtime.
| Backend | Use |
|---|---|
| In-memory | Conversations within one application Scope; isolated stores for tests |
| SQLite | Persistent history in a local Node.js database |
| PostgreSQL | A database shared by multiple processes, using your Effect SQL client |
| Cloudflare | SQLite owned by a Durable Object |
Keep @yielded/agent and its adapters on the same release. See
installation and compatibility
for the matching Effect and model provider packages.
Connect storage to execution
Section titled “Connect storage to execution”Use InMemory.layer for conversations that live with your application.
For history that survives a restart, connect a database’s ThreadStore to
PersistentHistory.layer and provide it to AgentRuntime:
flowchart LR
accTitle: Persistent history storage
accDescr: AgentRuntime uses PersistentHistory, which uses a ThreadStore backed by a database.
runtime["AgentRuntime"] --> history["PersistentHistory"] --> store["ThreadStore"] --> database["database"]The SQLite and PostgreSQL guides show the complete Layer wiring. Successful Runs are retained; interrupted execution is not resumed. Reuse a thread ID to continue its conversation. See Threads for history behavior.
Durable execution also needs a SubmissionLedger, a SettlementPublisher, registered agents,
and a host that drives recovery and pending work. The publisher belongs to the same storage owner
as the journal and ledger: it checks settlement authority and appends the canonical terminal fact
atomically. RunStorage.layer() requires this adapter service; independently supplied stores do
not provide a non-atomic fallback. The Node.js and
Cloudflare hosts assemble those pieces with their storage.
For another host, see custom durable runtime composition.
Storage alone does not start workers or recover unfinished Runs.
Back up or change record formats
Section titled “Back up or change record formats”A Thread keeps one canonical order and producer fence throughout its lifetime. Storage rotates complete batches into bounded ranges; archiving a range preserves exact record identities and digest anchors. Compaction changes the model view, independently of physical storage. SQL adapters verify archive contents and publish their locator before removing hot payload copies.
streamExport({ threadId }) acquires ThreadExportSource and yields snapshot-bound pages of
canonical batches, immutable admissions, accepted commands, and retained deliveries. Pass those pages to the local ThreadImport
service through reencodeThread(source), or save the NDJSON archive with the admin CLI. Import
validates every page and referenced fact, applies destination admission constraints, and publishes
atomically into an empty Thread. Missing dependencies leave the destination unchanged. Historical
closed workers and children remain evidence; unsupported live foreign obligations refuse transfer.
Claims, leases, checkpoints, and recovery caches are not transferred. Unresolved effects retain
their uncertainty.
Provide ThreadExportSource.layer() from the source ThreadStore, or SQLite’s read-only
exportSourceLayer({ filename }). Bind that source separately from the destination import Layer
when transferring between stores.
Appends and imports refuse a batch whose identities and references cannot fit its complete 32 MiB transfer page, even when its canonical payload fits the 16 MiB batch bound. Native adapters also reserve page space for the complete admission, accepted command, or delivery fact before acknowledging it, including repeated identities and transfer metadata. Oversized fresh facts fail before mutation; replay of accepted work preserves its original Receipt.
The unreleased protocol accepts only fresh layout-21 stores and effect-agent/thread@3 records.
Predecessor stores fail before mutation; no older layout upgrade or archive converter is included.
See the operator procedure and limits.
Build another adapter
Section titled “Build another adapter”@yielded/agent-storage-sql contains shared SQL implementations for thread history,
submissions, schedules, subscriptions, message delivery, and activity progress.
SQLite and PostgreSQL use this core; Cloudflare reuses the helpers that fit Durable Objects.
An adapter supplies the database-specific initialization, transactions, and error handling
around an Effect SqlClient. Start with the shared SQL package reference
and storage adapter contracts.