DEV Community

Cover image for My AI Agent Ran for a Week — Here's How It Remembers Things
Kaelii
Kaelii

Posted on

My AI Agent Ran for a Week — Here's How It Remembers Things

I run a 24/7 AI agent connected to Telegram. It handles daily tasks, spawns sub-agents, and runs scheduled jobs.

Most agent frameworks have some kind of memory mechanism — a markdown file that gets loaded at session start, where the agent writes things down and reads them back next time. Basic persistence works fine.

But after running it for a while, I noticed a problem: the memory file kept growing.

The agent dumped everything in — debug logs, temporary state, duplicate information, long-outdated decisions. The file grew and grew, useful information buried under noise. And there was no cleanup mechanism — things went in, nothing came out.

I realized the agent didn't just need "the ability to remember things." It needed a memory system with a lifecycle: what to remember, how long to keep it, and when to forget. So I plugged in an external memory service to replace the markdown file. But having the tool didn't mean the problem was solved — the hardest part was teaching the AI to store and retrieve correctly.


Pitfall #1: It Doesn't Store Anything

After setting up the memory service, I wrote storage instructions in the system prompt. The first version used a table: what to store, what tags to use, what category. Clean and structured — looked great to me.

The result? The agent stored almost nothing.

A 30-minute conversation where I corrected two mistakes, confirmed a technical approach, and set a rule — it didn't store a single one. After the session ended, all of it was gone.

The reason is simple: an LLM's instinct is to respond, not to record. It'll go all-out answering your question, but it won't spontaneously think "is there something worth remembering in this conversation?" No matter how clean the table is, it won't pause mid-conversation to consult it.

Pitfall #2: Scattered Instructions

After discovering the storage problem, I switched to more forceful imperative instructions with lots of emphasis markers. "CRITICAL: When I correct you, store first, then reply." "HIGHEST PRIORITY: User feedback." "⚠️ Don't miss storing."

It worked better, but the rules were scattered across different parts of the prompt. CRITICAL appeared three times, ⚠️ twice, 🚫 once. They competed for attention. When everything screams "I'm the most important," nothing is.

Pitfall #3: Over-Compression

Realizing the prompt was too long, I did an aggressive trim. It backfired — shorter, yes, but the crucial guidance on when to store got cut too. The agent went passive: it only stored things when I explicitly said "remember this," no longer proactively extracting decisions and lessons from conversations.

The Structure That Finally Worked

After about two or three weeks of iteration, I converged on a stable structure. Four lines, each with a clear function:

  • Principle: Store everything valuable, store it immediately, never batch. Over-storing costs nothing, forgetting costs everything.
  • Action rule: User corrects you → store FIRST, then reply. If you think "I'll store this later," you're already wrong.
  • What to store: Identity, preferences, decisions, constraints, lessons, milestone recaps.
  • What not to store: Command output, step-by-step narration, info already in code/config files.

Each line gets an emoji prefix (🧠⚠️✅🚫). Not for decoration — they're visual anchors that help the model parse the structure at a glance. All in one compact block, not scattered across multiple sections.

Two specific wording changes made the biggest difference:

  1. "Over-storing costs nothing, forgetting costs everything" — eliminated the agent's hesitation. It stopped agonizing over "is this worth storing?" because the answer is always "storing it can't hurt."
  2. "Store FIRST, then reply" — solved the timing problem. After finishing a reply, the agent often forgot to store. Forcing store-before-reply meant corrections actually stuck.

Resume: The First Thing After Waking Up

With storing solved, there was still the retrieval problem. Each new session starts as a blank slate — the agent needs to know what it already knows.

I wrote a hard rule in the prompt: the first action of every session must be calling the resume endpoint, no exceptions. Before replying to the user, before reading files, before anything.

Resume doesn't return every memory in full (that would blow up the context). Instead, it returns an index — like a table of contents listing all topics and how many memories each contains. When the agent needs details on a specific topic, it pulls them on demand.

This design resolves a fundamental tension: the agent needs the confidence of "everything is saved" to be willing to store, but the context window can't actually load all memories. The index gives you both.

But the real pitfall with resume wasn't the design — it was that it often didn't get triggered.

A long-running agent continuously accumulates context. The framework periodically compresses it (compaction). The compressed summary preserves the rough outline of the conversation but loses details. The problem: the summary looks "good enough" — the agent reads the compressed context, thinks it knows what's going on, and starts working, not feeling any need to call resume.

This is a variant of hallucination: the agent gets false confidence from the compressed summary, believing it has enough context, when it's actually lost a mass of specifics — the exact wording of a rule, the reasoning behind a decision, the lesson from last time's mistake.

Writing "MANDATORY FIRST ACTION" in the prompt wasn't enough. Because the post-compaction context might already contain a seemingly reasonable conversation history, the agent prioritizes responding to that context over following a rule that "doesn't seem urgent."

My final solution wasn't a prompt rule — it was a file hook. I created a WORKFLOW_AUTO.md that the framework force-loads after every compaction. The file says one thing: call resume. No matter how the context gets compressed, the agent reads this file and triggers the resume call.

Moving a critical behavior from "a rule in the prompt" to "a hook in the filesystem" is a completely different level of reliability. Prompts can be ignored. File loading is deterministic.


Triggers: Reflexes Before Actions

Once, the agent did something I had explicitly told it not to do. It wasn't being defiant — it had "remembered" the rule (it was in the memory service), but it didn't think to check before executing the action.

This led me to add a trigger mechanism. When the agent learns a lesson, it stores it with a trigger tag (e.g., trigger:git-push). Before executing a related action, the prompt instructs it to check for relevant lessons first.

It's like muscle memory — no conscious recall needed. When the relevant action comes up, the lesson surfaces automatically. Far more reliable than depending on the agent to "remember."


After One Week

The agent has been running stably for a week now. Over a hundred memories, automatically clustered into a dozen-plus topics. It remembers who I am, the project's technical decisions, and mistakes it made before. Context restoration after a session restart takes about 300ms.

Looking back, the biggest lesson isn't technical — it's that the essence of prompt engineering isn't "what to say" but "how to say it so the model actually listens." The same rule, scattered vs. consolidated, passive vs. active voice, with or without explaining why — the difference in effectiveness is night and day.

The memory system's architecture matters, of course. But if the agent won't use it, the best architecture in the world is useless.


Memory service: engram — single Rust binary, MCP-compatible. Agent framework: OpenClaw.

Top comments (0)