{
  "source_file": "0930",
  "source_platform": "Dev.to",
  "author": "Enrique Bruzual",
  "title_listed": "Your AI Agent is Stuck in a Loop. Here's the Memory Layer That Breaks It and Saves You Money",
  "keywords": "",
  "domain": "大模型算法",
  "content_type": "深度技术解析",
  "is_paid_flag": "否",
  "url": "https://dev.to/kike/your-ai-agent-is-stuck-in-a-loop-heres-the-memory-layer-that-breaks-it-and-saves-you-money-5fni",
  "publish_date": "2026-05-19",
  "corpus_stage": "",
  "notes": "",
  "id": "3e0e18e4cb09",
  "collected_at": "2026-10-02T14:05:26",
  "title": "Your AI Agent is Stuck in a Loop. Here's the Memory Layer That Breaks It and Saves You Money - DEV Community",
  "body_markdown": "Every time you open a new chat in Cursor, VS Code, Antigravity and even Claude Desktop, you paste your codebase back in. Or you let the IDE do it automatically, same result. You're burning context tokens on files the agent already \"knew\" ten minutes ago in a different window. The agent re-reads\nmy_models.py\n,\nyour_script.js\n,\ntheir_script.ts\n,\nindex.html\nand the three service files it touched yesterday, just to orient itself before answering your actual question.\nThat's not a context window problem. It's a memory architecture problem. There's no persistence layer between sessions or IDEs. The fix isn't a bigger context window; it's not sending the same data twice.\nIn a real test session with Copilot, after three exchanges with four unnecessary re-queries, zerikai_memory's tool results accounted for just\n1.6% of a 128K context window\n. A raw file-chunk retrieval setup doing the same work would burn\n~40% of that window\nbefore you got to your actual question. On the DeepSeek side, locking the project brief as a fixed system prefix means every query hits the KV cache at\n$0.0028/M tokens instead of $0.14/M\n, a\n50x cost reduction\non the largest token block per call.\nThat's the exact problem\nzerikai_memory\nwas built to solve.\n(\nOpen source\n)\nHi, I'm Enrique, an AI software engineer with over 30 years of tech experience. I built zerikai_memory after diagnosing a structural bottleneck in my own workflows: context loss between sessions, redundant re-injection across IDEs, and rising per-query costs that compound with every sloppy retrieval. The rising cost of AI IDE subscriptions made the economics impossible to ignore, but the underlying architecture problem was already there. zerikai_memory is the engineering response to that diagnosis, built for developers who want precision and cost control.\nWhat It Actually Does\nzerikai_memory\nis a local MCP server. Any IDE that supports the Model Context Protocol (Cursor, pi, Antigravity, Copilot, and even Claude Desktop) can connect to it. When you run\nscan_workspace\n, it walks your project using\ntree-sitter\nto parse source files into individual code entities:\nFunctions\n,\nClasses\n,\nMethods\n,\nHTML components\n.\nEach entity gets its own embedding in a local\nChromaDB\ncollection, along with structured metadata:\nLanguage\n,\nReturn type\n,\nParent class\n,\nLine numbers\n,\nParam count\n,\nDecorators\n,\nDocstring presence.\nThat last part matters. Most RAG setups (including the ones built into commercial IDEs) chunk files by token count or line count, which means a function might get split across two chunks, or buried under 500 lines of imports. This is a corner being cut at your expense: you pay for the tokens, the agent gets noise.\nzerikai_memory\ntreats each function as the atomic unit instead.\nextract_entities\nin\ncode_indexer.py\nreturns a list of\nCodeEntity\nobjects, one per parsed symbol: clean signal, no noise.\nWhen your agent queries memory,\nalong with the raw answer\n, it gets\ninline source citations\nback:\nSources:\n`extract_entities`\n#code_indexer.py:184 (0.35)\n`_extract_js_function`\n#code_indexer.py:595 (0.81)\n`_extract_js_like`\n#code_indexer.py:543 (0.89)\n`CodeEntity`\n#code_indexer.py:156 (0.83)\n`_extract_html`\n#code_indexer.py:907 (0.84)\n\n(raw answer synthesized from those sources)\nEnter fullscreen mode\nExit fullscreen mode\nThe IDE agent doesn't hunt for the function; the citations give it the exact file, line number, and L2 distance score.\n#code_indexer.py:184\nis plain text that renders in every IDE and is clickable in VS Code Copilot, so you can jump straight to the source too. No additional search, no extra API call.\nThe Indexing Cost Is Zero\ntree-sitter\nis a deterministic local parser. It runs entirely on your machine, no API calls, no LLM involvement.\nParsing\nand\nembedding\nyour codebase\ncosts $0.00\n.\nThe only thing that costs money is the\nproject brief\n: a 9-section structured summary (Overview, Technical Stack, Core Architecture, Primary Conventions, Purpose, Key Files, Data Flow, Development & Testing, Future Roadmap). That brief is generated once after the first scan using either the\nDeepSeek API\nor\nOllama\n. With DeepSeek, it's a few cents. With Ollama, it's free. After that, the brief is locked and cached.\nWhy lock it? Because the brief is the fixed prefix of every system message sent to DeepSeek. DeepSeek's KV cache means identical prefixes are stored server-side after the first call, so subsequent queries hit the cache at $0.0028/M tokens instead of \\$0.14/M tokens. That's a 50× cost reduction on the largest token block per query. Intentionally keeping the brief stable is what makes that discount work consistently.\nIf you update the Architecture or implement a large feature, you can regenerate the brief by asking the MCP server to\nupdate_brief\n.\nAuto-Routing: Paying Only for What Needs It\nNot every query deserves a cloud LLM. A lookup like \"where is\nprocess_data\ndefined?\" is a short, specific question that Ollama handles fine locally. An architectural question like \"explain how the query routing pipeline decides between DeepSeek v4-flash and v4-pro\" is a 20-word query touching design decisions, and that earns the cloud call.\nThe routing logic in\n_should_use_cloud()\nruns a 4-step priority chain on every incoming query:\nExplicit override:\nuse_cloud=True\nor\nuse_cloud=False\npassed directly; short-circuits everything else.\nArchitectural keyword escalation:\nif the query contains design/architecture terms (configured in\nconfig.py\n), route to DeepSeek.\nLength escalation:\nqueries of 40 words or more route to DeepSeek.\nDefault fallback:\nfall back to whatever\nMEMORY_MODE\nis set to in\n.env\n(\nlocal\n,\ncloud\n, or\nhybrid\n).\nWithin the DeepSeek path,\n_select_model\npicks between v4-flash and v4-pro based on query complexity. Short cloud queries get the cheaper model; heavier ones get the capable one. You're not paying v4-pro rates for a function lookup.\nTip:\nstart in\ncloud\nmode (DeepSeek API), then you can try\nhybrid\nand then\nlocal\n(Ollama).\nLexical Re-ranking: Fixing the Semantic Similarity False Positive Problem\nSemantic similarity alone has a well-known failure mode: a generic function that\ndescribes\nthe same concept as your query can outscore the specific function you actually want. A file summary mentioning \"parsing\" might beat\nparse_entities()\nin cosine space if the embeddings aren't tight.\nzerikai_memory\nadds a re-ranking pass on top of ChromaDB's semantic results. After distance filtering removes weak matches, survivors are re-scored by weighted keyword overlap in entity names and docstrings:\nscore\n=\n(\n1\n/\ndistance\n)\n+\n(\nkeyword_hits\n×\nLEXICAL_RERANK_WEIGHT\n)\nEnter fullscreen mode\nExit fullscreen mode\nA function named\nextract_entities\nwill outrank a vague file-level summary that happened to embed close to the query. No results are dropped; it's a pure reorder. The weight is configurable via\nENABLE_LEXICAL_RERANK\nin\n.env\n. It's off by default; turn it on if you're seeing generic summaries crowding out specific function hits.\nThe reranking test in the inline citations example above shows it working:\nVS Code Query:\n{\n\"workspace\"\n:\n\"zerikai_memory\"\n,\n\"user_query\"\n:\n\"extract function for parsing code entities from source files. Show me the Sources table.\"\n}\nEnter fullscreen mode\nExit fullscreen mode\nReturns\nextract_entities\nat distance 0.35 as the top hit, with the JS and HTML extractors behind it. Notably,\n_extract_markdown\ndidn't appear despite sharing vocabulary, which is exactly the false positive problem the\nre-ranker exists to solve\n.\nContext Window Impact\nEntity-level indexing matters most when the agent is sloppy. In a test session with Copilot, after three back-and-forth exchanges (including four re-queries it didn't need), the context window sat at 17.1K of 128K tokens, just 13%. The tool results from Zerikai accounted for 1.6% of that total.\nIf zerikai returned raw file chunks instead of individual entities, a single retrieval might pull 500 lines of a file to find one function. Twelve retrievals across three turns could burn north of 40% of the window before you even got to your actual work.\nEntity-level (zerikai, tested)\nRaw file chunks (estimated)\nTool results after 3 turns, 4 calls\n1.6% of window (~2K tokens)\n~40% of window (~50K tokens)\nSpace left for actual work\n~111K tokens\n~28K tokens\nAgent re-queries\nNegligible cost\nAmplifies the burn\nWhen the agent re-queries four times because it summarized too aggressively, entity-level indexing means it burned 800 tokens, not 50,000. The real cost of a bad agent layer is multiplied by how much data each retrieval returns (one of the reasons I migrated to pi.dev, but that's another write-up).\nSmall retrievals save you twice:\nthey stretch your IDE's token quota and they shrink your DeepSeek bill. Pay for the brief once. Query your own code for free.\nHow Agents Display Source Citations\nzerikai memory returns the full\n#file:line (distance)\nin every response. But each agent publisher decides how much of it to surface. The same query, same tool, four different agents:\nExample:\n\"Sources:\n_truncate_for_brief\n#main.py:401 (0.62)\"\nAgent\nCalls\nFailed\nShowed L2\nNotes\nAntigravity (Gemini)\n1\n0\nYes\nRe-rendered inline text as a table\nClaude Desktop\n1\n0\nYes\nShowed full citation in body\nCopilot\n5\n0\nNo\nRe-queried 4x, hid distance from user until asked\nPi (inside workspace)\n1\n0\nYes\nOne clean call when in the project path\nThe data is always there in context; the agent uses\n#file:line (distance)\nfor reasoning regardless.\nAsk:\n\"show me the full sources with distances\"\nand it surfaces the complete line. What you see is filtered by your agent's display layer, not by zerikai memory.\nWorkspace Isolation and\n.memignore\nEvery project gets its own ChromaDB sub-collection, its own SQLite records, and its own brief file. Queries for\nproject_a\ndon't pull from\nproject_b\n. Workspaces are identified by normalized filesystem path with deterministic UUIDs, so the same project opened from different IDE windows or different paths resolves to the same memory store.\nBefore any file hits the indexer,\n.memignore\nfilters it out. It works identically to\n.gitignore\n: glob patterns,\n#\ncomments, blank lines ignored.\nnode_modules/\n,\n.git/\n,\nvenv/\n, compiled output: configure it once per workspace, it's enforced on every scan.\nScans are idempotent. Re-scanning the same file overwrites its existing records using deterministic hashing. Stale entries (files deleted or added to\n.memignore\nsince the last scan) are automatically purged. Run\nscan_workspace\nas often as you want; no duplicates accumulate, no ghost records from renamed files.\nBe discriminative with the files and folders added to\n.memignore\n. We tend to save\ntest/\nor\nresearch/\n, and other dated resources, which add unnecessary noise to the ChromaDB index. Add those types of folders and files to\n.memignore\nto ignore them during the scan.\nLocal Mode: Zero Cost, No Data Leaves Your Machine\nIf you're working on a private codebase or just don't want to touch a cloud API, set\nMEMORY_MODE=local\nin\n.env\nand point\nzerikai_memory\nat a running Ollama instance. Everything runs locally: parsing, embedding, retrieval, and synthesis. The inline citations still work. The project brief still generates. Auto-routing routes everything to Ollama. Token tracking still logs usage (it just logs zero cost).\nThis makes the local mode genuinely useful for confidential projects, not just a fallback. The main trade-off versus DeepSeek is synthesis quality on complex architectural queries, as Ollama models are capable but won't match v4-pro on multi-hop reasoning about your codebase design.\nWhat It Doesn't Do\nWorth being explicit:\nzerikai_memory\ndoesn't replace your IDE's built-in context management for the file you're actively editing. It's additive; what it eliminates is the need to re-inject project-wide context at the start of every new session. It also doesn't currently support all languages tree-sitter handles;\nPython\n,\nJS/TS\n,\nHTML\n,\nCSS\n, and\nMarkdown\nare covered, and others are on the roadmap.\nThe project brief is intentionally locked after the first scan. If your architecture changes significantly, you need to trigger\nupdate_brief\nvia the MCP server. That's a manual step, and it's a deliberate trade-off for KV cache stability over automatic freshness.\nStack\nPython:\nMCP server, query routing, brief synthesis\nChromaDB:\nlocal vector store (file-based, stored in\n.brain/vector_db/\n)\nzerikai.db:\nSQLite workspace registry and token tracking (stored in\n.brain/zerikai.db\n)\ntree-sitter:\ndeterministic local code parser, zero API cost\nDeepSeek:\ncloud LLM (v4-flash and v4-pro), with KV cache optimization\nOllama:\nlocal LLM for zero-cost operation\nGetting Started:\nIndex\nzerikai_memory\nitself as your first workspace. It's the fastest way to see how entity-level indexing, lexical re-ranking, and inline citations actually work before applying them to your own projects. If your language isn't supported yet, search PyPI for\ntree-sitter-<language>\nto find the grammar bindings, then use the MCP server itself to guide you through adding it to\ncode_indexer.py\n. Rescan, and you're ready to index your other workspaces with the newly added language.\nThe repo is on GitHub:\nzerikai_memory\nIf you're running agent workflows across multiple IDEs or projects, the context re-injection overhead adds up.\nzerikai_memory\ncuts that out at the root.\nThe more interesting problems turned out to be elsewhere: getting traceable, line-precise source citations out of a retrieval layer so agents stop guessing and start pointing, and getting lexical re-ranking to prevent semantically close but functionally irrelevant results from crowding out the right answer.\nHave you thought about the impact of traceable sources on your own agent workflows? Have you hit the false-positive problem in semantic memory search? Drop your setup and approach below.\nThank you\nEnrique",
  "metadata": {
    "title": "Your AI Agent is Stuck in a Loop. Here's the Memory Layer That Breaks It and Saves You Money - DEV Community",
    "description": "Every time you open a new chat in Cursor, VS Code, Antigravity and even Claude Desktop, you paste... Tagged with ai, mcp, deepseek, discuss.",
    "keywords": "ai, mcp, deepseek, discuss, software, coding, development, engineering, inclusive, community",
    "author": null,
    "og:type": "article",
    "og:url": "https://dev.to/kike/your-ai-agent-is-stuck-in-a-loop-heres-the-memory-layer-that-breaks-it-and-saves-you-money-5fni",
    "og:title": "Your AI Agent is Stuck in a Loop. Here's the Memory Layer That Breaks It and Saves You Money",
    "og:description": "Every time you open a new chat in Cursor, VS Code, Antigravity and even Claude Desktop, you paste...",
    "og:site_name": "DEV Community",
    "og:image": "https://media2.dev.to/dynamic/image/width=1200,height=627,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkcvntqkj23yb37i9zldv.png",
    "twitter:site": "@thepracticaldev",
    "twitter:creator": "@",
    "twitter:title": "Your AI Agent is Stuck in a Loop. Here's the Memory Layer That Breaks It and Saves You Money",
    "twitter:description": "Every time you open a new chat in Cursor, VS Code, Antigravity and even Claude Desktop, you paste...",
    "twitter:card": "summary_large_image",
    "twitter:widgets:new-embed-design": "on",
    "twitter:image:src": "https://media2.dev.to/dynamic/image/width=1200,height=627,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkcvntqkj23yb37i9zldv.png"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/3e0e18e4cb09/code/body-000.txt",
      "chars": 284,
      "language": "text"
    },
    {
      "file": "attachments/3e0e18e4cb09/code/body-001.txt",
      "chars": 64,
      "language": "text"
    },
    {
      "file": "attachments/3e0e18e4cb09/code/body-002.txt",
      "chars": 144,
      "language": "text"
    }
  ],
  "images": [
    {
      "status": "ok",
      "url": "https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhj97805xxhedlvr75jqk.png",
      "bytes": 47670,
      "reused": true,
      "local_path": "attachments/3e0e18e4cb09/images/001.png",
      "src": "https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhj97805xxhedlvr75jqk.png",
      "alt": "Indexing workflow",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsanij2fqnl75ut0aaaz3.png",
      "bytes": 52978,
      "reused": true,
      "local_path": "attachments/3e0e18e4cb09/images/002.png",
      "src": "https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsanij2fqnl75ut0aaaz3.png",
      "alt": "Lexical re-ranking",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtwn6m8vwgl4tuizt1hj.png",
      "bytes": 62834,
      "reused": true,
      "local_path": "attachments/3e0e18e4cb09/images/003.png",
      "src": "https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtwn6m8vwgl4tuizt1hj.png",
      "alt": "Agent chat window screen grab",
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [],
  "links": [
    {
      "href": "https://github.com/KikeVen/zerikai_memory",
      "label": "zerikai_memory",
      "type": "a"
    },
    {
      "href": "https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhj97805xxhedlvr75jqk.png",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsanij2fqnl75ut0aaaz3.png",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtwn6m8vwgl4tuizt1hj.png",
      "label": "",
      "type": "a"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:50:00Z",
  "source_url": "https://dev.to/kike/your-ai-agent-is-stuck-in-a-loop-heres-the-memory-layer-that-breaks-it-and-saves-you-money-5fni",
  "papers": [],
  "actual_video_files": [],
  "body_chars": 13841,
  "expected_body_images": 3,
  "discovery_status": "ok",
  "delivery_status": "ok",
  "missing_reason": "",
  "raw_html": "attachments/3e0e18e4cb09/pages/source.html",
  "local_html": "attachments/3e0e18e4cb09/pages/article.html",
  "body_base_path": "attachments/3e0e18e4cb09/pages/",
  "body_markdown_path": "attachments/3e0e18e4cb09/pages/article.md"
}