Episodic Memory
IntaGrin's memory system has three tiers already: working memory (checkpointed conversation history, memory.max_messages sliding-window eviction), long-term memory (a single evolving prose summary, state["long_term_memory"], regenerated by an LLM call whenever eviction happens — see 04_Shared_State_Redux.md), and semantic/knowledge memory (rag: — document/knowledge-base retrieval, unrelated to agent experience). episodic_memory: adds the fourth: discrete, structured, individually queryable event records — "user prefers window seats," "booking BK-4471 failed: card declined" — as opposed to the single blended long_term_memory prose summary, which can't be filtered or reliably retrieved for one specific fact.
(Procedural memory — learned skills/code — isn't included; it doesn't map onto this framework's declarative YAML/tool model.)
Episodic memory here is explicit and tool-driven, not automatic per-turn logging: an agent calls remember_episode when something notable happens, and later calls recall_episodes to look it back up.
memory:
type: "sqlite" # or "postgres" — episodic_memory is a no-op for redis/sliding_window/buffer/custom
episodic_memory:
embedding_model: "text-embedding-3-small" # defaults to match rag.embedding_model's default
scope: "session" # "session" (default) | "tenant" | "global"
default_limit: 5Setting episodic_memory: auto-registers two tools on every agent — the same "presence triggers registration" pattern rag: uses for search_knowledge_base:
remember_episode(event_type, content, tags=None)— records one event.event_typeis a short label you choose (e.g."preference","failure","booking") used later to filterrecall_episodes.tagsare optional free-form labels for finer-grained filtering.recall_episodes(query=None, event_type=None, tags=None, limit=None)— recalls previously recorded episodes. Omitqueryfor a cheap structured lookup byevent_type/tags/recency alone (no embedding call); passqueryfor embedding-based semantic similarity search over episode content.tags, if given, requires every tag to be present (AND, not OR).
Scope
episodic_memory.scope is independent of memory.shared_scope — a project might want the long_term_memory summary private per-session while episodic events are shared globally, or vice versa.
"session"(default): only thissession_id's own episodes."tenant": shared across every session under the same authenticated caller/tenant prefix (same convention asmemory.shared_scope: tenant)."global": shared across every session in the project, any tenant.
Storage
Episodes are stored in a sqlite/postgres episodes table — the same self-managing-schema convention shared_memory/run_logs already use, living in the same database as checkpoints. Unlike shared_memory's single row per scope (last-write-wins), the episodes table is append-only: remember_episode always inserts a new row, so nothing is ever silently overwritten.
Limitations
There is no retention or pruning policy in this version — episodes accumulate indefinitely for a scope. For a long-running, high-frequency use of remember_episode, plan for unbounded row growth the same way you would for any other unbounded application table.