Part VI: Agentic AI
Chapter 22: AI Agent Foundations

Agent Memory Systems

"I remember everything you told me. The hard part is knowing which memories matter right now."

Agent X Agent X, Nostalgic but Context-Limited AI Agent
Big Picture

Memory is the difference between an agent that solves one task and an agent that grows more capable over time. The agent loop from Section 22.1 describes a single cycle of perceive, reason, and act. But real tasks require the agent to remember what it tried before, recall what the user prefers, and avoid repeating past mistakes. This section covers the three types of agent memory (episodic, semantic, and procedural), practical memory architectures like MemGPT that treat context management as a virtual memory problem, and the retrieval-augmented memory systems built on the vector database infrastructure from Chapter 19.

Prerequisites

This section builds on agent foundations from Section 22.1. Familiarity with vector databases from Chapter 19 will help with the retrieval-augmented memory discussion.

1. Why Agents Need Memory

A stateless agent forgets everything between turns. It cannot recall what tools it used five minutes ago, what the user preferred last week, or what strategies failed yesterday. Memory transforms an agent from a reactive system into one that learns, adapts, and improves over time. Without memory, every interaction starts from scratch, forcing the agent to re-derive context that should already be available.

Agent memory systems fall into three broad categories borrowed from cognitive science. Episodic memory stores specific past experiences: what happened, when, and in what context. Semantic memory captures general knowledge and facts extracted from those experiences. Procedural memory encodes learned skills and action sequences that the agent can reuse. Each type serves a different purpose in the agent loop, and effective agents typically combine all three.

The fundamental challenge is fitting useful memory into a finite context window. A model with a 128K token context cannot store every past interaction verbatim. Memory systems must therefore implement strategies for compression, retrieval, and forgetting. This is analogous to how human memory works: we do not remember every detail of every conversation, but we can recall relevant information when cued by context.

Key Insight

The best agent memory systems are retrieval-augmented, not buffer-based. Instead of cramming a fixed window with recent messages, they store memories in a vector database and retrieve only what is relevant to the current task. This mirrors how human memory works: we recall based on relevance, not recency alone. MemGPT formalized this insight by treating context management as a virtual memory problem, paging information in and out of the LLM's context window as needed.

MemGPT and Virtual Context Management

MemGPT (now called Letta) introduced a breakthrough concept: treating the LLM's context window like an operating system treats RAM. Just as an OS pages data between RAM and disk, MemGPT pages information between the model's active context and an external store. The agent can explicitly decide to save important information to long-term storage, retrieve relevant memories when needed, and discard outdated context to make room for new information. This gives the agent an effectively unlimited memory capacity within a fixed context window.

The architecture has three tiers. The main context is the LLM's current prompt, containing the system message, recent conversation turns, and currently relevant memories. The recall storage holds the full conversation history, searchable by recency or content. The archival storage is a vector database holding long-term facts, preferences, and learned procedures. The agent issues memory management function calls (save, search, delete) alongside its regular tool calls.

# Simplified MemGPT-style memory management
from letta import create_client

# Create a Letta client with persistent memory
client = create_client()

# Create an agent with memory tiers
agent = client.create_agent(
 name="research_assistant",
 memory_blocks=[
 {"label": "user_preferences", "value": "User prefers concise answers with code examples."},
 {"label": "project_context", "value": "Working on a Python ML pipeline for text classification."},
 ],
 tools=["web_search", "code_execution", "memory_save", "memory_search"],
)

# The agent can now manage its own memory
response = agent.send_message(
 "Remember that I prefer PyTorch over TensorFlow for new projects."
)
# Agent internally calls memory_save to persist this preference

# Later, when asked about frameworks, it retrieves the preference
response = agent.send_message(
 "What framework should I use for my next model?"
)
# Agent calls memory_search, finds the PyTorch preference, responds accordingly
Code Fragment 22.2.1: This snippet demonstrates MemGPT-style tiered memory management using the Letta client SDK. The create_agent call configures working memory (system prompt context), archival memory (vector-indexed long-term store), and recall memory (conversation history), with explicit insert and search operations on each tier.

Mem0 and A-MEM: Zettelkasten for Agents

Mem0 provides a simpler, API-first approach to agent memory. Rather than requiring the agent to manage its own memory explicitly, Mem0 automatically extracts and stores key facts from conversations. When the agent needs context, Mem0 retrieves relevant memories based on the current query. This reduces the cognitive burden on the agent itself, letting the memory layer operate as a transparent middleware.

A-MEM takes a different approach inspired by the Zettelkasten method, a note-taking system where ideas are stored as atomic, interconnected notes. Each memory is a self-contained unit with explicit links to related memories, forming a knowledge graph. When the agent retrieves a memory, it also gets the connected context, enabling richer reasoning about relationships between past experiences. This is particularly useful for research agents that need to synthesize information across many sources.

Real-World Scenario: Customer Support Agent with Persistent Memory

Who: A platform engineering team at a B2B SaaS company with 3,000 enterprise customers.

Situation: The AI support agent handled 800 tickets per day but treated every interaction as a fresh conversation, even when the same customer returned within hours of a previous ticket.

Problem: Customers with complex configurations (custom SSO, enterprise billing, multi-region deployments) had to re-explain their setup on every ticket. Repeat customers rated the agent 2.1 out of 5 for helpfulness, and 40% of tickets included the phrase "as I already told you."

Decision: Rather than building a custom memory layer, the team integrated Mem0 as middleware. Mem0 automatically extracted key facts from each resolved ticket (billing plan, communication preference, infrastructure details) and stored them per-customer. On new tickets, relevant customer context was retrieved and injected into the agent's prompt before reasoning began.

Result: Resolution time dropped 35% because the agent stopped asking customers to repeat information. Repeat-customer satisfaction rose from 2.1 to 4.3 out of 5 within six weeks of deployment.

Lesson: Persistent memory transforms a support agent from a stranger into a colleague who remembers past conversations, and the biggest gains come from the simplest memories (customer preferences and environment details).

2. Episodic, Semantic, and Procedural Memory

Episodic memory stores timestamped records of specific interactions. When did the user last ask about deployment? What error message appeared during the last debugging session? These memories are retrieved by similarity to the current situation, enabling the agent to say "we encountered a similar issue last Tuesday" and apply the same resolution strategy. Implementation typically uses a vector store with metadata (timestamps, session IDs, outcome labels).

Semantic memory captures distilled facts and relationships. Rather than storing the full conversation where the user mentioned their database is PostgreSQL 15, semantic memory stores the fact itself: "user's database = PostgreSQL 15." This is more token-efficient and avoids the noise of raw conversation history. Knowledge graphs are a natural fit for semantic memory, with entities as nodes and relationships as edges.

Procedural memory records successful action sequences. If the agent discovered that deploying to staging requires running migrations first, then updating environment variables, then restarting the service, that procedure is stored and can be replayed in future deployments. This is the agent equivalent of muscle memory: learned skills that can be executed without re-deriving the steps each time.

Memory Retrieval Scoring.

Given a query q and a candidate memory m, the retrieval score combines three signals:

$$\operatorname{score}(q, m) = \alpha \cdot \operatorname{relevance}(q, m) + \beta \cdot \operatorname{recency}(m) + \gamma \cdot \operatorname{importance}(m)$$

where $\operatorname{relevance}(q, m) = \cos(\operatorname{embed}(q),\, \operatorname{embed}(m))$ is the semantic similarity between query and memory, $\operatorname{recency}(m) = \exp(-\lambda \cdot (t_{\text{now}} - t_{\text{access}}))$ applies exponential decay based on time since last access, and $\operatorname{importance}(m) \in [0, 1]$ is an LLM-assigned salience score capturing how significant the memory is. The weights $\alpha$, $\beta$, $\gamma$ control the balance between finding relevant, recent, and important memories.

Worked Example: Memory Retrieval Scoring

Suppose $\alpha = 1.0$, $\beta = 0.5$, $\gamma = 0.3$, and $\lambda = 0.02$ per hour. A query about "database connection errors" is compared against a memory recorded 48 hours ago with a cosine similarity of 0.82 and an LLM-assigned importance of 0.9.

Compare this with a less relevant memory (cosine 0.55) from just 2 hours ago with importance 0.4: score = $1.0 \times 0.55 + 0.5 \times \exp(-0.04) + 0.3 \times 0.4 = 0.55 + 0.480 + 0.12 = 1.150$. The older but more relevant memory wins, illustrating how the weighting scheme prioritizes semantic match and importance over raw recency.

import mem0

# Initialize Mem0 with different memory types
memory = mem0.Memory.from_config({
 "vector_store": {"provider": "qdrant", "config": {"url": "localhost:6333"}},
 "llm": {"provider": "openai", "config": {"model": "gpt-4o-mini"}},
})

# Store episodic memory (what happened)
memory.add(
 "User reported a 502 error on the /api/payments endpoint. "
 "Root cause was a connection pool exhaustion in the database layer. "
 "Fixed by increasing max_connections from 20 to 50.",
 user_id="user_123",
 metadata={"type": "episodic", "category": "incident", "resolved": True},
)

# Store semantic memory (what we know)
memory.add(
 "User's production stack: Python 3.11, FastAPI, PostgreSQL 15, Redis 7, "
 "deployed on AWS ECS with Fargate.",
 user_id="user_123",
 metadata={"type": "semantic", "category": "infrastructure"},
)

# Retrieve relevant memories for a new query
results = memory.search(
 "The payments API is returning errors again",
 user_id="user_123",
 limit=5,
)
# Returns the previous incident memory, enabling the agent to check
# connection pool settings as a first diagnostic step
Code Fragment 22.2.2: This snippet initializes Mem0 with separate memory type configurations for short_term (session buffer), long_term (persistent vector store), and episodic (experience summaries). The add and search methods show how memories are stored with user_id scoping and retrieved by semantic similarity with a top_k limit.
Common Misconception: Agent Memory Is Like Human Memory

The cognitive science terminology (episodic, semantic, procedural) is useful for categorization, but agent memory systems are fundamentally different from human memory in critical ways. Human memory is associative, lossy, and reconstructive; we do not retrieve exact records but rebuild memories from fragments, often inaccurately. Agent memory systems, by contrast, store exact records but struggle with relevance filtering and integration. The real engineering challenge is not storage (vector databases handle that well) but retrieval relevance: deciding which of potentially thousands of stored memories is useful for the current task. Additionally, agent memory systems can accumulate stale or contradictory information over time. A user's database version recorded six months ago may no longer be accurate. Implement memory expiration policies, confidence scoring, and explicit update mechanisms.

3. Context Window Management Strategies

Even with external memory stores, the agent must decide what to put in its context window for each turn. The context window budget must be allocated across the system prompt (fixed), retrieved memories (variable), tool definitions (fixed per tool set), conversation history (growing), and space reserved for the model's response. A well-designed agent treats context allocation as an optimization problem: maximize the relevance of included information while staying within token limits.

Common strategies include sliding window (keep the N most recent messages), summarization (periodically compress older messages into summaries), retrieval-based selection (embed the current query and retrieve the most relevant past messages), and hybrid approaches that combine all three. The optimal strategy depends on the task: customer support benefits from recent context, while research tasks benefit from relevance-based retrieval across a longer history.

Key Insight

The "lost in the middle" phenomenon affects agent memory just as it affects RAG systems: information placed in the middle of a long context window receives less attention from the model than information at the beginning or end. Place the most critical memories at the start of the context (right after the system prompt) or at the end (just before the current query), not buried in the middle of a long conversation history.

Exercises

Exercise 22.2.1: Memory Tier Design Conceptual

Describe the three memory tiers in the MemGPT (Letta) architecture and explain the role of each. Why is a three-tier approach more effective than simply increasing the context window size?

Answer Sketch

Main context holds the active prompt and recent turns. Recall storage holds the full conversation history, searchable by recency or content. Archival storage is a vector database for long-term facts. A larger context window still has finite capacity and suffers from the 'lost in the middle' problem. Three tiers let the agent page in only what is relevant, similar to how an OS manages RAM and disk.

Exercise 22.2.2: Episodic vs. Semantic Memory Conceptual

A support agent helped a user fix a database connection pool exhaustion last month. Explain what would be stored in episodic memory versus semantic memory for this interaction, and when each would be retrieved.

Answer Sketch

Episodic: 'On March 3, user_123 reported 502 errors on /api/payments. Root cause was connection pool exhaustion. Fixed by increasing max_connections from 20 to 50.' Semantic: 'user_123 production stack uses PostgreSQL 15 with max_connections=50.' Episodic is retrieved when a similar error pattern appears. Semantic is retrieved whenever the agent needs to know the user's infrastructure.

Exercise 22.2.3: Context Window Budget Allocator Coding

Write a Python function allocate_context(system_prompt, memories, history, max_tokens=8000) that allocates token budget across system prompt, retrieved memories, conversation history, and a reserved block for the model response. Implement a strategy that trims history first, then memories, if the total exceeds the budget.

Answer Sketch

Count tokens for each section (using tiktoken or a simple word-count approximation). Reserve 2000 tokens for the response. If the total of system_prompt + memories + history exceeds max_tokens minus the reserve, trim history from the oldest messages first. If still over budget, drop the lowest-relevance memories. Return the assembled prompt string.

Exercise 22.2.4: Memory Staleness Analysis

An agent's semantic memory says "user's database is PostgreSQL 14" but the user upgraded to PostgreSQL 16 three months ago. Propose a strategy that detects and corrects stale memories without requiring the user to explicitly update them.

Answer Sketch

Attach a last_verified timestamp and a confidence score to each memory. When a memory older than N days is retrieved for a critical decision, the agent asks a confirmation question: 'I have on record that you use PostgreSQL 14. Is that still correct?' On contradiction detection (e.g., user mentions PG 16), automatically update the memory and log the change.

Exercise 22.2.5: Lost-in-the-Middle Mitigation Conceptual

Explain the 'lost in the middle' phenomenon and how it affects agent memory placement. Where in the context window should the most critical memories be placed, and why?

Answer Sketch

LLMs attend less to information in the middle of a long context compared to the beginning and end. Place the most critical memories right after the system prompt (beginning) or just before the current query (end). Conversation history, which is less critical per-turn, can occupy the middle. This mirrors findings from Liu et al. (2023) on retrieval-augmented generation.

Tip: Set a Maximum Step Limit

Always cap the number of reasoning/action steps an agent can take (10 to 20 is usually sufficient). Without a limit, agents can enter infinite loops, burn through API credits, and never return a response. Fail gracefully when the limit is reached.

Key Takeaways
Self-Check
Q1: Why do agents need memory systems beyond the LLM's context window?
Show Answer

Context windows are finite and expensive. Memory systems allow agents to retain information across sessions, manage long-running tasks, and recall relevant past experiences without consuming the entire context budget on every turn.

Q2: How does MemGPT's virtual context management approach solve the context window limitation?
Show Answer

MemGPT treats the context window like virtual memory in an operating system: it pages information in and out of the active context on demand, allowing the agent to work with far more information than fits in a single prompt while keeping the most relevant data accessible.

Q3: What is the core idea behind Mem0 and A-MEM's Zettelkasten-style memory?
Show Answer

These systems store memories as interconnected, atomic notes (similar to the Zettelkasten method) with explicit links between related memories. This enables the agent to traverse a knowledge graph of past experiences rather than relying on flat retrieval.

What Comes Next

In the next section, Planning and Agentic Reasoning, we explore how agents decompose complex tasks into multi-step plans and adapt when those plans encounter unexpected observations.

References and Further Reading

Agent Memory Architectures

Park, J.S., O'Brien, J.C., Cai, C.J., et al. (2023). "Generative Agents: Interactive Simulacra of Human Behavior." UIST 2023.

Introduces the generative agent architecture with memory stream, reflection, and planning. The foundational work on how LLM agents can maintain and use long-term memory.

Paper

Zhong, W., Guo, L., Gao, Q., et al. (2024). "MemoryBank: Enhancing Large Language Models with Long-Term Memory." AAAI 2024.

Proposes a memory mechanism inspired by the Ebbinghaus forgetting curve, enabling LLMs to selectively retain and forget information over time.

Paper

Sumers, T.R., Yao, S., Narasimhan, K., et al. (2024). "Cognitive Architectures for Language Agents." TMLR.

The CoALA framework formalizes working memory and long-term memory as core components of language agent architectures, providing the theoretical foundation for memory system design.

Paper

Context Window and Retrieval Strategies

Liu, N.F., Lin, K., Hewitt, J., et al. (2024). "Lost in the Middle: How Language Models Use Long Contexts." TACL 2024.

Demonstrates that LLMs struggle to use information in the middle of long contexts, motivating careful memory placement strategies in agent systems.

Paper

Modarressi, A., Imani, A., Fayyaz, M., et al. (2023). "RET-LLM: Towards a General Read-Write Memory for Large Language Models." arXiv preprint.

Proposes a read-write memory mechanism using triplets stored in a retrieval-augmented architecture, enabling persistent memory across sessions.

Paper

Zhang, Z., Zhang, A., Li, M., et al. (2024). "A Survey on the Memory Mechanism of Large Language Model based Agents." arXiv preprint.

Comprehensive survey categorizing memory mechanisms into inside-trial, cross-trial, and external memory, providing a useful taxonomy for agent memory design.

Paper