M

The Graph Engineering Setup Guide: How to Give Your Agents Memory That Compounds (Exact Config)

6 min readView source ↗

Cover image

Vector search retrieves text. It can't tell you the function you're about to edit is owned by a team that deprecated it last month.

Inside: the bi-temporal model, the MCP config that gives Claude persistent graph memory, and the routing rule for graph vs vector.

Gartner expects half of all agent systems on graph context by 2028.

Here's the full setup 👇

Before we dive in, I share daily notes on AI & vibe coding in my Telegram channel: https://t.me/zodchixquant 🧠

Article image

What graph engineering actually is

Vector RAG stores your knowledge as isolated chunks and retrieves by similarity. Graph engineering stores it as entities and relationships, so the agent can traverse instead of guess.

The difference shows up on questions with more than one hop:

  • Vector search: "find text similar to auth service" and hope the right chunk ranks first
  • Graph traversal: "which dashboards break if this table is deprecated" walks table → lineage → every dependent metric, and returns the actual list
  • The measured gap: production deployments report 36-46% accuracy gains on multi-hop tasks and 40%+ fewer hallucinations against vector-only baselines

Gartner projects that through 2028, context engineering improvements including graph grounding lift agentic accuracy by at least 30%.

The tooling stopped being academic in 2025-2026: Graphiti, Cognee, KARMA, plus MCP as the standard way to plug a graph into any agent.

Article image

The killer feature is time, not structure

Most people think a knowledge graph is a fancier database. The part that actually matters for agents is bi-temporal modeling.

Every edge in Graphiti carries two timestamps: when the event happened, and when your system learned about it. Facts get explicit validity windows. When something changes, the old edge is invalidated, not deleted.

That gives your agent three things flat memory can never have:

  • Point-in-time queries. "What did we believe about this API in June" returns June's answer, not today's
  • Contradiction handling. New info doesn't silently overwrite old info, it supersedes it with a timestamp trail
  • An audit trail. Every claim traces back to when and where it entered the graph

Your context window forgets at compaction. A vector store remembers everything and understands nothing. A temporal graph remembers what changed and when.

Setup: graph memory in Claude Code (copy this)

Graphiti ships an MCP server, so Claude Code, Claude Desktop, and Cursor can read and write the graph with no integration code.

In your .mcp.json:

{
  "mcpServers": {
    "graphiti": {
      "command": "uvx",
      "args": ["graphiti-mcp"],
      "env": {
        "NEO4J_URI": "bolt://localhost:7687",
        "NEO4J_USER": "neo4j",
        "NEO4J_PASSWORD": "${NEO4J_PASSWORD}",
        "MODEL_NAME": "claude-sonnet-5"
      }
    }
  }
}

Two details that decide whether this works:

  • Point extraction at a cheap model. Entity and edge extraction runs on every ingested episode. Sonnet 5 or Haiku here, not your frontier model, this is the single biggest cost lever in the whole setup
  • Neo4j runs locally in Docker for a dev graph. One container, and your agent has memory that survives every restart, every compaction, and every new session

Article image

The routing rule (this is the actual skill)

A graph is not a replacement for vector search or your context window. Hybrid routing beats every single-backend setup in benchmarks, and the routing logic is where the engineering lives.

Drop this in CLAUDE.md:

## Memory routing

Before answering, classify the question:

- Relational or multi-hop ("who owns", "what breaks if",
  "what changed since") → query the graph via MCP
- Broad semantic ("find docs about X", "similar examples")
  → vector search
- Anything already in this session → answer from context,
  don't hit either backend

Writing to the graph:
- After any decision, write an episode: what was decided,
  why, which files/people it touches
- Never write speculation. Only facts with a source
- Contradictions get written as new edges, never edits

The rule that saves you money and accuracy at once: the agent stops brute-forcing search when it has a graph to walk. Off-the-shelf setups burn roughly 30% more tokens doing what one traversal answers directly.

Feeding the graph without burning your budget

Ingestion is where naive setups get expensive: every entity resolution and every dedup used to mean another model call.

from graphiti_core import Graphiti

graphiti = Graphiti(NEO4J_URI, NEO4J_USER, NEO4J_PASSWORD)

await graphiti.add_episode(
    name="deprecate_legacy_auth",
    episode_body=(
        "Team Platform deprecated legacy_auth on 2026-07-14. "
        "Replacement is auth_v3. Owner: Marina. "
        "Blocked services: billing-api, notifications."
    ),
    source_description="engineering decision log",
    reference_time=datetime(2026, 7, 14),
)

Three habits that keep ingestion cheap:

  • Write episodes, not documents. One decision per episode with named entities beats dumping a wiki page and hoping extraction figures it out
  • Always set reference_time. Without it you lose the entire bi-temporal advantage and end up with a regular graph
  • Batch the backfill, stream the rest. Load your history once, then write incrementally as decisions happen. Graphiti updates without recomputing the graph

Common mistakes

  • Treating the graph as a second vector store. If you're querying it for "similar text", you built the wrong thing. Graphs answer relationship questions
  • Running extraction on a frontier model. Ingestion is high-volume and mechanical. Frontier rates here will produce a bill that kills the project before it proves value
  • Dumping everything in. A graph full of speculation and duplicated facts is worse than no graph, because the agent now traverses confidently into garbage
  • Skipping reference_time. The temporal layer is the whole reason to pick this over embeddings. Without timestamps you get a static ontology that rots
  • No write discipline. Agents that write freely create contradictions nobody notices for weeks. One rule (facts with sources only) prevents most of it

The 20-minute setup

  1. Run Neo4j in Docker, one command, dev credentials (4 min)
  2. Add the Graphiti MCP block to .mcp.json, point extraction at a cheap model (4 min)
  3. Write 5 real episodes by hand: recent decisions, owners, deprecations (6 min)
  4. Paste the routing rules into CLAUDE.md (2 min)
  5. Ask a multi-hop question you know the answer to, and check the traversal (4 min)

Context windows got huge and everyone assumed memory was solved. It wasn't. A big window remembers this session. A graph remembers your project, and it gets more valuable every week you feed it.

Thanks for reading!

I share daily notes on AI & vibe coding in my Telegram channel: https://t.me/zodchixquant 🧠

Article image

Related articles