Engineering

Memory Systems: Building Persistent State for AI Agents

By Agents Squads · · 11 min

“Without memory, every session starts from zero. With memory, agents compound their knowledge.”

The Statefulness Problem

Claude Code is stateless by design. Each conversation starts fresh with no recollection of previous sessions. For one-off tasks, this is fine—you ask a question, get an answer, and move on. But for ongoing work, statelessness creates serious problems.

Consider an agent tasked with tracking your organization’s AI costs. On Monday, it researches cost patterns and discovers that Opus costs fifteen times more than Haiku. On Tuesday, you ask about costs again. The agent has forgotten everything. It starts the research from scratch, rediscovers the same patterns, and produces essentially the same report. No learning, no building, no progress.

This isn’t just inefficient—it makes meaningful agent work impossible. Agents can’t improve over time because they don’t remember what worked and what didn’t. Feedback given in one session evaporates before the next. There’s no continuity, no accumulated expertise, no institutional knowledge.

We needed agents that remember.

Our Approach to Memory

We built a memory system that stores agent state in markdown files tracked by git. The structure is simple:

.agents/memory/
├── finance/
│   ├── state.md           # Current squad state
│   ├── learnings.md       # What we've learned
│   └── feedback.md        # Execution feedback
├── engineering/
│   ├── state.md
│   └── ...
└── .last-sync             # Git sync timestamp

Markdown files are human-readable, easy to edit, and work naturally with version control. Git provides versioning, distribution, and collaboration—we get those capabilities for free by building on a tool developers already understand.

Three Types of Memory

We’ve found it useful to separate memory into three distinct categories.

State Memory

State memory captures the current situation: what’s in progress, what’s pending, what’s blocked. It’s the kind of information you’d share in a standup meeting.

# Finance Squad State

## Active Work
- Q1 budget analysis (in progress)
- Cost optimization review (blocked on data)

## Key Metrics
- Monthly AI spend: $2,340
- Budget remaining: $7,660

## Last Updated
2026-01-07

When an agent starts working, state memory tells it where things stand. What projects are underway? What numbers matter? What’s been decided? This context lets the agent pick up where previous sessions left off rather than starting from nothing.

Learnings Memory

Learnings memory captures accumulated knowledge—insights gained from experience that should inform future work.

# Finance Squad Learnings

## Cost Patterns
- Opus costs 15x more than Haiku
- Image generation dominates spend
- Peak usage: Mon-Wed mornings

## What Works
- Batch similar queries to reduce overhead
- Use Haiku for classification tasks
- Cache repeated analyses

This is institutional knowledge for agents. Instead of rediscovering the same insights every session, agents inherit what previous sessions learned. Over time, learnings memory becomes a valuable repository of expertise that makes the squad increasingly effective.

Feedback Memory

Feedback memory captures human reactions to agent outputs—what was good, what needs improvement, what to do differently.

# Finance Squad Feedback

## 2026-01-05: Cost Report
Rating: 4/5
Notes: Good breakdown, but missing per-agent detail

## 2026-01-03: Budget Forecast
Rating: 3/5
Notes: Assumptions not clearly stated

Without feedback, agents have no signal about quality. They might produce outputs that look impressive but miss what matters to humans. Feedback memory closes the loop, letting agents learn from human evaluation and adjust accordingly.

How Agents Actually Use Memory

The lifecycle works like this. At session start, relevant memory gets loaded and injected into the agent’s context. The agent sees the current state, past learnings, and recent feedback before doing any work. This context shapes how it approaches the task.

At session end, the agent summarizes what happened and updates memory accordingly. If it learned something new, that goes into learnings. If the state changed, state.md gets updated. If the human provided feedback, that gets recorded.

We use Claude Code’s hooks feature to automate memory injection:

{
  "hooks": {
    "SessionStart": [{
      "type": "command",
      "command": "squads memory inject $SQUAD"
    }]
  }
}

The agent doesn’t have to remember to load memory—it happens automatically every time a session begins.

Querying Across Squads

Sometimes agents need knowledge from outside their domain. Our CLI supports cross-squad memory queries:

squads memory query "cost optimization"

This returns relevant snippets from all squads:

[finance] Cost Patterns: Opus costs 15x more than Haiku...
[engineering] Infrastructure: Reduced costs 40% by batching...

Different squads can share knowledge without polluting each other’s primary context. The finance squad might discover something useful to engineering, and a query surfaces it without requiring the engineering squad to constantly load finance memory.

Why Git?

Storing memory in git gives us several benefits almost for free.

Version control means we can see how memory evolves over time. When did the finance squad learn about Opus pricing? What did the engineering squad’s state look like last month? Git history answers these questions.

Distribution means memory works offline and syncs when connectivity returns. An agent can work on a plane, update its memory, and sync changes when it lands. Multiple agents can work in parallel and merge their memory updates.

Auditability means we always know who changed what and when. If memory gets corrupted or contains bad information, we can trace it back to the source and understand what happened.

The sync command handles the mechanics:

squads memory sync  # Pull + push memory changes

Keeping Memory Healthy

Memory accumulates over time, and without maintenance, it becomes noise. Several practices keep memory useful.

Summarization compresses verbose memory. If your learnings contain fifteen separate entries about Opus pricing discovered on different days, summarize them into one clear statement. The detail isn’t lost—it’s in git history—but the active memory stays focused.

Archival moves old information out of the way. Memory about Q3 2025 cost patterns probably isn’t relevant to current work. Move it to an archive directory so it doesn’t clutter current context while remaining accessible if needed.

Relevance decay means recent memory matters more. When injecting memory, weight recent entries more heavily than old ones. The state from yesterday is more relevant than the state from six months ago.

Common Mistakes

We’ve learned what doesn’t work.

Too much memory is counterproductive. If you inject 10,000 tokens of memory, you’ve consumed most of the context window before the agent even starts working. Keep memory tight—under 2,000 tokens per squad is a reasonable target.

Unstructured memory becomes unsearchable. Free-form notes might make sense when you write them, but they’re hard to query and hard for agents to extract value from. Use consistent headings, clear formatting, and structured sections.

Memory without feedback doesn’t improve. If agents never learn which outputs were good and which were bad, memory just accumulates activity logs. The feedback loop is what makes memory valuable for learning.

Implementation Without Our Tools

You don’t need our specific CLI to implement agent memory. The pattern is simple:

Store memory in a known location—markdown files in a predictable directory structure. Inject memory at session start—load the relevant files and include them in the agent’s context. Update memory at session end—have the agent summarize what changed and write updates. Sync across sessions—use git or any other version control to distribute and version memory.

# Pseudo-code
def start_session(squad):
    memory = read_file(f".agents/memory/{squad}/state.md")
    inject_into_context(memory)

def end_session(squad, summary):
    update_file(f".agents/memory/{squad}/state.md", summary)
    git_commit_and_push()

The tools we’ve built make this convenient, but the core pattern works with any orchestration approach.

The Difference Memory Makes

With memory, agents transform from stateless functions into something more like team members. They remember what they’ve learned. They build on previous work. They improve based on feedback. They maintain awareness of ongoing projects and accumulated expertise.

Without memory, every session is day one. With memory, agents compound their knowledge across weeks and months of operation. That’s the difference between a tool you use and a system that genuinely helps.

Ready to add memory to your agents? Run:

squads memory show finance

This shows the current memory state for any squad. Or get started with our CLI guide.


This is part of the Engineering AI Agents series—practical patterns for building autonomous AI systems.

Related Reading

Back to Engineering