Redeo Docs
DocsLADR / How to Add Persistent Memory

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.

yaml
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:

yaml
- 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:

yaml
- name: Tags
  type: slateRead
  from: { slate: Memory, folder: facts, file: core.md, metatag: tags }

Reading folder indexes (system metatag):

yaml
- 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:

yaml
- 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:

  • slateWrite runs after every execution of the step. It extracts JSON and validates against match. 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:

bash
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:

bash
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.