Miscellaneous

Miscellaneous

Harness Comparison: How Claude Code, Cursor, Devin, and Antigravity Each Handle Memory

Harness Comparison: How Claude Code, Cursor, Devin, and Antigravity Each Handle Memory

AI coding harnesses have shifted from autocomplete tools to persistent collaborators. Claude Code, Cursor, Devin, and Antigravity each wrap an LLM in a workflow engine that tracks files, commands, and execution history.

The bottleneck is no longer model capacity but the quality of the harness memory stack. How context is collected, summarized, and reintroduced back into prompts determines whether the agent feels consistent or forgetful.

This post takes a systems view of how four popular harness styles approach memory, then shows how Mem0 adds durable, cross-session memory on top of any of them.

👉Get a free API key at app.mem0.ai to follow along (free tier, no credit card, includes all the add() and search() calls shown below).

The core memory problem in coding harnesses

Shows the three memory layers in coding harnesses and how they relate, clarifying where current tools focus versus the long term gap Mem0 targets.

Coding harnesses operate over three distinct memory layers:

  1. Ephemeral context: Immediate prompt window, inline code snippets, cursor location, and recent edits.

  2. Session memory: Files opened, commands run, tests executed, temporary scratchpads, and intermediate summaries.

  3. Long-term memory: Architecture decisions, past tickets, user preferences, and recurring patterns that should survive sessions.

Most harnesses excel at the first two layers. They track files and commands well, and they synthesize short-term summaries. The problem appears when:

  • The codebase exceeds a few megabytes of relevant context.

  • Multiple tickets, branches, or sessions interleave.

  • The same agent needs to resume work days or weeks later.

Without a dedicated long-term memory layer, the harness repeatedly recomputes the state. It resummarizes directories, re-explains the same architecture choices, and re-asks for preferences on tests, logging, or frameworks.

Mem0 exists to solve that specific gap.

Claude Code auto-compacting and hierarchical summarization

Claude Code-style harnesses build memory through aggressive summarization. The basic pattern looks like:

  1. File-level summaries: Each open file is summarized into a condensed description, often at multiple granularities.

  2. Workspace summaries: Directories and projects gain aggregate summaries that reference the file-level summaries.

  3. Conversation summaries: The chat history is compacted periodically, with emphasis on decisions and constraints.

  4. Auto compaction policy: Once token budgets are hit, low-value details are replaced with higher-level summaries.

Conceptually, the hierarchy is:

  • Raw code

  • Block summary

  • File summary

  • Project summary

  • Conversation summary

At the prompt time, the harness chooses the appropriate level for each component based on the task. Fixing a single function uses block summaries and raw code. High-level refactors use project and conversation summaries.

Strengths

  • Scales relatively well as codebases grow.

  • Supports multi-resolution context, which is important for both local fixes and global refactors.

  • Encourages a consistent vocabulary about the codebase that the model can reuse.

Weaknesses

  • Summaries are tightly coupled to a session or workspace snapshot.

  • Changing the codebase invalidates some of the hierarchy.

  • Long term decisions and the rationale behind them can get compacted away.

Hierarchical summarization solves transient context pressure, not multi-session continuity. The same project picked up next week often has to resummarize or re-explain key design choices.

Cursor raw stuffing and aggressive retrieval

Cursor-style harnesses prioritize raw context stuffing. Instead of aggressively summarizing early, they:

  1. Index the workspace using embeddings or symbol graphs.

  2. Retrieve the most relevant files or code blocks per query.

  3. Stuff those directly into the prompt with minimal intermediate summaries.

  4. Heavily annotate the prompt with file paths and code slices.

This design assumes that the best signal for the task is often the actual code and comments, not a derived summary. Any summarization is applied lazily, usually in the conversation history, not in the code context.

Strengths

  • The model sees real code, which improves correctness and reduces hallucination.

  • Retrieval is flexible and can adapt to changing codebases in near real time.

  • Debugging is transparent because the harness shows which files were injected.

Weaknesses

  • Prompt budgets cap the effective codebase size, especially for multi-file tasks.

  • Lack of durable summaries makes cross-session continuity dependent on re-indexing.

  • Repeated context fetching for similar queries wastes compute.

Raw stuffing excels at short to medium tasks but does not independently store long-term decisions. Repeated tasks on the same repo depend on embedding retrieval alone, which may miss nuance like "this team prefers dependency injection over singletons".

Devin checkpointing and execution state as memory

Devin-style harnesses introduce a more explicit notion of "checkpointed" memory. The harness treats agent progress like a build system:

  1. Plan decomposition: The task is decomposed into steps and subgoals.

  2. Checkpointing: After each meaningful step, the harness records:

    • Files changed.

    • Commands executed.

    • Tests run and their results.

    • Artifacts produced (logs, screenshots, outputs).

  3. Recovery: On failure or interruption, the agent reloads the last checkpoint to reconstruct context.

  4. Task-level history: Each task maintains its own sequence of checkpoints and progress notes.

This resembles long-running workflow engines. Memory is anchored in explicit milestones, not just chat history or file summaries.

Strengths

  • Strong resilience to interruptions and environment resets.

  • Clear replay and audit trail of what the agent has done.

  • Good alignment with CI and deployment pipelines.

Weaknesses

  • Memory is mostly scoped to a single task or ticket.

  • Checkpoints can be heavy and are rarely reused across unrelated tasks.

  • Long-term preferences and patterns do not naturally bubble up from checkpoints.

Checkpointing gives a persistent state within a task, but cross-task continuity is manual. An agent may forget that a previous project decided to standardize on a certain logging format.

Antigravity artifacts as memory

Antigravity-style harnesses treat artifacts as first-class memory units. An artifact can be:

  • A planning document.

  • A test report.

  • A code diff.

  • A design diagram.

  • A transcript segment.

The harness organizes these artifacts in a graph or workspace, and the agent interacts with them in a quasi-visual environment.

Artifact-centric memory has this loop:

  1. The agent produces an artifact for each meaningful thought or deliverable.

  2. Artifacts are versioned and linked.

  3. The harness surfaces relevant artifacts for new tasks via:

    • Tag-based search.

    • Embedding similarity.

    • Structured queries on artifact metadata.

In effect, the agent "remembers" through the artifacts it leaves behind.

Strengths

  • Strong alignment with how human teams share knowledge.

  • Easy to inspect and reuse prior work by both humans and agents.

  • Provides a natural home for long-form design documents and rationales.

Weaknesses

  • Retrieval quality depends heavily on tagging and indexing discipline.

  • Many artifacts are task-specific and not normalized into reusable facts.

  • Cross-session continuity is implicit, not enforced by a memory API.

Artifacts as memory shift the burden from raw context or summaries to structured outputs. Without a separate memory layer that distills the durable parts of those artifacts, important patterns can still slip through.

Comparison of harness memory strategies

Visually compares the four harness memory styles side by side, mapping each to its primary unit, scope, and persistence so the tradeoffs are easier to internalize.

The four styles target different slices of the memory problem. The table below summarizes the tradeoffs through the lens of agent memory.

Harness style

Primary memory unit

Scope

Persistence model

Strength

Weakness

Claude Code style

Hierarchical summaries

File and project

Auto compaction per session

Scales summaries over large codebases

Long term rationale can be compacted away

Cursor style

Raw code context

File and snippet

Retrieval per query

Accurate view of current code

Limited cross-session continuity

Devin style

Checkpoints and logs

Task

Task-scoped history

Strong within-task continuity

Weak reuse across tasks

Antigravity style

Artifacts and documents

Workspace

Graph or workspace storage

Human-aligned knowledge representation

Retrieval depends on artifact quality

Each harness partially solves context limits. None of them, by design, exposes a generic API for long-term personalized memory that is:

  • Independent of a single codebase or task.

  • Shared across sessions and environments.

  • Explicitly queryable and updateable by multiple agents.

This is the layer Mem0 is designed to fill.

How Mem0 fits as a dedicated memory layer

Mem0 treats memory as a first-class service that sits beside any harness. Instead of tying memory to a single chat window or repository, it exposes:

  • Write APIs: Agents can store structured memories with metadata (project, user, tags, timestamps).

  • Read APIs: Agents can query relevant memories by text, metadata filters, or vector similarity.

  • Identity and scope control: Memory can be scoped per user, per project, per agent, or shared.

  • Persistence and versioning: Memories survive across sessions and can be updated or merged.

For harnesses like Claude Code, Cursor, Devin, or Antigravity, Mem0 acts as an external spine:

  • Summaries, artifacts, and checkpoints become inputs to Mem0, not the final memory.

  • The harness itself remains stateless between sessions, delegating persistence to Mem0.

  • Multiple harnesses can share the same memory base if desired.

Critical behaviors that Mem0 enables in this context:

  1. Cross-session recall of design decisions: The first time the agent decides on architecture, it stores those decisions. Future sessions reuse them automatically.

  2. Personalization by user and team: Mem0 records styling preferences, code review patterns, and standard practices that apply across projects.

  3. Multi-harness consistency: A user can move between harnesses while keeping a consistent memory layer.

  4. Explicit forgetting and scope control: Derive new memories from artifacts but still delete or isolate sensitive content.

The same Mem0 base can absorb:

  • Claude-style hierarchical summaries of codebases.

  • Cursor-style retrieval traces.

  • Devin-style checkpoints and logs.

  • Antigravity-style artifacts.

Mem0 distills these into compact, queryable memories that survive beyond any single harness run.

A shared demo architecture with Mem0 on top

Shows how the four harness styles connect to Mem0 as a shared long term memory spine, making the cross harness demo architecture concrete.

Consider a shared demo where all four harness styles interact with the same Mem0 instance.

The scenario:

  • An engineer uses a Claude-style harness to introduce a new service layout.

  • A Cursor-style harness then implements additional endpoints.

  • A Devin-style harness runs an end-to-end integration task.

  • An Antigravity-style harness creates architecture diagrams and documents.

With Mem0, the pipeline looks like:

  1. Claude-style harness writes architecture decisions

    • High level structure: services, modules, and dependencies.

    • Naming conventions and directory layout.

  2. Cursor-style harness reads Mem0 during code generation

    • Resolves ambiguous naming or directory placement via Mem0 queries.

    • Recalls team conventions or prior decisions.

  3. Devin-style harness stores and reuses test and deployment outcomes

    • Logs the fact that a particular combination of flags is required for a certain CI pipeline.

    • On future tasks, it retrieves these constraints automatically.

  4. Antigravity-style harness uploads artifacts into Mem0

    • Extracts key decisions from diagrams or documents and stores them as text memories.

    • Links artifacts metadata (like project, environment) to Mem0 scopes.

Every harness can keep its own internal memory structure, but all share a common, persistent, text-based memory API through Mem0.

Real Mem0 integration example in Python

Illustrates the basic read then write loop between a harness agent and Mem0, supporting the Python example and integration patterns.

The following example shows how a simple harness-like agent can:

  • Pull relevant long term memories from Mem0 before planning.

  • Update Mem0 with new decisions after each run.

Assume:

  • The harness gets a project_id and user_id.

  • It wants to remember architecture decisions and coding preferences.

👉Wanna give it a try? Get a Mem0 API Key and try it yourself.

import os
from mem0 import MemoryClient
from typing import List, Dict

MEM0_API_KEY = os.environ.get("MEM0_API_KEY")

mem0 = MemoryClient(api_key=MEM0_API_KEY)

def fetch_project_memories(project_id: str, user_id: str) -> List[Dict]:
    """
    Retrieve relevant memories for a given project and user.
    Example: architecture decisions, style preferences, prior bugs.
    """
    query = f"project:{project_id} user:{user_id}"
    response = mem0.search(
        query=query,
        filters={"project_id": project_id, "user_id": user_id},
        top_k=10,
    )
    return response.get("results", [])

def store_architecture_decision(project_id: str, user_id: str, decision: str) -> Dict:
    """
    Store a new architecture decision in Mem0.
    """
    memory_payload = {
        "content": decision,
        "metadata": {
            "project_id": project_id,
            "user_id": user_id,
            "type": "architecture_decision",
        },
    }
    return mem0.add(memory_payload)

def apply_memories_to_prompt(base_prompt: str, memories: List[Dict]) -> str:
    """
    Combine base prompt with retrieved memories into a single context string.
    """
    if not memories:
        return base_prompt

    memory_texts = []
    for m in memories:
        content = m.get("content", "")
        meta = m.get("metadata", {})
        typename = meta.get("type", "memory")
        memory_texts.append(f"[{typename}] {content}")

    memory_block = "\n".join(memory_texts)
    combined = (
        "You have access to the following long-term project context:\n"
        f"{memory_block}\n\n"
        "Use this context when answering the user request.\n\n"
        f"User request:\n{base_prompt}"
    )
    return combined

if __name__ == "__main__":
    project_id = "proj-42"
    user_id = "alice"

    # Example: harness receives a new user request
    user_request = "Add a new payment gateway integration to the existing billing service."

    # 1. Fetch long-term memories from Mem0
    memories = fetch_project_memories(project_id, user_id)

    # 2. Build an LLM prompt that includes those memories
    full_prompt = apply_memories_to_prompt(user_request, memories)

    # 3. Send full_prompt to your chosen LLM here
    # (pseudo code, integrate with Claude, Cursor, Devin, or Antigravity harnesses)
    # response = llm.generate(full_prompt)

    # 4. Imagine the agent decides on a specific architecture
    new_decision = (
        "For project proj-42, all payment gateways must implement the "
        "`PaymentProvider` interface in `payments/providers.py` and be registered "
        "in `payments/registry.py`."
    )

    # 5. Store that decision in Mem0 for future sessions
    saved_memory = store_architecture_decision(project_id, user_id, new_decision)

    print("Stored memory id:", saved_memory.get("id"))
import os
from mem0 import MemoryClient
from typing import List, Dict

MEM0_API_KEY = os.environ.get("MEM0_API_KEY")

mem0 = MemoryClient(api_key=MEM0_API_KEY)

def fetch_project_memories(project_id: str, user_id: str) -> List[Dict]:
    """
    Retrieve relevant memories for a given project and user.
    Example: architecture decisions, style preferences, prior bugs.
    """
    query = f"project:{project_id} user:{user_id}"
    response = mem0.search(
        query=query,
        filters={"project_id": project_id, "user_id": user_id},
        top_k=10,
    )
    return response.get("results", [])

def store_architecture_decision(project_id: str, user_id: str, decision: str) -> Dict:
    """
    Store a new architecture decision in Mem0.
    """
    memory_payload = {
        "content": decision,
        "metadata": {
            "project_id": project_id,
            "user_id": user_id,
            "type": "architecture_decision",
        },
    }
    return mem0.add(memory_payload)

def apply_memories_to_prompt(base_prompt: str, memories: List[Dict]) -> str:
    """
    Combine base prompt with retrieved memories into a single context string.
    """
    if not memories:
        return base_prompt

    memory_texts = []
    for m in memories:
        content = m.get("content", "")
        meta = m.get("metadata", {})
        typename = meta.get("type", "memory")
        memory_texts.append(f"[{typename}] {content}")

    memory_block = "\n".join(memory_texts)
    combined = (
        "You have access to the following long-term project context:\n"
        f"{memory_block}\n\n"
        "Use this context when answering the user request.\n\n"
        f"User request:\n{base_prompt}"
    )
    return combined

if __name__ == "__main__":
    project_id = "proj-42"
    user_id = "alice"

    # Example: harness receives a new user request
    user_request = "Add a new payment gateway integration to the existing billing service."

    # 1. Fetch long-term memories from Mem0
    memories = fetch_project_memories(project_id, user_id)

    # 2. Build an LLM prompt that includes those memories
    full_prompt = apply_memories_to_prompt(user_request, memories)

    # 3. Send full_prompt to your chosen LLM here
    # (pseudo code, integrate with Claude, Cursor, Devin, or Antigravity harnesses)
    # response = llm.generate(full_prompt)

    # 4. Imagine the agent decides on a specific architecture
    new_decision = (
        "For project proj-42, all payment gateways must implement the "
        "`PaymentProvider` interface in `payments/providers.py` and be registered "
        "in `payments/registry.py`."
    )

    # 5. Store that decision in Mem0 for future sessions
    saved_memory = store_architecture_decision(project_id, user_id, new_decision)

    print("Stored memory id:", saved_memory.get("id"))
import os
from mem0 import MemoryClient
from typing import List, Dict

MEM0_API_KEY = os.environ.get("MEM0_API_KEY")

mem0 = MemoryClient(api_key=MEM0_API_KEY)

def fetch_project_memories(project_id: str, user_id: str) -> List[Dict]:
    """
    Retrieve relevant memories for a given project and user.
    Example: architecture decisions, style preferences, prior bugs.
    """
    query = f"project:{project_id} user:{user_id}"
    response = mem0.search(
        query=query,
        filters={"project_id": project_id, "user_id": user_id},
        top_k=10,
    )
    return response.get("results", [])

def store_architecture_decision(project_id: str, user_id: str, decision: str) -> Dict:
    """
    Store a new architecture decision in Mem0.
    """
    memory_payload = {
        "content": decision,
        "metadata": {
            "project_id": project_id,
            "user_id": user_id,
            "type": "architecture_decision",
        },
    }
    return mem0.add(memory_payload)

def apply_memories_to_prompt(base_prompt: str, memories: List[Dict]) -> str:
    """
    Combine base prompt with retrieved memories into a single context string.
    """
    if not memories:
        return base_prompt

    memory_texts = []
    for m in memories:
        content = m.get("content", "")
        meta = m.get("metadata", {})
        typename = meta.get("type", "memory")
        memory_texts.append(f"[{typename}] {content}")

    memory_block = "\n".join(memory_texts)
    combined = (
        "You have access to the following long-term project context:\n"
        f"{memory_block}\n\n"
        "Use this context when answering the user request.\n\n"
        f"User request:\n{base_prompt}"
    )
    return combined

if __name__ == "__main__":
    project_id = "proj-42"
    user_id = "alice"

    # Example: harness receives a new user request
    user_request = "Add a new payment gateway integration to the existing billing service."

    # 1. Fetch long-term memories from Mem0
    memories = fetch_project_memories(project_id, user_id)

    # 2. Build an LLM prompt that includes those memories
    full_prompt = apply_memories_to_prompt(user_request, memories)

    # 3. Send full_prompt to your chosen LLM here
    # (pseudo code, integrate with Claude, Cursor, Devin, or Antigravity harnesses)
    # response = llm.generate(full_prompt)

    # 4. Imagine the agent decides on a specific architecture
    new_decision = (
        "For project proj-42, all payment gateways must implement the "
        "`PaymentProvider` interface in `payments/providers.py` and be registered "
        "in `payments/registry.py`."
    )

    # 5. Store that decision in Mem0 for future sessions
    saved_memory = store_architecture_decision(project_id, user_id, new_decision)

    print("Stored memory id:", saved_memory.get("id"))

This sample is intentionally minimal. In a real harness integration:

  • Claude-style harnesses would be called store_architecture_decision when finalizing a design summary.

  • Cursor-style harnesses would call fetch_project_memories before generating code, and embed the results into the system prompt.

  • Devin-style harnesses would store checkpoint-level insights, such as optimal flags or environment quirks.

  • Antigravity-style harnesses would extract text from artifacts and write it as Mem0 memories with proper metadata.

Mem0 provides the shared memory spine that the harnesses currently lack.

Practical integration patterns with existing harnesses

Integrating Mem0 with existing harnesses follows a few repeatable patterns:

  1. System prompt augmentation: Before each LLM call, fetch relevant memories from Mem0 and prepend them to the system or assistant message. This works for all four harness styles.

  2. Memory hooks on key events: Define hooks for:

    • File creation or significant refactors.

    • Plan completion or subgoal completion.

    • Artifact creation (docs, diagrams).

    • Test or deployment success/failure.

    Each hook calls Mem0 to add or update memories.

  3. Scope by project and user: Use Mem0 metadata to segment memory:

    • project_id for repo or service boundary.

    • user_id for personalization.

    • agent_id or harness_type if needed.

  4. Summarization step before writing: Do not store raw logs or code. Instead:

    • Summarize the key decision or outcome.

    • Include links or identifiers to artifacts stored elsewhere.

  5. Backfilling from existing artifacts: For harnesses that have been in use without a memory layer:

    • Scan existing design docs, ADRs, or reports.

    • Generate Mem0 memories from them.

    • Boot the agent with a populated memory base.

This approach lets Mem0 sit beside existing harnesses without invasive changes, while providing an external memory contract that can be shared across tools and sessions.

Limitations of harness memory patterns

Each harness memory pattern has clear limits that Mem0 does not attempt to replace, but instead complements:

  • Hierarchical summarization
    Works well within a single project snapshot. It struggles with:

    • Continuous refactors where summaries quickly get stale.

    • Capturing human intent behind code changes.

    • Sharing decisions across multiple projects.

  • Raw context stuffing
    Keeps the model close to source truth, but:

    • Cannot scale to very large monorepos at high granularity.

    • Tends to repeat similar context across sessions.

    • Depends heavily on retrieval quality for subtle decisions.

  • Checkpointing
    Provides strong task-level reliability, yet:

    • Checkpoints are not intrinsically queryable across tasks.

    • Many agents do not expose their checkpoints as reusable knowledge.

    • Sharing checkpoints between different harnesses is nontrivial.

  • Artifacts as memory
    Aligns well with human workflows, though:

    • Requires disciplined tagging and documentation practices.

    • Artifacts often contain more noise than reusable facts.

    • Not all harnesses can ingest arbitrary artifact formats as context.

Mem0 sits at a higher level of abstraction. It does not manage file diffs, full logs, or artifact UIs. Instead, it focuses on durable, text-based memories that express decisions, preferences, constraints, and lessons learned. Harnesses still need their internal mechanisms for code and execution level context.

Frequently Asked Questions

Q. What problem does Mem0 solve that harnessing memory alone does not?

Harnesses are excellent at managing short-term context inside a single session or task. Mem0 focuses on cross-session and cross-harness continuity by storing durable memories that express decisions, preferences, and constraints that outlive any single run.

Q. How should an AI engineer decide what to store in Mem0 versus the harness?

Use the harness for transient context, such as current file contents, logs, and intermediate prompts. Use Mem0 for any information that should still matter tomorrow, such as architecture decisions, coding standards, project invariants, and recurring gotchas.

Q. When is the right time to write to Mem0 during an agent run?

The most effective pattern is to write to Mem0 at milestones: when a design is accepted, a refactor is completed, a bug is diagnosed, or a deployment is stabilized. These points naturally produce summarized knowledge that is reusable and less noisy than raw logs.

Q. How does Mem0 interact with hierarchical summaries or artifacts?

Mem0 does not replace internal summaries or artifacts. Instead, agents extract key statements from those sources and store them as Mem0 memories with metadata. Hierarchical summaries and artifacts remain detailed, while Mem0 holds a compact, queryable layer of distilled knowledge.

Q. Why use a shared memory layer across different harnesses?

Many teams experiment with multiple harnesses or tools for different tasks. A shared memory layer ensures that decisions made in one context, such as architecture patterns or conventions, are available to agents in other tools, which reduces rework and prevents conflicting behaviors.

Q. Can Mem0 help with personalization for individual developers?

Yes. By scoping memories withuser_id, agents can remember individual preferences, such as code style tendencies, tooling choices, or typical workflows. This personalization persists across sessions and can be reused by different harnesses that integrate with the same Mem0 base.

Further Reading

Mem0 is an intelligent, open-source memory layer designed for LLMs and AI agents to provide long-term, personalized, and context-aware interactions across sessions.

Get your free API Key here: app.mem0.ai or self-host mem0 from our open source GitHub repository.

GET TLDR from:

Summarize

Website/Footer

Summarize

Website/Footer

Summarize

Website/Footer

Summarize

Website/Footer