PROTOCOL 06 / MEMORY

Memory, Recall and SQLite Persistence

1–2 sessions Foundation Eden research series

Learning outcomes

  • Separate persistence from learning
  • Classify memory types
  • Track provenance and time
  • Store memories in SQLite
  • Retrieve relevant context
  • Restore state safely

1. What does it mean to remember?

Adam finds water at (7, 2), the program closes and the next session begins tomorrow. Ollama does not automatically retain that experience. The application must store it and deliberately retrieve it when it becomes relevant.

  • Persistence means data survives process shutdown.
  • Memory means an agent can retain and retrieve prior information.
  • Observable learning means prior information changes later behaviour.

A successful SQLite insert proves persistence only. Demonstrating learning requires a behavioural comparison.

2. State, events and memory are different records

World state says what is true now. An event says what happened at a particular tick. A memory says what an agent retains from an observation, result, message or inference. A memory may be incomplete or outdated.

EVENTWater observedTick 12, (7, 2)
POLICYWorth retaining?Importance rule
MEMORYEpisode storedSource + time
RECALLRelevant contextSelected, not dumped

Three useful memory classes

  • Working memory: current objective, recent observation and pending tool call.
  • Episodic memory: a specific experience tied to a tick and source.
  • Knowledge: information synthesised from multiple experiences.

3. Preserve provenance and time

“I saw water” and “Eve told me there is water” are not equivalent evidence. Record a source such as direct_observation, tool_result, agent_message or inference. Keep the observed tick and, later, a confidence or validity field.

memory = { "agent_id": "adam", "kind": "episodic", "content": "Observed water at (7, 2)", "source": "direct_observation", "observed_tick": 12, }
HISTORICAL, NOT CURRENT

If the water disappears at tick 30, the tick-12 memory remains historically correct. Mark it stale or verify it; do not rewrite the past.

4. Create the first SQLite repository

from pathlib import Path import sqlite3 DB_PATH = Path("data/eden.db") DB_PATH.parent.mkdir(parents=True, exist_ok=True) with sqlite3.connect(DB_PATH) as connection: connection.execute(""" CREATE TABLE IF NOT EXISTS memories ( id INTEGER PRIMARY KEY, agent_id TEXT NOT NULL, observed_tick INTEGER NOT NULL, kind TEXT NOT NULL, content TEXT NOT NULL, source TEXT NOT NULL ) """) connection.execute( "INSERT INTO memories " "(agent_id, observed_tick, kind, content, source) " "VALUES (?, ?, ?, ?, ?)", ("adam", 12, "episodic", "Water at (7, 2)", "direct_observation"), )

Use parameters, not string interpolation. Hide SQL behind a repository such as MemoryRepository so the agent does not own connection details.

5. Retrieve useful context

Do not place every stored memory in the prompt. Filter by agent, type, recency, location or keyword; apply a strict limit; then format a bounded context. Retrieval is part of application policy and must be testable without Ollama.

6. Snapshot the world separately

World restoration and agent memories have different authority. A snapshot serialises current world state and is restored through validation. Memories remain historical records. Keep SQLite work off the Tkinter thread and use short transactions.

EXPERIMENT A

Persist without AI

Insert and query one episode using sqlite3.

EXPERIMENT B

Build the repository

Move SQL behind typed methods.

EXPERIMENT C

Select context

Retrieve only Adam's three most relevant memories.

EXPERIMENT D

Restart

Restore a world snapshot and preserve its separate memories.

Protocol completion

After restart, Adam can recover a sourced memory of water and use it in a later decision. You can explain why this demonstrates persistence and memory, but not necessarily general learning.