LIVE DEMO → Home Product
Features Use Cases Compare Enterprise
Docs
Documentation Quickstart MCP Server Integrations Benchmark
Pricing Blog DASHBOARD → LOG IN →
← All articles
GUIDE · MEMORY ARCHITECTURE

Episodic, Semantic, Procedural — Choosing the Right Memory Type for Your AI Agent

Mar 12, 2026 · 7 min read

The three memory types that mirror human cognition — and why using the wrong one degrades your agent's recall precision by up to 40%.

Most developers who add memory to an AI agent start by storing everything as the same type. One blob of text, one vector, one table. It works — until it doesn't.

The problem surfaces during recall. When a user asks "what did we discuss last time?", you want episodic context — the narrative of past interactions. When they ask "what's my subscription plan?", you want semantic facts. When your agent is about to generate code, you want procedural rules — conventions, constraints, patterns.

Mix them all together and your similarity search returns a soup of everything. Kronvex supports three memory types, each optimized for different retrieval patterns. Here's how to use them.


The three types

📖
EPISODIC
Events, interactions, narrative. "What happened last session." Time-ordered, context-rich.
🧠
SEMANTIC
Facts, profiles, knowledge. "What is true about this user/world." Timeless, structured.
⚙️
PROCEDURAL
Rules, workflows, constraints. "How to behave in this context." Stable, prescriptive.

This mirrors how human long-term memory is structured, as described by Endel Tulving's model of memory systems. Your agent should work the same way.


Episodic memory — the event log

Episodic memories are timestamped interactions. Use them to store what happened in a session — what the user said, what problem they had, what was resolved.

📖
When to use: After each conversation turn, support ticket resolution, sales call, or any time-sensitive interaction that should influence future sessions.
PYTHON
# After resolving a support ticket
kx.remember(
    "User reported login issue on mobile app. Root cause: cached "
    "OAuth token from old device. Resolved by clearing app data. "
    "User is satisfied.",
    memory_type="episodic",
    session_id="ticket_4821",
    metadata={"resolved": True, "category": "auth"}
)

Episodic memories are naturally TTL candidates. A support ticket from 6 months ago is less useful than one from last week. Use ttl_days=180 to auto-expire stale events while pinning critical ones.

PYTHON
# Expires in 90 days, but keeps the fact it was a VIP issue
kx.remember(
    "VIP client (ACME Corp) escalated billing dispute to CEO.",
    memory_type="episodic",
    ttl_days=90,
    pinned=True,   # pinned = survives even past ttl
    metadata={"vip": True, "escalation_level": "ceo"}
)

Semantic memory — the knowledge base

Semantic memories are facts about the world or the user that don't expire with time. They're not about events — they're about states: what plan someone is on, what language they prefer, what their role is.

🧠
When to use: User profiles, preferences, account attributes, domain knowledge, and any fact that should persist indefinitely regardless of session.
PYTHON
# User profile facts — no TTL, these are permanent
kx.remember(
    "User is a senior backend engineer, 8 years experience. "
    "Prefers Python (FastAPI) and Go. Hostile to unnecessary abstractions.",
    memory_type="semantic",
    pinned=True
)

kx.remember(
    "User's company: Dataflow Inc, Series A startup, 25 employees, "
    "building an AI-powered data pipeline tool.",
    memory_type="semantic",
    pinned=True
)

Semantic memory is what makes an agent feel like it knows you. When a user asks "what stack should I use?", the agent doesn't ask for context — it already has it.

Updating semantic facts

A key challenge: semantic facts change. Users switch plans, companies pivot. The simplest pattern is to store the update as a new memory with higher recency weight — the confidence scoring system (similarity×0.6 + recency×0.2 + frequency×0.2) will naturally surface the most recent version first.

For critical updates, delete the outdated memory explicitly before storing the new one.


Procedural memory — the rulebook

Procedural memories are instructions the agent should follow. They're not about events or facts — they're about behaviour. Think of them as injected system prompt fragments that persist across sessions.

⚙️
When to use: Architecture decisions, coding conventions, workflow rules, communication guidelines, compliance constraints, team-specific processes.
PYTHON
# Codebase conventions — shared across team
kx.remember(
    "We use CQRS for all write operations. Commands go through "
    "the CommandBus, queries use direct repository calls. Never mix.",
    memory_type="procedural",
    pinned=True
)

kx.remember(
    "All API responses must follow RFC 9457 (Problem Details). "
    "Error format: {type, title, status, detail, instance}.",
    memory_type="procedural",
    pinned=True
)

Procedural memories are almost always pinned and have no TTL — architectural decisions don't expire. They change only when intentionally updated.


Choosing the right type: a decision table

SCENARIO TYPE TTL? PINNED?
User resolved a support ticket episodic Yes (90–180d) No
User mentioned their tech stack semantic No Yes
Sales call notes, objections raised episodic Yes (30–60d) No
User is on Pro plan, 3 agents semantic No Yes
Architecture decision: use event sourcing procedural No Yes
Tutoring session: student struggled with recursion episodic Yes (60d) No
Student's mastery level: recursion = intermediate semantic No No (update regularly)
Coding convention: no any in TypeScript procedural No Yes
Renewal intel: contract up in 30 days episodic Yes (30d) No

Filtering by type during recall

Memory type filtering is one of the most underused features. When you know the kind of memory you need, filtering by type reduces noise and improves the confidence scores of your results.

PYTHON
# Before generating code: only want rules
conventions = kx.recall(
    "error handling in API responses",
    memory_type="procedural",
    top_k=3
)

# Before responding to a support message: want event history
history = kx.recall(
    "past issues with this user",
    memory_type="episodic",
    session_id=user_id,   # scoped to this user's thread
    top_k=5
)

# For personalisation: want profile facts
profile = kx.recall(
    "user preferences and background",
    memory_type="semantic",
    top_k=5
)
⚠️
Avoid recalling without a type filter for large agents. At 1,000+ memories, unfiltered queries become noisy. Separate your retrieval calls by type and merge the context blocks before injecting into your system prompt.

Combining types in inject-context

For most use cases, /inject-context handles the merge automatically — it returns the top-K most relevant memories across all types. But for power users, you can build a richer context block manually:

PYTHON
def build_system_prompt(user_message: str, agent_id: str) -> str:
    kx = Kronvex(agent_id=agent_id)

    # Fetch each type in parallel (async version available)
    rules    = kx.recall(user_message, memory_type="procedural", top_k=3)
    facts    = kx.recall(user_message, memory_type="semantic",    top_k=4)
    history  = kx.recall(user_message, memory_type="episodic",    top_k=3)

    # Build context sections
    sections = []
    if rules.results:
        sections.append("## Rules & Conventions\n" +
            "\n".join(f"- {r.memory.content}" for r in rules.results))
    if facts.results:
        sections.append("## User Profile\n" +
            "\n".join(f"- {r.memory.content}" for r in facts.results))
    if history.results:
        sections.append("## Recent History\n" +
            "\n".join(f"- {r.memory.content}" for r in history.results))

    context = "\n\n".join(sections)
    return f"[CONTEXT]\n{context}\n[/CONTEXT]\n\nYou are a helpful assistant."

What happens if you mix types?

Storing everything as episodic is the most common mistake. It works at small scale but creates two problems at scale:

The fix is straightforward: classify at store time, filter at recall time. It's one extra parameter that pays off compoundingly as your memory store grows.


TL;DR

Start building with 100 free memories

Three memory types. One API. No infrastructure to manage.

Get your free API key →
Related articles
Free access
Get your API key

100 free memories. No credit card required.

Already have an account? Sign in →