Memory System

Memory Flows

How data moves through the Agent Memory Schema — from session close through keyword search to targeted retrieval.

Flow 1

Write — How memories get created

Three write paths, one per memory type. All writes are initiated by MCP tool calls — never direct DB access.

SESSION CLOSE WRITE PATH 1. SESSION ENDS Sweep open threads and next steps first 2. RESOLVE ITEMS For each inherited thread or step: resolve/park/drop update_session_element 3. ATOMIC WRITE ONE call captures all session elements at once close_session() 4. SINGLE DB TRANSACTION session_headers session_decisions open_threads next_steps key_context + more returns session lineage_id for reference RULE: Nothing new goes to T4 or Letta blocks at session close. The Agent Memory Schema is the only write destination for han-solo work. WHY ATOMIC: A partial write (some tables but not others) leaves the session in an inconsistent state. One transaction = all or nothing.
Lesson write path
1 A pattern or gotcha is identified during the session — record it as it happens, not at close
2 record_lesson(agent_id, task_type, lesson_kind, lesson, tags)
3 Written to lessons table — immediately available for keyword matching at wake
4 Status defaults to active. Deprecated via deprecate_lesson() when superseded
Touchstone write path
1 A significant moment or relationship event occurs — worth anchoring in Ren's memory as felt experience
2 record_touchstone(agent, type, title, felt_weight, fact, texture, why_it_matters)
3 Written to touchstones table with the emotional register intact
4 Optionally linked to a session via link_touchstone(touchstone_id, session_lineage)
Conversation write path
1 A design or architecture discussion deserves persistence — not just the outcome but the thread
2 create_conversation(title, topic, topic_tags) — creates the container
3 add_conversation_entry(conversation_id, entry_type, author, body) — appends each turn
4 Entries are append-only. The conversation accumulates; nothing is revised or overwritten
Flow 2

Retrieve — How Ren wakes up

One call. One round-trip. Everything needed to start working — no scanning, no reconstruction from fragments.

SESSION OPENS agent reads instructions first SINGLE MCP CALL get_memory_bundle() agent_id + depth + intent DB QUERIES (han-solo-data) current build · latest session lessons · touchstones · convos BUNDLE RETURNED Full context object — structured, ready to read, one round-trip BUNDLE CONTENTS (depth="cold_start") Work state → Current build record → In-flight work slices → Active build phases Intent matching → Gotcha lessons relevant to stated intent (only if intent passed) Session continuity → Latest session summary → ALL open threads → Pending next steps → Recent decisions → Key context items Conversations → Active conversation threads Carried understanding → Active lessons (all agent_id + general) → Key touchstones (significant moments) Letta core (separate) T1 blocks always loaded by Letta at Ren's start WHY ONE CALL Before the cutover, Claude scanned T4 handoff entries, searched transcripts, and reconstructed context from multiple partial sources. One structured read means nothing gets missed, context is always current, no drift.
The sweep rule at session close: The open threads and next steps that appear in the wake bundle must be read back — from the bundle or a fresh pull if stale — before writing the close. Anything this session's work actually resolved must be marked via update_session_element before the atomic close_session call. This prevents closed items from accumulating indefinitely. The incident that prompted this rule: 43 working-state items on 2026-06-11, a third already done.
Flow 3

Search — Keyword discovery to targeted retrieval

When the wake bundle isn't enough — diving into history to find a specific session, decision, or conversation.

1. QUESTION "What did we decide about X?" 2. KEYWORD SEARCH search_sessions("X") AND-matched across session summaries and elements 3. RESULTS LIST Matching sessions with title · date · agent · lineage_id → Pick the right one 4. FULL RECORD get_session(lineage_id) All elements — decisions, threads, context, steps — for that session SEARCH TOOLS BY TARGET TOOL SEARCHES THEN GET WITH search_sessions(q) session summaries and all elements get_session(lineage_id) search_conversations(q) conversation title + topic + entries get_conversation(id) get_lessons(agent_id, task_type) lessons by agent and task type (no separate search) returns directly — no second call
AND-matched keyword search: The Agent Memory Schema uses AND-matching — all query terms must appear in the record. This is intentionally different from Letta's semantic (pgvector) search. Keyword search is predictable and fast; you know exactly what you're looking for when you use it. For fuzzy or concept-based search across Ren's archival memory, use archival_memory_search (Letta Store 1).

T4 search (framework artifacts)

Framework project artifacts in the T4 store use the same AND-keyword pattern via search_t4(query, project_slug). Narrowing by project_slug prevents cross-project noise. Full record via get_t4_entry(project_slug, entry_type, entry_id).

Related docs