{"slug": "i-stopped-asking-my-ai-agents-to-read-the-project-memory-now-the-server-does-it", "title": "I stopped asking my AI agents to read the project memory. Now the server does it for them.", "summary": "A developer running nine parallel Claude Code sessions rebuilt agent memory recall as server-side plumbing rather than a prompt instruction, injecting semantically retrieved project notes into each session's first message before the model takes a turn. The change addresses the roughly one-in-nine sessions that ignored a memory_search instruction and silently violated project conventions, with an end-to-end test seeding notes that contradict a deliberately wrong README to verify recall.", "body_md": "Follow-up to [*I run 9 parallel Claude Code sessions — the bottleneck wasn't\nthe model, it was memory*](https://dev.to/nicolas_micaud_20671fb4f2/i-run-9-parallel-claude-code-sessions-the-bottleneck-wasnt-the-model-it-was-memory-1n7c).\n\nThat post described the problem. This one is about the fix I shipped, and the\n\nuncomfortable thing it taught me about \"instructing\" a model.\n\nI build and run our products — a Swiss job platform, a handful of sites, the\n\ninfrastructure under them — with a cockpit that keeps ~9 Claude Code sessions\n\nalive in parallel. Each session is a task: a kanban card you drag, and it\n\nbecomes a working agent.\n\nThe recurring failure was never intelligence. It was amnesia. Session #7 would\n\nhappily reimplement an error format we'd standardized weeks ago, because nothing\n\ntold it that decision existed. The decision *was* written down — in a markdown\n\nnote, in the project memory — but the session never looked.\n\nMy first fix was the obvious one. When a session spawns, append an instruction\n\nto its first prompt:\n\n```\n{the task}\nStart by calling the memory_search tool to load any relevant project context,\nthen propose a plan — don't execute anything without my go-ahead.\n```\n\nThis is what most \"give your agent memory\" setups do: a system prompt, a tool,\n\nand trust that the model uses them. And it mostly works. *Mostly.*\n\nHere's the thing about \"mostly\" when you have nine of them running. One session\n\nin nine ignoring the instruction isn't a 1-in-9 annoyance — it's a silent,\n\nguaranteed defect generator. The model doesn't announce \"I skipped the memory\n\nthis time.\" It just dives into the code, does something locally reasonable, and\n\nviolates a convention you'd forgotten you even needed to defend. You find out at\n\nreview, or worse, after merge.\n\nI spent a while trying to make the instruction *stickier* — stronger wording,\n\nputting it last, tool descriptions that begged. That's when it clicked: **I was trying to make a non-deterministic thing reliable by asking harder.** Wrong\n\nThe recall doesn't belong in the prompt. It belongs in the plumbing.\n\nNow, when a session spawns, the **server** runs the semantic search — before the\n\nmodel gets a single turn — and injects the results directly into the session's\n\nfirst message:\n\n``` php\ndef _memory_preseed(query: str, top_k: int = 5) -> str:\n    hits = memory_search(query, top_k=top_k)   # server-side, deterministic\n    if not hits:\n        return \"\"                               # empty memory → fall back to the ritual\n    lines = [\"=== Project memory (auto-recalled) ===\"]\n    for h in hits:\n        star = \"★ \" if h.get(\"priority\") else \"\"\n        lines.append(f\"- {star}[{h['note_name']}] {h['description']} — {h['snippet']}\")\n    return \"\\n\".join(lines)\n```\n\nThe task the model receives now looks like:\n\n```\nFix the healthcheck flapping on staging.\n\n=== Project memory (auto-recalled) ===\n- ★ [staging-stack] Staging API is on port 6443, deploys land on host \"callisto\"\n- [deploy-ritual] Deploys go exclusively through `make ship-v2`, never raw rsync\n\nThe notes above were auto-recalled from project memory for this task. Call\nmemory_get on any note you need in full… then propose a plan and wait for my go.\n```\n\nThe model can't *not* have the context now. It's not a tool it might call. It's\n\nin the first tokens it reads.\n\nCrucially, the old ritual is still there — as a **fallback**. If the memory is\n\nempty (fresh project) or the embedding backend is down, the injected block is\n\nempty and the prompt reverts to \"please go search.\" Determinism where it\n\nmatters, graceful degradation where it doesn't.\n\nClaims about memory systems are cheap. So the release has an end-to-end test\n\nthat seeds a throwaway instance with two notes containing facts that exist\n\n**nowhere in the code**: the staging port is `6443`, deploys go to a host called\n\n`callisto`, via `make ship-v2`. The workspace README is deliberately *wrong*\n\nabout all three.\n\nThen it spawns a session asking: *\"what port does staging run on, which host do we deploy to, and with what command?\"*\n\nA session that reads the code (or the lying README) fails. A session with\n\nworking recall answers `6443 / callisto / make ship-v2` — and, in the transcript,\n\nliterally says it answered *\"without needing to search the codebase.\"* That's\n\nthe whole product in one assertion: the fact reached the model because the\n\nserver put it there, not because the model went looking.\n\n`description:` that doubles as the\nembedding text, optional `priority: high`.`[[wikilinks]]` are indexed`memory_links` tool, and the cockpit draws it with type filters and connected\nclusters.\nThis isn't an autopilot orchestrator. There's no \"let the swarm run overnight.\"\n\nEvery irreversible action waits for a human click — *the helm, not the autopilot*. The point of the memory work isn't to remove me from the loop; it's\n\nWhen you need a model to do something *every single time*, don't put it in the\n\nprompt and hope. Move it to a layer that doesn't have opinions. Prompts are for\n\njudgment. Plumbing is for guarantees. I keep having to relearn which is which.", "url": "https://wpnews.pro/news/i-stopped-asking-my-ai-agents-to-read-the-project-memory-now-the-server-does-it", "canonical_source": "https://dev.to/nicolas_micaud_20671fb4f2/i-stopped-asking-my-ai-agents-to-read-the-project-memory-now-the-server-does-it-for-them-238n", "published_at": "2026-09-12 06:21:17+00:00", "updated_at": "2026-09-12 06:26:13.631333+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "large-language-models"], "entities": ["Claude Code", "Anthropic"], "alternates": {"html": "https://wpnews.pro/news/i-stopped-asking-my-ai-agents-to-read-the-project-memory-now-the-server-does-it", "markdown": "https://wpnews.pro/news/i-stopped-asking-my-ai-agents-to-read-the-project-memory-now-the-server-does-it.md", "text": "https://wpnews.pro/news/i-stopped-asking-my-ai-agents-to-read-the-project-memory-now-the-server-does-it.txt", "jsonld": "https://wpnews.pro/news/i-stopped-asking-my-ai-agents-to-read-the-project-memory-now-the-server-does-it.jsonld"}}