Adding Features
How to Add Persistent Memory
How to Add Persistent Memory
Persistent memory lets a ladder learn from prior calls. This guide shows how to declare a slate, read from it, and write validated data to it. Three steps: declare the slate schema, add a slateRead field, add a slateWrite block.
Step 1: Declare the slate
Add a slates: block to the top-level config. A slate has folders; each folder has a token limit and optional files.
slates:
- title: Memory
folders:
- name: facts
tokenLimit: 500
evictionPolicy: FIFO
files:
- { name: core.md, init: blank }
- name: lessons
tokenLimit: 300
evictionPolicy: LRU
files:
- { name: failures.md, init: blank }
- { name: wins.md, init: blank }The tokenLimit on each folder caps how many tokens it can hold. When the limit is exceeded, the evictionPolicy determines what gets removed: FIFO (oldest first), LRU (least recently used), or reject (refuse the write).
The init: field seeds the file at config time. blank starts empty; a literal string starts with content.
Step 2: Read from the slate
Add a slateRead field to any step that should see prior memory:
- id: answer
fields:
- { name: Question, type: text, from: input.context }
- name: KnownFacts
type: slateRead
from: { slate: Memory, folder: facts, file: core.md }
fallback: "No prior facts available."
systemPrompt: "Answer the question. Use KnownFacts if relevant."The fallback: is consulted when the slate file is empty (first call) or the read fails. Without a fallback, empty reads produce an empty string in the prompt.
Reading metatags instead of file contents:
- name: Tags
type: slateRead
from: { slate: Memory, folder: facts, file: core.md, metatag: tags }Reading folder indexes (system metatag):
- name: FileList
type: slateRead
from: { slate: Memory, folder: facts, metatag: index }The index metatag returns a JSON array of file names and sizes. The tree metatag returns a nested tree structure (controllable via depth:).
Step 3: Write to the slate
Add a slateWrite: block to any step that should persist findings:
- id: answer
fields:
- { name: Question, type: text, from: input.context }
- { name: KnownFacts, type: slateRead, from: { slate: Memory, folder: facts, file: core.md } }
systemPrompt: 'Answer. If you discover a durable fact, emit JSON {"fact": "..."}.'
slateWrite:
to: { slate: Memory, folder: facts, file: core.md }
field: fact
on: append
match:
type: object
required: [fact]
properties:
fact: { type: string, minLength: 5 }The match schema validates the LLM's JSON output. Only objects with a fact field (string, at least 5 characters) are persisted. The field: fact extracts the fact value before writing — so the slate receives the string, not the JSON object.
Write policies:
append(default): add to the end of existing content.overwrite: replace existing content entirely.mergeByKey: for JSON arrays, update items by a key field.
See Write Policies for details.
Schema-matched vs gated writes:
slateWriteruns after every execution of the step. It extracts JSON and validates againstmatch. No match = silent no-op.- Gated writes (
if: { then: { write: ... } }) write verbatim when a gate passes. No JSON extraction.
Use slateWrite when you want to persist validated structured data. Use gated writes when you want to persist raw text on a condition.
Verify it works
After saving the ladder, call it twice. The first call writes to the slate; the second call reads what was written.
Call 1:
curl http://localhost:8788/v1/local/memory-ladder/chat/completions \\
-H "Authorization: Bearer $LADR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"model": "gpt-4o",
"messages": [{"role": "user", "content": "What is the capital of France?"}]
}'The step runs, answers the question, and if it emitted valid JSON with a fact field, that fact is appended to core.md.
Call 2:
curl http://localhost:8788/v1/local/memory-ladder/chat/completions \\
-H "Authorization: Bearer $LADR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{
"model": "gpt-4o",
"messages": [{"role": "user", "content": "What is the capital of Germany?"}]
}'On this call, the KnownFacts field resolves to the content written in call 1. The prompt includes the prior fact about France. The step sees accumulated knowledge.
Inspecting the slate in Foundry: Navigate to the ladder, open the Slate Inspector tab, and view the file contents. Each file is plain text or JSON, inspectable at any time.