Storage and restarts
Introduction
Section titled “Introduction”The local backend keeps everything on the user’s machine: one SQLite file for conversations and runs, and plain files for configuration and uploads. This page says where each thing lives, so you know what to back up, what a user may edit by hand, and what a restart does to a run.
What is stored
Section titled “What is stored”One SQLite file, <dataDir>/local.db, holds nearly everything:
| Data | Tables |
|---|---|
LangGraph checkpoints (the stock SqliteSaver of @langchain/langgraph-checkpoint-sqlite) |
checkpoints, writes |
| Conversation catalog | conversations |
| Run events | run_events |
| Background tasks | background_tasks |
Token usage, served at /usage as on the gateway |
usage_calls |
Schedules and their runs, served at /schedules |
schedules, schedule_runs |
The server keeps the same data in PostgreSQL; see Storage for every store and its port.
Deleting a conversation removes its row, its checkpoint rows, its schedule run row and the conversations its background tasks run on, in one transaction.
Agents, profiles, providers and skills are files under configDir. Uploaded images are files under <dataDir>/attachments. Fork, edit-and-regenerate and interrupts behave as on the gateway.
Editing agents by hand or in the editor
Section titled “Editing agents by hand or in the editor”createFileAgentDefinitionStore(dir) (@pilotoo/agent-runtime) is a source and a store in one. It reads <dir>/<id>.yaml (or .yml) and writes the same format, so any host with a folder of agents can offer the editor by passing it as both agentDefinitionSource and agentDefinitionStore.
The local module does exactly that over <configDir>/agents, and sets AGENT_MANAGER_ROLES=owner so the fixed local identity manages agents. It also turns on every config tool over the same folder (a host’s configTools replaces them) and sets SCHEDULE_ROLES=owner so the local owner schedules runs.
- The file is the truth. The version is the file’s modification time, so a hand edit and an editor save bump it alike, and nothing needs a restart.
- No system agents here. The store reports its agents with
source: 'database'(the wire word for an editable record), so the editor treats every file as the user’s own, shipped ones included. - Writes go to a temporary file in the folder and are renamed over the target. Writes of one process are serialised. Deleting or drafting the last active agent is
LastActiveAgentError(409). Another process writing the folder at the same moment is not covered. - Ids are file names:
[A-Za-z0-9][A-Za-z0-9._-]*, at most 200 characters, no... Create refuses anything else (InvalidAgentFileNameError); update and delete answer 404.
Keeping uploaded images
Section titled “Keeping uploaded images”createFileAttachmentStore(dir) (@pilotoo/agent-runtime, beside createS3AttachmentStore) is the AttachmentStore over a folder. The local module passes it over <dataDir>/attachments, so uploads work with no bucket. A host’s own attachmentStore, null included, replaces it. The contract, limits and HTTP answers are the same as on the server (Attachments).
- One file per attachment,
<id>.att: a JSON line (owner, display name, type) and then the bytes. A single rename publishes both, so no file is ever served without an owner. Uploads write a temp file in the folder (mode 600), fsync, then rename; a failure removes the temp file. The folder (mode 700) is created on the first upload. - Ids are lowercase UUIDs. Any other id answers as unknown before the disk is touched, so no id can name a path. Another owner’s id answers like a missing one. An error other than “missing” (permissions, a directory in the way) is raised, not hidden.
- Nothing expires. Deleting a conversation does not delete its images.
What a restart does
Section titled “What a restart does”Conversations and checkpoints survive a restart.
- A run in flight when the process stopped is not resumed. The next reader of its thread gets its replay, closed by exactly one
RUN_ERRORwith codeRUN_INTERRUPTED, which a UI should render as an interrupted turn. - A run paused on
ask_humanor a client tool stays pending and resumes after the restart. - A background task that was running is marked
interrupted, and its parent agent is told in a turn of its own. - The protocol has no “last seen sequence”, so a reader receives the whole replay and finds what it already showed as its prefix.
Next steps
Section titled “Next steps”- Hosting it from another app for choosing and seeding
configDir. - Subagents for background tasks.
- Security for who can reach the server.