Tháng 3, tôi đang debug một config wrangler kỳ quặc cho blog cá nhân. Global API key trong ~/.credentials.env conflict với OAuth session của wrangler, deploy fail dù đã wrangler login. Mất khoảng 40 phút mò ra. Tôi save một memory file vào folder personal/: tên user-cloudflare-wrangler.md, body 30 dòng kể lại nguyên nhân cộng fix.

Tháng 5, tôi mở session mới ở một project khác cũng dùng wrangler. Claude vừa boot lên đã đọc memory đó (vì project trỏ chung tới folder shared), thấy pattern match, chủ động nói “trước khi chạy wrangler pages deploy, unset CLOUDFLARE_API_KEY cộng CLOUDFLARE_EMAIL cộng CLOUDFLARE_API_TOKEN đi nhé, anh đã ghi lại fix này 2 tháng trước”. Tôi không cần nhớ tôi từng gặp. Tôi không cần grep. Memory cứu khoảng 30 phút mò lại từ đầu.

Khoảnh khắc đó là lý do tôi giữ pipeline memory tự build, dù tuần này AgentMemory MCP đang trending GitHub với pitch nghe rất sang: SQLite backend, hybrid BM25 cộng vector embedding cộng knowledge graph, 51 MCP tool, theo README đạt 95.2% recall@5 trên LongMemEval-S. Tool nhìn xịn. Nhưng tôi vẫn chưa chuyển. Bài này tôi soi tại sao.

Tại sao agent cần long-term memory

Context window của Claude Sonnet 4.5 là 200K token, Opus 4.7 1M token. Nghe rộng nhưng vẫn là window. Session kết thúc, context tan. Session tiếp theo boot lại với CLAUDE.md cộng rules, không nhớ session trước đã ra quyết định gì, đã debug được vấn đề gì, đã chốt convention nào.

Với solo dev workflow nhiều project song song như tôi, vấn đề không phải “agent quên hôm qua”, mà là “agent không biết tôi đã quyết định một convention 2 tháng trước ở project khác, giờ đang lặp lại pattern đó”. Long-term memory là cách neo các quyết định đó lại để future session có thể đọc.

Câu hỏi thật sự không phải “có cần memory không”, mà là “memory lưu ở đâu, retrieve thế nào, agent đọc nó ra sao”.

Cách tôi đã build hệ memory hiện tại

Pipeline gồm 4 mảng. Tôi không viết hết spec ở đây, chỉ note ý tưởng.

autoMemoryDirectory config. Mỗi project có .claude/settings.local.json trỏ tới một folder shared trong ~/.claude/memory/. Folder chia theo “context”, ví dụ personal/, work-a/, work-b/, side-projects/. Khi Claude Code boot session trong một project, nó auto-load mọi .md trong folder tương ứng. Skill nf-memory lo cái config này per-project.

Plain markdown với YAML frontmatter. Mỗi memory là một file. Frontmatter có name, description, metadata.type (user, feedback, project, reference), metadata.project, metadata.cwd, metadata.tags, metadata.related. Tôi tự viết một global rule user-memory-frontmatter.md để Claude tuân thủ schema mỗi khi save. Body là markdown thuần.

MEMORY.md index. File 1 dòng/entry, max ~200 dòng, group theo bucket (Now, Next, Done, Reference). Là cửa sổ Claude nhìn trước khi quyết định grep sâu vào file nào.

Consolidation bằng skill nf-dream. Skill chạy 8 mode (preview, reorganize, handoff, consolidate, dedupe, stale, lint, rollback). Đó là “sleep” của hệ memory: classify file thành Now / Next / Done / Future / Reference / Stale, rewrite MEMORY.md, archive aged session-end states, dedupe topic overlap. Snapshot-first, không bao giờ delete, có rollback.

Sync giữa machine. Folder memory/ là một git submodule, repo riêng claude-memory private. Mỗi machine pull về SHA giống nhau. Single branch main, conflict rare vì memory mostly additive. nf-cc-sync skill lo việc đồng bộ.

Tổng cost: $0 hosting, $0 embedding. Cost duy nhất là vài giây Claude load folder lúc boot session, cộng thời gian tôi tự bảo trì.

AgentMemory MCP là gì

Theo README repo rohitg00/agentmemory, AgentMemory là một MCP server standalone, persist memory cho Claude Code, Cursor, Gemini CLI, Codex CLI, và bất kỳ MCP client nào. Stack thật sự gồm:

  • Backend: SQLite, không cần external service.
  • Vector store: in-memory vector index, default embedding bằng all-MiniLM-L6-v2 local (free, không cần API key); cũng hỗ trợ Gemini, OpenAI, Voyage AI, Cohere, OpenRouter.
  • Retrieval: hybrid triple-stream, BM25 cộng vector cosine cộng knowledge graph traversal, fuse bằng Reciprocal Rank Fusion (k=60).
  • Tier memory: 4 tier (working, episodic, semantic, procedural), kèm 12 hook auto-capture và 51 MCP tool cho operation.
  • Benchmark (theo README): 95.2% recall@5, 98.6% recall@10, 88.2% MRR trên LongMemEval-S 500 câu. Token efficiency claim ~170K token/năm so với 19.5M token/năm nếu paste full context, tức 92% fewer token so với LLM-summarized approach.
  • Install: npx @agentmemory/agentmemory không cần install, hoặc global. Apache-2.0.

Đọc list này tôi thấy đây là tool build cho ai chạy nhiều agent, retrieve nhiều fact, không có thời gian quản lý memory bằng tay. Không phải build cho ai có 60 file markdown và muốn grep -r ra ngay.

So sánh từng axis

Tôi sẽ tránh kiểu “tool A tốt hơn tool B”. Tool tốt là tool fit workflow.

Persistence backend. Plain markdown là file phẳng trên filesystem, không lock, không corrupt khi crash, mở bằng bất cứ editor nào. AgentMemory dùng SQLite, cũng là single file nhưng phải qua driver đọc. Khi memory chỉ vài chục file, markdown thắng hands-down về tính kiểm tra. Khi memory lên cỡ vài nghìn entry với cross-reference dày, SQLite quản lý relation và index tốt hơn nhiều.

Schema. Markdown frontmatter mềm, tôi đổi schema bằng cách edit một rule file là xong, future session sẽ tuân theo. Nhưng cái mềm đó cũng là cái yếu: không có validator tự động ngoài chính Claude. SQLite có schema cứng, một field thêm vào là phải migrate. Đổi schema chậm hơn nhưng đảm bảo nhất quán hơn.

Retrieval. Đây là axis khác biệt rõ nhất. Markdown retrieve bằng cách: Claude đọc nguyên folder lúc boot, nhớ ngữ cảnh, khi cần thì grep hoặc đọc file cụ thể. Nó là “agent đọc trước khi cần”. Bottleneck là context window: với 60 file markdown trung bình 2KB mỗi file, tổng ~120KB, vẫn fit. Nhưng nếu lên 500 file thì không fit nữa, agent phải selective load.

AgentMemory ngược lại: agent gọi MCP tool recall(query) khi cần, server trả top-k kết quả bằng hybrid search. “Agent đọc khi cần”. Quy mô không bị giới hạn bởi context. Recall@5 95.2% theo README là số tốt cho task hỏi-trả-lời. Nhưng nó cũng là số benchmark trên LongMemEval-S, không phải workload của tôi (debug context, decision log, quirky config).

Câu hỏi thật là: workload của bạn có dạng “tra cứu fact rời rạc” hay “load nguyên decision tree project rồi suy luận”? Workload tôi thiên về dạng 2, retrieval-on-demand giúp ít hơn vì Claude cần context đầy đủ để hiểu decision, không phải 5 fact rời.

Sync giữa machine. Markdown plus git submodule là pattern đã solve. Tôi push memory lên private repo, machine khác git submodule update --init, xong. Conflict cực hiếm vì memory mostly additive (file mới được tạo, file cũ ít edit lại). AgentMemory dùng SQLite, sync database giữa machine là bài toán khó hơn: hoặc export/import thủ công, hoặc setup một service làm source of truth (mà claim là “no external dependencies” thì lại không có service). Repo README chưa nói rõ multi-machine sync; nếu bạn chạy 1 máy thì axis này không quan trọng, nhưng tôi nhảy giữa MacBook và homelab server hằng ngày.

Observability. Đây là axis nặng nhất với tôi. Plain markdown human-readable. Tôi mở Obsidian, gõ Cmd+P, search memory như note. Tôi grep cli được. Tôi git log thấy memory nào sửa khi nào, ai sửa. Khi Claude làm điều lạ, tôi đọc memory để hiểu vì sao nó tin một fact nào đó. Audit cực dễ.

SQLite plus vector embedding là black box hơn. Có CLI tool xem, có dashboard viewer real-time theo README, nhưng đọc một fact cụ thể không nhanh bằng cat file.md. Khi agent halucinate hoặc recall sai, debug “tại sao recall ra item này” cần hiểu BM25 score, cosine similarity, RRF fusion. Người dùng đại trà ít ai làm việc đó.

Cost. Markdown plus git: $0, kể cả lúc folder lên vài trăm file. AgentMemory với embedding local (all-MiniLM-L6-v2): $0 nhưng cost compute lúc index. Nếu chuyển sang Gemini/OpenAI embedding để boost quality: vài $/tháng tùy volume. Số tiền nhỏ, nhưng nó là một dây phụ thuộc nữa lên external API.

Skill composition. Đây là điểm tôi suy nghĩ nhiều nhất. Hệ markdown của tôi compose tự nhiên với rules và skills khác: user-memory-frontmatter.md rule chuẩn hóa save, nf-dream skill consolidate, nf-memory skill config, nf-cc-sync skill sync. Mỗi layer là một file plain text Claude đọc lúc boot. AgentMemory là một MCP server đứng riêng. 51 MCP tool, 6 resource, 3 prompt, 4 skill. Tích hợp tốt nếu bạn live trong MCP ecosystem, nhưng nó không “blend” với rule-based config Claude Code, nó là một stack song song.

Khi nào AgentMemory thật sự hợp

Nhìn từ feature list, tool này build cho:

  • Multi-agent system với nhiều agent độc lập cần share fact qua lease và signal. Markdown không có cơ chế lock, agent ghi đè nhau là chuyện thường.
  • Workload retrieve hàng trăm fact rời mỗi turn, kiểu agent customer support hỏi đáp policy. Hybrid search là đúng dụng cụ.
  • Team setup không muốn user thấy memory raw (privacy-first design strip secret trước khi store). Nếu memory có PII hoặc secret leak, SQLite cộng filter tốt hơn markdown plain text.
  • Workload long context history, theo claim 92% fewer token so paste full context. Với task agent chạy lâu nhiều turn, cost token có thể đáng kể.

Khi nào markdown vẫn thắng

Trường hợp của tôi (và nhiều solo dev tôi đoán):

  • Dưới ~100 memory file mỗi project context. Grep nhanh, đọc tay được.
  • Single-user, không multi-tenant. Không cần lease, không cần signal.
  • Cần audit thường xuyên. Plain text giúp tôi debug khi Claude làm điều lạ.
  • Multi-machine (laptop, server, máy mới mỗi 2-3 năm). Git submodule giải quyết gọn.
  • Workflow nhiều project song song, mỗi project có context riêng. Folder structure rõ ràng hơn database schema cho não tôi.
  • Tích hợp sâu với rule và skill system của Claude Code. Tôi đã đầu tư vào layer này, AgentMemory đứng song song chứ không thay thế.

Tôi đang định thử AgentMemory ở đâu

Sau khi đọc kỹ, tôi nghĩ có một use case fit: project có agent tự động trả lời câu hỏi từ corpus tài liệu khách hàng. Đó là workload retrieval-heavy, fact rời rạc, query đa dạng, ngữ cảnh có thể vượt context window. Bạn không cần audit memory bằng mắt, bạn cần recall@5 cao. Hybrid BM25 cộng vector là đúng dụng cụ.

Nhưng cho workflow Claude Code cá nhân, debug, decision log, quirky config, tôi vẫn giữ markdown.

Lời cuối

Có một moment tôi nhớ. Tháng trước, tôi nhờ Claude đọc memory/personal/feedback_claude_config_repo.md và quyết định pattern branch-per-machine. Memory đó là một feedback note tôi save sau một lần config repo nhầm năm 2026-03. Claude đọc 30 giây, áp dụng pattern, không hỏi lại. Tôi không cần explain context. Memory đó là người tôi cũ nói chuyện với tôi mới.

Vector embedding làm được điều tương tự không? Có thể. Nhưng cảm giác đọc một file markdown nguyên văn, hiểu được tại sao tôi cũ ghi cái đó, không thay thế được bằng top-k hit. Ít nhất là cho workflow của tôi, bây giờ.

Tool xịn nhưng không phải tool nào cũng cần đổi. AgentMemory đáng tracking, đáng thử cho workload đúng. Còn markdown thì vẫn ngồi đó, im lặng, làm việc.