Memory
Steelframe has three memory layers. Do not conflate them:
| Layer | Question | Store |
|---|---|---|
| Session memory | What happened | Agent WAL + SQLite index |
| Committed memory | What is true | Git (docs/memory/) |
| Config / credentials | Host paths and secrets | Config table |
Committed memory outranks retrieve when they conflict.
Session memory
Section titled “Session memory”The agent persists coordinator decisions, worker prompts/outcomes, and operator Chat turns as an append-only write-ahead log on local disk or S3 (RustFS). SQLite holds pointers for search only — summaries, links to issue/PR/SHA/paths, and FTS. Wipe the DB and the agent rebuilds the index from the WAL on startup if wal/head.json exists.
Blobs are redacted on write: PEM blocks, bearer tokens, ghp_, AKIA…, and the master key never land in a blob.
Storage config:
| Key | Default | Meaning |
|---|---|---|
memory_s3_endpoint | empty | Empty uses the file backend under the data dir; set it to RustFS in production |
memory_s3_bucket | steelframe-memory | Bucket |
memory_s3_prefix | derived from github_repo | Object prefix |
memory_embed_model | bge-small-en-v1.5 | off/empty disables embed live |
memory_embed_cache_dir | /opt/steelframe/models | ONNX model cache |
memory_retrieve_limit | 8 | Default top-k chunks |
memory_retrieve_candidates | 50 | Max session packs to fetch |
Credentials for the store are the encrypted memory_s3 service (access key + secret); the file backend needs none.
Retrieve
Section titled “Retrieve”Retrieve is semantic search over session memory. It is shared: workers inject hits as prior context, and Chat answers from them.
- Derived vector packs live next to the WAL at
vec/{model_id}/session/{session_id}. SQLite keeps only pointers; vectors stay in the packs. - The default embedder is local BGE-small-en-v1.5 (384-d). Weights download lazily on first embed after the agent is running — not during
steelframe setuporagent install. - Retrieve filters sessions in SQLite first, then fetches a bounded candidate set, then ranks in-process with cosine. Pack GETs and the query embed share a short deadline.
- Workers inject the top chunks as a
Prior Steelframe context:block. Chat uses the same path with the ranking loop described in Chat.
If the embedder is unavailable, retrieve degrades to recency summaries (mode: prior_context) rather than failing a workflow. Workflows never fail because memory is down.
HTTP:
| Method | Path |
|---|---|
GET | /api/memory/sessions?issue=&pr=&path=&q= (q is FTS) |
GET | /api/memory/sessions/{id} |
GET | /api/memory/sessions/{id}/blob (plain text) |
GET | /api/memory/retrieve?q=&issue=&pr=&path=&fts=&limit= |
GET /api/memory/retrieve requires q (retrieve text, at most 2048 characters; empty or longer is 400). limit is capped at 32. mode is semantic or prior_context; fallback returns synthesized summary chunks with score 0.0.
Committed memory
Section titled “Committed memory”Committed memory is operator-approved truth in the repository:
docs/memory/README.md # index, precedencedocs/memory/general.md # cross-cuttingdocs/memory/delivery.md # pickup, PRs, promotedocs/memory/retrieve.md # session memory / Chat retrievedocs/memory/harness.md # pack, overlay, convergeIt changes only through a labeled issue and a PR:
- In Chat, assert a lasting fact or correct retrieve.
- Chat uses
file_memoryand files an issue with pickup labels +steelframe:from-tui+steelframe:memory. - The body names the fact and the target file under
docs/memory/. - Pickup runs
task_lifecycle; the implement worker loads thecommitted-memoryskill, edits onlydocs/memory/, and opens a feature-branch PR. - After merge, every worker sees it on the next clone.
Never store credentials, PEM, tokens, host paths, or STEELFRAME_MASTER_KEY here.
Rebuild
Section titled “Rebuild”steelframe agent memory-rebuild replays the WAL into the SQLite index and rebuilds derived vector packs. Change the embed model means a new model_id prefix and a rebuild.