Memory System
Talon maintains persistent memory across four layers. Each layer has a different durability, mutability, and access pattern. Together they give agents durable context that survives session boundaries, daemon restarts, and context window rotations.
The four layers
Section titled “The four layers”| Layer | Storage | Description |
|---|---|---|
| Transcript | messages table | Canonical message log, append-only |
| Working memory | In-prompt context | Recent message window included in agent prompts |
| Thread notebook | Filesystem | Human-editable per-thread notes |
| Structured memory | memory_items table | Extracted facts and summaries, agent-managed |
Transcript
Section titled “Transcript”Every inbound and outbound message is persisted to the messages table. This is the source of truth for what was said. It’s append-only — messages are never modified or deleted. The transcript is what session-summarizer reads when creating context summaries.
Working memory
Section titled “Working memory”When an agent run starts, Talon assembles the in-context prompt. This includes the most recent N messages from the transcript verbatim. The count is configurable via context.recentMessageCount. This is the agent’s immediate short-term view of the conversation.
Thread notebook
Section titled “Thread notebook”Each thread gets a writable directory at data/threads/<thread_id>/. The agent can read and write files here via fs.read and fs.write capabilities. This is useful for structured notes, scratch work, or human-readable summaries that you want to inspect or edit directly.
Structured memory
Section titled “Structured memory”The memory_items table holds extracted facts, session summaries, observation logs, and freeform notes. The agent writes to it via memory_access.
| Type | Purpose |
|---|---|
fact | Discrete pieces of information (“user prefers JSON output”) |
summary | Session summaries created by session-summarizer |
observation | Dated decision-log entries created by session-observer |
note | Freeform notes the agent wants to retain |
All items are scoped to a thread. An agent in thread A cannot read or write memory items from thread B.
Using memory_access
Section titled “Using memory_access”The memory_access host tool is the agent’s interface to structured memory. Required capability: memory.access:thread.
# write a factmemory_access({ operation: "write", key: "user-format-preference", value: "prefers markdown tables", namespace: "fact"})
# read it backmemory_access({ operation: "read", key: "user-format-preference"})
# list all factsmemory_access({ operation: "list", namespace: "fact"})Memory retrieval
Section titled “Memory retrieval”The memory-retriever sub-agent provides semantic search over memory items. It uses keyword matching combined with LLM reranking to surface relevant facts for a given query.
subagent_invoke({ name: "memory-retriever", input: { query: "what does the user prefer?" }})Requires subagent.invoke capability and memory-retriever in the persona’s subagents list.
Named memory keys from summaries
Section titled “Named memory keys from summaries”When session-summarizer or session-observer produces a compression result, it can include structured memoryUpdates. The context roller extracts these and writes them as named keys to structured memory instead of anonymous blobs. For example, a summary might produce:
{ "memoryUpdates": { "work:current-project": "Building A2A protocol for Talon", "preference:output-format": "Prefers markdown tables" }}Each key-value pair is written via memory_access with the key as the memory key. This gives the agent stable, addressable memory entries that can be read back by key rather than requiring a semantic search. Over time, named keys build up a structured profile of the conversation.
Memory grooming
Section titled “Memory grooming”Over time, memory_items accumulates redundant or outdated entries. The memory-groomer sub-agent consolidates and prunes them. Call it periodically via a scheduled task:
# In a persona schedule- cronExpr: "0 3 * * *" promptFile: memory-groomingWhere personas/<name>/prompts/memory-grooming.md contains the instruction to invoke memory-groomer.
The default timeout for memory-groomer is now 180 seconds. That gives it enough room to work through larger memory stores without timing out mid-pass.
Observational memory
Section titled “Observational memory”PR #189 adds observational memory as a second context-compression mode. Instead of storing one summary item that gets replaced on each rotation, Talon can append observation items over time. This is useful for long-running threads where the agent needs a durable record of decisions, open work, and chronology.
Observation entries:
- are grouped by date
- use priority markers (
🔴,🟡,🟢) - preserve
currentTaskandsuggestedContinuationmetadata - are periodically consolidated by
session-reflectorwhen the log gets too large
That makes the memory layer more like an operational notebook than a rolling synopsis.
Thread workspace
Section titled “Thread workspace”Thread files persist at data/threads/<thread_id>/. This path is stable for the lifetime of the thread. Agents can use this for anything that benefits from filesystem persistence: drafts, research notes, generated files.
# example: agent writes a research summaryfs.write({ path: "data/threads/abc123/research-notes.md", content: "..." })