Chapter 6 ยท CORE

Long-Term Memory Updater

๐Ÿ“„ 06_long_term_memory_updater.md ๐Ÿท Core

Chapter 6: Long-Term Memory Updater

In Chapter 5: Sandboxed Environment, we built a secure laboratory where our Agent can run code without destroying your computer. Our Agent is now smart, capable, and safe.

But there is still one major flaw: Amnesia.

If you tell a standard chatbot, "My name is Alice and I am a Python developer," it remembers you for that session. But if you refresh the page or come back tomorrow, it asks: "Who are you?"

In this chapter, we build the Long-Term Memory Updater. This is the component that gives our Agent a permanent memory, allowing it to remember your preferences, facts, and project details forever.

The Motivation: The "Secretary" Analogy

Standard Large Language Models (LLMs) are "stateless." They don't have a hard drive in their brain. Every time you send a message, you have to resend the entire conversation history so they know what's going on.

Eventually, that history gets too long and is deleted.

deer-flow solves this by acting like a Secretary in a meeting:

  1. The Meeting (Chat): The Agent talks to you.
  2. The Minutes (Update): In the background, a specific component reads the chat.
  3. The Filing Cabinet (JSON): It extracts important facts ("User loves Python") and files them into a permanent document.

Next time you start a chat, the Agent reads this "Filing Cabinet" before saying hello.

Central Use Case: "Remember My Stack"

User: "I strictly use TypeScript for all my projects."

Without Memory Updater:

With Memory Updater:

  1. System detects a preference in the chat.
  2. System updates the generic "User Context" file.
  3. Next Day: User asks "Write a script." -> Agent reads memory, sees "TypeScript," and writes the code correctly.

Key Concepts

1. The Memory File (memory.json)

We don't need a complex database for this. A simple JSON file works perfectly. It acts as the "Dossier" on the user.

It is structured into categories:

2. The Updater Loop

This is a background process. It does not run during your sentence (which would slow down the chat). It runs after a conversation turn.

It takes the recent chat messages, sends them to a cheaper, faster AI model, and asks: "Did we learn anything new about the user?"

3. Middleware Trigger

Just like in Chapter 2, we use Middleware to trigger this process automatically. The Lead Agent doesn't need to consciously "decide" to remember; the system does it for them.


Internal Implementation: How it Works

Let's visualize the flow of information when you tell the agent a fact.

Sequence Diagram

sequenceDiagram participant U as User participant LA as Lead Agent participant MU as Memory Updater participant JSON as Memory File U->>LA: "I hate writing unit tests." LA-->>U: "Understood, I'll keep that in mind." Note over LA: Conversation turn finishes. LA->>MU: Trigger Update (Background) MU->>JSON: Read current memory JSON-->>MU: { "likes_tests": unknown } MU->>MU: Analyze Chat: "User hates tests" MU->>JSON: Write Update Note right of JSON: { "preferences": "Hates unit tests" }

Code Deep Dive

Let's look at backend/src/agents/memory/updater.py to see how we implement this.

1. The Memory Structure

First, we define what our "Filing Cabinet" looks like. We create an empty structure if the file doesn't exist.

Simplified Code (updater.py):

def _create_empty_memory() -> dict:
    return {
        "version": "1.0",
        "lastUpdated": "2024-01-01T12:00:00Z",
        "user": {
            # General info about the user
            "workContext": {"summary": "", "updatedAt": ""},
            "personalContext": {"summary": "", "updatedAt": ""},
        },
        "facts": [], # Specific items like "Project ID is 123"
    }

Explanation: This JSON structure is what is injected into the Lead Agent's prompt every time a new chat starts.

2. The Updater Logic

The core magic happens in the MemoryUpdater class. It uses an LLM to read the chat and output JSON updates.

Simplified Code (updater.py):

class MemoryUpdater:
    def update_memory(self, messages: list) -> bool:
        # 1. Load the existing dossier
        current_memory = get_memory_data()

        # 2. Format a prompt: "Here is the old memory, here is the new chat."
        prompt = MEMORY_UPDATE_PROMPT.format(
            current_memory=json.dumps(current_memory),
            conversation=format_conversation(messages),
        )

        # 3. Ask the AI to generate updates
        response = self.model.invoke(prompt)
        
        # 4. Apply the AI's suggestions to our JSON file
        updated_memory = self._apply_updates(current_memory, json.loads(response))
        return _save_memory_to_file(updated_memory)

Explanation: We don't write if "Python" in message statements. We rely on the AI's intelligence to understand the context. The AI returns a JSON object describing what to add or change, and we save it.

3. Saving the Data

Writing to a file seems simple, but if the computer crashes while writing, we could corrupt the memory. We use an "Atomic Write" pattern (write to a temp file, then rename).

Simplified Code (updater.py):

def _save_memory_to_file(memory_data: dict) -> bool:
    file_path = _get_memory_file_path()
    
    # 1. Write to a temporary file first (Safety!)
    temp_path = file_path.with_suffix(".tmp")
    with open(temp_path, "w") as f:
        json.dump(memory_data, f, indent=2)

    # 2. Swap the files
    temp_path.replace(file_path)
    return True

Explanation: This ensures that memory.json is always valid. It's never half-written.

4. Connecting it to the Agent

Finally, we need to ensure this runs automatically. We add MemoryMiddleware to our Lead Agent's pipeline in agent.py.

Simplified Code (agent.py):

def _build_middlewares(config):
    middlewares = [
        ThreadDataMiddleware(),
        # ... other middlewares ...
        
        # This middleware ensures the agent READS memory on startup
        # AND triggers the updater after conversations.
        MemoryMiddleware() 
    ]
    return middlewares

Explanation: By adding this one line, every conversation the Lead Agent has is automatically analyzed and filed away.


Summary

In this chapter, we solved the "Amnesia" problem.

  1. Memory File: A JSON document that acts as the user's permanent record.
  2. Memory Updater: A background AI process that reads conversations and updates the record.
  3. Integration: We hooked this into the Lead Agent via Middleware.

We now have a complete, intelligent, safe, and persistent AI system running on our backend!

The final step is to open this system up to the outside world. What if you want to trigger this agent from a Slack message or a generic HTTP request?

Next Chapter: Gateway API


Generated by Code IQ