Agent Memory Architecture - Kiến trúc Bộ nhớ Đa tầng cho AI Agents với Redis, Vector DB, ClickHouse và Knowledge Graph 2026
Posted on: 4/14/2026 12:19:21 PM
Table of contents
- 1. Vì sao một AI Agent cần bộ nhớ thực sự?
- 2. Phân loại bộ nhớ — khung CoALA là điểm tựa chung
- 3. Redis — nền tảng cho Working Memory và Session State
- 4. Vector DB — trái tim của Episodic và Semantic Memory
- 5. ClickHouse — nền tảng cold log và Episodic Memory quy mô lớn
- 6. Knowledge Graph — khi bộ nhớ có quan hệ
- 7. So kè 5 framework Memory tiêu biểu 2026
- 8. Vòng đời của một ký ức — 6 thao tác cốt lõi
- 9. Memory trong hệ Multi-Agent — chia sẻ hay cách ly?
- 10. Production concerns — những thứ giết chết một kiến trúc đẹp trên giấy
- 11. Kiến trúc tham khảo — gộp tất cả lại
- 12. Lộ trình triển khai từng bước cho team bạn
- 13. Kết luận
Một AI agent không có bộ nhớ thì chỉ là một cỗ máy phản xạ: mỗi lượt đối thoại là một lần bắt đầu lại từ con số không. Nhưng khi ta muốn agent học từ tương tác quá khứ, nhớ sở thích người dùng, duy trì trạng thái dự án kéo dài nhiều ngày và phối hợp với agent khác trong cùng một tổ chức, câu chuyện bộ nhớ đột nhiên trở thành một bài toán kiến trúc hệ thống thực thụ — với nhiều tầng lưu trữ, nhiều mô hình truy xuất, nhiều chính sách quên và củng cố. Bài viết này đi sâu vào Agent Memory Architecture năm 2026: từ phân loại bộ nhớ theo CoALA, đến cách ánh xạ từng tầng vào Redis, Vector DB, ClickHouse và Knowledge Graph, rồi mổ xẻ năm framework nổi bật nhất hiện nay — Letta (MemGPT), Mem0, Zep, LangMem và Anthropic Memory Tool.
1. Vì sao một AI Agent cần bộ nhớ thực sự?
Context window dài 200K, 1M token nghe có vẻ đủ cho "bất cứ thứ gì". Nhưng trong thực tế triển khai, ba giới hạn vật lý khiến chúng ta không thể chỉ nhồi toàn bộ lịch sử vào prompt:
- Chi phí tăng tuyến tính theo độ dài context. Mỗi lượt gọi LLM phải trả tiền cho từng token input; với một agent chạy 20 lượt hội thoại trong ngày, việc luôn đính kèm 80K token lịch sử sẽ nhanh chóng đốt ngân sách.
- "Lost-in-the-middle": các benchmark đều cho thấy mô hình ghi nhớ kém đoạn giữa của context dài. Context càng dài, xác suất mô hình bỏ qua chi tiết quan trọng càng cao.
- Ngữ cảnh không tái tạo được sau khi compact: khi Claude Code hay LangGraph thực hiện context compaction, các chi tiết không được "rút gọn" một cách có chủ đích sẽ biến mất vĩnh viễn. Nếu ta không chủ động ghi ra ngoài, agent sẽ "mất trí" ngay khi vượt ngưỡng.
Giải pháp chuẩn là tách rời bộ nhớ làm việc (working memory) nằm trong context window với các tầng bộ nhớ ngoài. Khi cần, agent truy xuất đúng đoạn memory cần thiết và nhúng vào prompt — thay vì mang vác toàn bộ quá khứ. Đây chính là tinh thần just-in-time context mà Anthropic khuyến nghị trong bài "Effective context engineering".
Memory là đòn bẩy chi phí, không chỉ là tính năng
Anthropic công bố Memory Tool giảm 84% token tiêu thụ trong các workflow dài. Mem0 (paper arXiv 2504.19413) báo giảm ~90% chi phí token và 91% P95 latency so với giải pháp nhồi full-context. Zep (arXiv 2501.13956) đưa context trung bình trên LongMemEval từ 115K xuống còn 1,6K token — tức hơn 98%. Điều này nghĩa là: bộ nhớ ngoài là kỹ thuật tối ưu chi phí bậc nhất trong LLM ops hiện nay.
2. Phân loại bộ nhớ — khung CoALA là điểm tựa chung
Hầu hết framework agent hiện đại — LangGraph, LangMem, Mem0, Letta, Zep — đều trực tiếp hoặc gián tiếp tham chiếu đến CoALA (Cognitive Architectures for Language Agents) của Sumers et al. (Princeton, 2023). CoALA vay mượn cách phân loại trí nhớ từ khoa học nhận thức và các kiến trúc cổ điển như ACT-R, Soar, rồi ánh xạ vào bối cảnh LLM agent.
| Loại bộ nhớ | Chứa gì | Đặc trưng truy cập | Ánh xạ hiện thực 2026 |
|---|---|---|---|
| Working memory (bộ nhớ làm việc) | Messages, scratchpad, tool outputs, reasoning state hiện tại | Đọc/ghi mỗi bước suy luận, luôn nằm trong context window | LangGraph State + Checkpointer, Letta Core Memory Blocks, Redis Hash/JSON |
| Episodic memory (bộ nhớ tình tiết) | Sự kiện cụ thể đã xảy ra — lượt hội thoại, trace tool call, quyết định và kết quả | Truy xuất theo ngữ cảnh, thời gian, chủ đề | Vector DB (episodic collection), ClickHouse (event log), Letta Recall Memory |
| Semantic memory (bộ nhớ ngữ nghĩa) | Sự thật đã được tổng quát hoá — "Alice là lập trình viên Go", "dự án dùng pnpm" | Truy xuất theo độ tương đồng, theo chủ thể, lọc dedup | Vector DB (semantic facts), Knowledge Graph, Mem0, LangMem profiles |
| Procedural memory (bộ nhớ thủ tục) | Cách thực hiện: skills, rules, workflows | Đính kèm system prompt hoặc nạp theo nhu cầu | Model weights + tool definitions + system prompt (LangMem prompt optimizer viết lại) |
| Reflective memory (bộ nhớ phản tỉnh) | Tổng kết, "insight" tầng cao được sinh ra từ các ký ức cấp thấp | Sinh định kỳ hoặc khi có đủ tín hiệu | Generative Agents (Park 2023), Zep communities, Letta sleeptime compute |
Ranh giới giữa các tầng không phải là một đường thẳng tắp. Một đoạn hội thoại có thể là episodic khi mới vừa diễn ra, và theo thời gian nó được chưng cất thành một semantic fact ("người dùng này không thích email marketing"). Một "reflection" có thể được sinh ra, rồi tự nó trở thành nguyên liệu cho reflection kế tiếp — hình thành một cây trừu tượng, đúng như những gì Park et al. trình diễn trong Generative Agents.
flowchart TB
A["Agent Loop"] -->|read/write| W["Working Memory
Redis / Checkpointer
~1ms"]
W -->|promote| E["Episodic Memory
Vector DB / ClickHouse
~50ms"]
E -->|consolidate| S["Semantic Memory
Vector DB / Mem0 / Profile
~80ms"]
S -->|entity link| G["Relational Memory
Knowledge Graph / Graphiti
~300ms"]
G -.->|reflection| R["Reflective Memory
LLM-synthesized insights"]
R -.->|feedback| S
E -->|archival| C["Cold Log
ClickHouse MergeTree
event replay"]
P["Procedural Memory
System prompt + tools"] -->|always in context| A
style A fill:#e94560,stroke:#fff,color:#fff
style W fill:#4CAF50,stroke:#fff,color:#fff
style E fill:#0f3460,stroke:#fff,color:#fff
style S fill:#0f3460,stroke:#fff,color:#fff
style G fill:#0f3460,stroke:#fff,color:#fff
style R fill:#ff9800,stroke:#fff,color:#fff
style C fill:#2c3e50,stroke:#fff,color:#fff
style P fill:#8e44ad,stroke:#fff,color:#fff
Kiến trúc bộ nhớ đa tầng cho AI Agent — các mũi tên thể hiện luồng promote, consolidate và reflection giữa các tầng
3. Redis — nền tảng cho Working Memory và Session State
Redis giữ vị trí thống trị ở tầng working memory vì ba lý do không thể tranh cãi: độ trễ dưới 1ms, các kiểu dữ liệu rất hợp với trạng thái hội thoại (Hash, List, Stream, JSON), và ngữ nghĩa TTL cho phép tự động "quên" những gì quá hạn. Redis 8 (GA 2025) và phiên bản 8.4 còn thống nhất vector search trực tiếp trong core, bỏ nhu cầu module riêng — vừa làm cache vừa làm embedding store trong cùng một cụm.
3.1. Session state bằng Hash + TTL
Mỗi session hội thoại được lưu thành một Hash. Redis 8 hỗ trợ TTL theo từng field — nghĩa là bạn có thể hết hạn riêng một "last_tool" trong khi vẫn giữ "user_profile" tồn tại lâu hơn. Đây là thay đổi quan trọng so với Redis 7.
import redis, time
r = redis.Redis(host="redis-prod", decode_responses=True)
# Lưu trạng thái session
r.hset("session:user_42", mapping={
"thread_id": "t-9f1c",
"last_intent": "refactor_auth",
"last_tool": "file_edit",
"turn_count": 7,
})
r.expire("session:user_42", 3600) # hết hạn toàn bộ sau 1 giờ
# Redis 8: hết hạn riêng một field (HEXPIRE)
r.execute_command("HEXPIRE", "session:user_42", 300, "FIELDS", 1, "last_tool")
3.2. Conversation buffer bằng Stream
Khi nhiều agent cùng theo dõi một luồng hội thoại (ví dụ một Supervisor và các Specialist), XADD và consumer group của Redis Streams cho ngữ nghĩa "fan-out with acknowledgement" miễn phí — một agent đã xử lý không kéo lại tin nhắn đó nữa, nhưng agent khác vẫn thấy.
r.xadd("chat:thread_42", {
"role": "user",
"content": "Sửa lại cache invalidation logic",
"ts": int(time.time() * 1000),
})
# Consumer group cho mỗi agent
r.xgroup_create("chat:thread_42", "supervisor", id="0", mkstream=True)
r.xgroup_create("chat:thread_42", "coder", id="0", mkstream=True)
3.3. LangGraph Checkpointer với Redis
LangGraph đóng gói working memory dưới khái niệm Checkpointer — lưu object State của graph sau mỗi superstep để có thể rewind, branch hoặc chèn human-in-the-loop. Package langgraph-checkpoint-redis cung cấp RedisSaver (lưu toàn bộ lịch sử checkpoint) và ShallowRedisSaver (chỉ giữ snapshot mới nhất để tiết kiệm bộ nhớ).
from langgraph.graph import StateGraph
from langgraph.checkpoint.redis import RedisSaver
memory = RedisSaver.from_url("redis://redis-prod:6379/0")
graph = builder.compile(checkpointer=memory)
config = {"configurable": {"thread_id": "user_42:session_1"}}
graph.invoke({"messages": [HumanMessage("Tóm tắt tiến độ hôm qua")]}, config=config)
# Rewind về checkpoint cũ
history = list(graph.get_state_history(config))
graph.update_state(history[3].config, values={...})
Checkpointer là RAM, Store là ổ cứng
LangGraph tách rõ hai primitive: Checkpointer là thread-scoped (một thread hội thoại), Store là cross-thread (xuyên phiên, xuyên user). Hãy nhớ nguyên tắc: thứ gì chỉ có ý nghĩa trong một hội thoại → Checkpointer; thứ gì cần tồn tại sang phiên sau → Store. Nhầm lẫn hai thứ này là nguồn gốc nhiều lỗi "agent quên" và "agent bị rò rỉ giữa user".
4. Vector DB — trái tim của Episodic và Semantic Memory
Khi phải truy xuất "bằng nghĩa" thay vì "bằng key chính xác", Vector DB là câu trả lời. Dù là Pinecone, Weaviate, Qdrant, Milvus, pgvector hay Redis Vector Search, mô hình chung đều là: mỗi ký ức được biểu diễn bằng một embedding ~1000 chiều, kèm metadata {user_id, namespace, type, timestamp, source_event_id}, và được truy vấn bằng ANN (approximate nearest neighbor) có kèm filter metadata.
Tầng vector chứa hai loại khác nhau, và sai lầm phổ biến là gộp chung chúng:
- Semantic facts: mỗi hàng là một khẳng định nhỏ gọn — "Người dùng thích dark mode", "Codebase dùng pnpm". Thường là kết quả của bước extraction/dedup và có số lượng nhỏ trên mỗi user.
- Episodic snippets: mỗi hàng là một đoạn hội thoại hoặc một ví dụ few-shot chưng cất từ trải nghiệm quá khứ. Số lượng nhiều, hay phình to theo thời gian.
Đừng nhét cả hai vào chung một collection. Chúng có TTL khác nhau, threshold similarity khác nhau, và đặc biệt semantic facts có ràng buộc nhất quán (một user chỉ có một địa chỉ nhà), còn episodic thì không. Trộn lẫn dẫn đến việc retrieval lôi về 5 phiên bản khác nhau của cùng một sự thật, khiến mô hình bối rối.
from langgraph.store.postgres import PostgresStore
store = PostgresStore.from_conn_string("postgresql://...", index={
"dims": 1536, "embed": embed_fn
})
namespace_semantic = ("user_42", "semantic")
namespace_episodic = ("user_42", "episodic")
# Semantic — ghi theo key ổn định để upsert
store.put(namespace_semantic, key="preferences:editor",
value={"fact": "Dùng VS Code làm editor chính"})
# Episodic — mỗi turn là một row riêng
store.put(namespace_episodic, key=f"turn:{turn_id}",
value={"summary": "User đã từ chối suggestion thêm TypeScript generic"})
5. ClickHouse — nền tảng cold log và Episodic Memory quy mô lớn
Khi kho sự kiện vượt mốc vài triệu hàng, Vector DB không còn là lựa chọn kinh tế cho mọi truy vấn — đặc biệt là các truy vấn analytic (tổng token theo user, latency p99 theo tool, error rate theo agent). Đây là lúc ClickHouse bước vào với tư cách là event log / episodic memory tier. Langfuse, Laminar, HyperDX (ClickStack), Respan — gần như mọi nền tảng observability LLM trong 2024–2025 đều đã chuyển về ClickHouse. Langfuse báo cáo thời gian query p95 giảm "từ phút xuống thời gian thực" sau khi migrate từ Postgres.
CREATE TABLE agent_events (
trace_id UUID,
span_id UUID,
parent_span Nullable(UUID),
agent_id LowCardinality(String),
user_id String,
event_type LowCardinality(String), -- tool_call | llm_call | memory_read | memory_write
timestamp DateTime64(6),
prompt_tokens UInt32,
output_tokens UInt32,
latency_ms UInt32,
cost_usd Decimal(10, 6),
payload String CODEC(ZSTD(3))
) ENGINE = MergeTree
PARTITION BY toYYYYMM(timestamp)
ORDER BY (agent_id, user_id, timestamp)
TTL timestamp + INTERVAL 180 DAY;
Ba engine family đặc biệt hữu ích cho memory layer:
- ReplacingMergeTree: khử trùng lặp theo
(trace_id, span_id)cho ingestion at-least-once. - AggregatingMergeTree + Materialized View: pre-aggregate token cost và latency theo user/ngày. Dashboard không phải scan hàng tỷ dòng.
- CollapsingMergeTree: model hoá state delta — hữu ích khi muốn replay trạng thái agent tại một thời điểm trong quá khứ.
Quan trọng hơn, ClickHouse biến tầng này thành nền tảng cho reflection và episodic recall: khi agent cần "nghĩ lại" về 30 ngày gần nhất, một tác vụ reflection có thể chạy một câu truy vấn ClickHouse lấy ra đúng các sự kiện quan trọng, rồi đưa qua LLM để sinh ra các insight cấp cao — những insight này sau đó được đẩy trở lại vào tầng semantic memory.
6. Knowledge Graph — khi bộ nhớ có quan hệ
Vector retrieval rất tệ ở ba việc: quan hệ nhiều chặng ("Alice là đồng nghiệp của ai?"), tính nhất quán ("user chỉ có một địa chỉ hiện tại") và temporal reasoning ("tuần trước Alice còn ở team A"). Các hạn chế này buộc nhiều hệ thống phải bổ sung một tầng Knowledge Graph. Nổi bật nhất 2025–2026 là Graphiti của Zep — một temporal KG engine được xây dựng trên Neo4j (mặc định), FalkorDB, Kuzu hoặc Amazon Neptune.
Điểm đắt giá nhất của Graphiti là mô hình bi-temporal: mỗi cạnh mang hai cặp thời gian — thời gian sự kiện (valid_from, valid_to) và thời gian quan sát (ingested_at, invalidated_at). Khi một sự thật mới mâu thuẫn với sự thật cũ, cạnh cũ không bị xoá mà chỉ đóng cửa sổ valid_to; truy vấn có thể hỏi "agent đang tin gì bây giờ?" hoặc "agent đã tin gì vào thứ Ba tuần trước?".
flowchart LR
Q["Câu hỏi"] --> E1["φ_cos
Embedding cosine"]
Q --> E2["φ_bm25
Full-text BM25"]
Q --> E3["φ_bfs
Graph BFS từ seed"]
E1 --> R["Reranker
RRF / MMR / CE"]
E2 --> R
E3 --> R
R --> T["Top-k facts
+ valid_from / valid_to"]
style Q fill:#e94560,stroke:#fff,color:#fff
style R fill:#ff9800,stroke:#fff,color:#fff
style T fill:#4CAF50,stroke:#fff,color:#fff
Pipeline truy xuất hybrid của Zep / Graphiti — không có LLM trong đường sync, nên P95 giữ quanh ~300ms
Một chi tiết rất quan trọng: không có lời gọi LLM nào trong đường truy xuất. Cả ba hàm φ_cos, φ_bm25, φ_bfs đều là query thuần, rerank bằng RRF (Reciprocal Rank Fusion) hoặc MMR. Nhờ vậy, Graphiti đạt latency P95 ~300ms ngay cả với đồ thị hàng trăm triệu cạnh. Trên benchmark LongMemEval, Zep đạt +18.5% accuracy so với baseline và giảm ~90% latency (2.58s so với 28.9s) — con số khẳng định một nguyên tắc thiết kế: đừng đặt LLM trong đường đọc đồng bộ.
7. So kè 5 framework Memory tiêu biểu 2026
Ranh giới giữa các framework memory đang rõ dần. Mỗi lựa chọn phản ánh một triết lý thiết kế khác nhau — và hiểu đúng triết lý đó quan trọng hơn nhớ được API nào.
7.1. Letta (MemGPT) — agent như một hệ điều hành
Letta (tiền thân là MemGPT, paper của Packer et al. 2023) đưa ra ẩn dụ nền tảng: context window là RAM, storage ngoài là disk, LLM là CPU. Mô hình hoá bộ nhớ thành ba tầng có thể "page" qua lại bằng tool call:
| Tầng | Nằm ở | Thời gian sống | Ai chỉnh sửa |
|---|---|---|---|
| Core memory blocks | Trong system prompt, luôn hiện | Dài hạn, bền qua phiên | Chính agent qua core_memory_append, core_memory_replace |
| Recall memory | DB ngoài (mọi tin nhắn lưu lại) | Dài hạn | Hệ thống tự ghi, agent có thể search |
| Archival memory | Vector DB / Graph DB | Dài hạn | Agent qua archival_memory_insert, archival_memory_search |
Đóng góp mang tính khai mở của MemGPT chính là self-editing memory — mô hình được prompt/fine-tune để chủ động biên tập trạng thái của chính nó, không chờ một ai đó ở ngoài. Toàn bộ "trào lưu" memory tool sau này — kể cả Anthropic Memory Tool — đều có gốc rễ ở đây.
Năm 2025, Letta v1 tái kiến trúc agent loop theo bài blog "Rearchitecting Letta's Agent Loop: Lessons from ReAct, MemGPT, & Claude Code": bỏ heartbeat và wrapper send_message, chuyển sang reasoning tự nhiên + direct assistant generation để khai thác GPT-5 và Claude Sonnet 4.5. Kèm theo đó là MemFS — một filesystem bộ nhớ có thể track bằng git — và cơ chế sleeptime compute: một agent nền chạy song song, xử lý consolidation, summarization và reflection trong lúc agent chính đang chờ tin nhắn tiếp theo của user. Nhờ vậy các tác vụ nặng không chèn vào P95 của request.
7.2. Mem0 — universal memory layer với extraction + dedup
Mem0 (arXiv 2504.19413, 4/2025) được định vị là một lớp memory phổ quát, plug vào bất kỳ LLM app nào. Điểm phân biệt lớn nhất của Mem0 không nằm ở storage (dùng vector DB là chính), mà nằm ở cơ chế write hai pha:
- Extraction: LLM đọc các turns mới, sinh ra các memory ứng viên ở dạng fact nguyên tử.
- Update: với mỗi ứng viên, hệ thống lấy các memory liền kề đã tồn tại, rồi một Conflict Detector + Update Resolver quyết định một trong bốn thao tác:
ADD(fact mới),UPDATE(tinh chỉnh cái cũ),DELETE(vô hiệu) hoặcNOOP(đã biết).
Đây chính là khác biệt với RAG ngây thơ: memory được dedup và reconcile tại thời điểm ghi, không phải chỉ lúc đọc. Kết quả trên benchmark LOCOMO (long-conversation): +26% accuracy so với memory sẵn có của OpenAI, giảm 91% P95 latency và giảm >90% chi phí token so với full-context.
from mem0 import Memory
m = Memory()
m.add("Tôi thích dark mode và dùng VS Code", user_id="alice")
m.add("Dự án hiện tại dùng pnpm, không phải npm", user_id="alice")
# Mem0 tự chạy hai pha: trích fact, phát hiện xung đột, quyết định ADD/UPDATE
m.search("alice dùng editor nào?", user_id="alice")
# [{"memory": "Uses VS Code", "score": 0.91, ...}]
Mem0 có hai backend: Mem0 (vector thuần) và Mem0g — phiên bản graph dùng Neo4j hoặc Neptune. Mem0g thêm layer graph để giải các câu hỏi multi-hop và temporal. AWS đã công bố reference architecture cho Mem0 với ElastiCache for Valkey (hot tier) và Neptune Analytics (graph tier).
7.3. Zep / Graphiti — temporal knowledge graph
Zep (arXiv 2501.13956, 1/2025) là hướng tiếp cận triệt để nhất về graph memory. Graphiti — engine lõi của Zep — tổ chức bộ nhớ thành ba tầng:
- Episodes: dữ liệu thô được nạp vào (messages + timestamps). Đây là lớp provenance ground-truth.
- Semantic entities + facts: LLM trích ra các entity và cạnh (subject, predicate, object), mỗi cạnh mang bi-temporal.
- Communities: cụm entity được nhóm theo Leiden community detection — tương tự cấu trúc của Microsoft GraphRAG, dùng để sinh ra các bản tóm tắt ở tầng cao.
Zep đánh bại MemGPT ngay trên chính benchmark DMR mà MemGPT tự tạo (94.8% so với 93.4% trên gpt-4-turbo), và trên LongMemEval cắt context trung bình từ 115K xuống 1.6K token. Bí mật nằm ở chỗ Graphiti không hạ thấp ambition — nó giữ được cả mối quan hệ lẫn tính thời gian, nhưng lại thay LLM retrieval bằng truy vấn thuần nên vẫn đạt ~300ms P95.
7.4. LangMem — bộ ba semantic, episodic, procedural
LangMem là SDK memory chính thống của LangChain, phát hành 2025. Nó tách biệt rõ ràng ba loại memory theo tinh thần CoALA và cho phép ta chọn chiến lược riêng cho từng loại:
- Semantic memory: hai pattern — profile document (một tài liệu duy nhất tự tinh chỉnh) hoặc collection (nhiều fact rời). Tool
create_manage_memory_toolvàcreate_search_memory_tool. - Procedural memory: điều thú vị nhất của LangMem —
create_prompt_optimizerphân tích các trace thành công và thất bại rồi đề xuất bản viết lại của system prompt. Ba thuật toán: metaprompt, gradient, prompt_memory. Đây là procedural memory ở dạng prompt tự sinh. - Episodic memory:
extract_episodic_memorieschưng cất lịch sử thành các few-shot example có thể nạp lại khi cần.
7.5. Anthropic Memory Tool — bộ nhớ dạng file
Phát hành beta 29/9/2025 dưới tool type memory_20250818. Đây là một first-party tool, nghĩa là Claude được huấn luyện trực tiếp để biết khi nào nên tra memory và khi nào nên ghi. Sáu lệnh cơ bản, rất giống một editor file:
| Lệnh | Tham số | Mục đích |
|---|---|---|
view | path, view_range | List thư mục (2 tầng, kèm size) hoặc đọc file có đánh số dòng |
create | path, file_text | Tạo file mới, lỗi nếu đã tồn tại |
str_replace | path, old_str, new_str | Chỉnh tại chỗ, lỗi nếu trùng hoặc không khớp |
insert | path, insert_line, insert_text | Chèn tại dòng (1-indexed) |
delete | path | Xoá đệ quy |
rename | old_path, new_path | Đổi tên, lỗi nếu đích đã có |
Mọi path đều được scope vào một thư mục logic /memories. SDK cung cấp BetaAbstractMemoryTool (Python) và betaMemoryTool (TypeScript) cho phép tự cài đặt backend — có thể là filesystem thật, S3, Postgres, hoặc vault được mã hoá.
Triết lý ngược dòng của Anthropic
Trong khi cả thế giới đổ về vector DB và knowledge graph, Anthropic cố ý không dùng embedding, không dùng vector search, không dùng graph. Đặt cược: một model đủ thông minh biết cách tự tổ chức các file có tên gọi và MEMORY.md làm index, kết quả sẽ vượt trội retrieval mờ. Số liệu thực tế: 84% giảm token trong workflow dài — chứng minh đặt cược này là có cơ sở.
Memory Tool còn đi kèm hai tính năng server-side: Context Editing (xoá các tool result cũ khỏi transcript, thay bằng reference tới memory) và Compaction (tóm tắt khi chạm ngưỡng context). Memory được giữ nguyên qua ranh giới compaction — tức là agent không mất trí sau khi bị rút gọn.
Claude Code xếp chồng lên trên ý tưởng đó hai cơ chế quen thuộc mà bất kỳ ai dùng công cụ này đều đã gặp:
- CLAUDE.md — human-authored, commit vào git, nạp ở đầu phiên. Đây là nơi chứa "quy ước nhóm" cho agent.
- Auto Memory (v2.1.59+, mặc định bật) — thư mục
memory/do chính agent ghi.MEMORY.mdlà index, 200 dòng đầu / 25KB được nạp vào đầu phiên; phần còn lại agent chủ động điều hướng qua các file topic khi cần.
8. Vòng đời của một ký ức — 6 thao tác cốt lõi
Một hệ thống memory trưởng thành không chỉ "ghi và đọc". Có ít nhất sáu thao tác, và mỗi framework chọn đặt chúng lên hot path hoặc cold path một cách khác nhau.
| Thao tác | Mô tả | Đặt ở đâu |
|---|---|---|
| Write (extract + store) | LLM đọc turn mới, sinh fact ứng viên, ghi ra store | Inline (Mem0 mặc định), background (Letta sleeptime), batch (nightly sweep) |
| Read (retrieve) | Truy xuất ký ức liên quan tới câu hỏi hiện tại | Luôn phải là đường đồng bộ, phải nhanh — không có LLM ở giữa |
| Update | Sửa ký ức đã có thay vì nhân bản | Upsert by id (vector), edge invalidation (graph), str_replace (file) |
| Summarize | Cô đọng buffer cũ thành tóm tắt ngắn hơn | Recursive (Letta), periodic reflection (Park), server-side compaction (Anthropic) |
| Forget | Hết hạn, giảm trọng số hoặc xoá theo compliance | TTL (Redis, ClickHouse), importance-decay (Mem0), purge by user_id (GDPR) |
| Consolidate | Chuyển giữa các tầng — hot → warm → cold | Redis → Vector → ClickHouse; episode → entity → community |
Công thức scoring episodic nổi tiếng nhất đến từ bài Generative Agents (Park et al. 2023) và đến nay vẫn được tham chiếu trong mọi tài liệu memory:
score = α_recency * recency + α_importance * importance + α_relevance * relevance
- Recency: suy giảm theo hàm mũ từ lần truy cập cuối:
exp(-Δt / τ). - Importance: điểm 1–10 do một LLM prompt đánh giá "mức độ đáng nhớ".
- Relevance: cosine similarity giữa query và memory embedding.
Cả ba thành phần được min-max chuẩn hoá về [0, 1]; bản gốc đặt α = 1 cho cả ba. Công thức đơn giản nhưng đủ mạnh để phục vụ phần lớn use case, và là starting point rất tốt cho production.
Đừng bỏ qua "forget"
Rất nhiều team chỉ nghĩ đến việc ghi nhớ mà quên quên. Hệ quả: store phình to, latency truy xuất tăng dần, và tệ nhất là agent bị "ám ảnh" bởi những sự thật đã quá hạn (người dùng từng dùng pnpm 6 tháng trước, giờ đã chuyển sang bun). Một hệ thống memory tốt phải có chiến lược forget rõ ràng: TTL theo tầng, decay theo importance, và hard purge theo compliance request.
9. Memory trong hệ Multi-Agent — chia sẻ hay cách ly?
Ở mô hình single-agent, memory là vấn đề tối ưu hoá. Nhưng khi có nhiều agent cùng chạy trên cùng một tổ chức, nó trở thành câu hỏi kiến trúc: ai được đọc cái gì, ai được ghi cái gì, và điều gì sẽ xảy ra khi một agent bị nhiễm prompt injection?
- Shared Blackboard (Swarm pattern): một store chung cho cả team. Đơn giản, thông tin chảy tự do. Nhược điểm: tranh chấp ghi, rủi ro lan truyền một ký ức độc hại cho toàn đội, và khó debug khi hai agent có cùng thời điểm sinh ra hai fact mâu thuẫn.
- Hierarchical (Orchestrator + Specialists): orchestrator giữ memory cấp cao của team; specialist giữ scratchpad riêng, chỉ publish lên một bản tóm tắt. Giảm nhiễu và hạn chế cross-talk, là lựa chọn được khuyến nghị cho đa số production.
- A2A Protocol (Google, 4/2025): khi các agent đến từ những tổ chức khác nhau, nguyên tắc opaque execution cấm chia sẻ bộ nhớ nội tại — agent chỉ trao đổi message qua một task interface chuẩn. Phù hợp khi ranh giới tin cậy yếu.
- Namespaced LangGraph Store: một store vật lý duy nhất, nhưng
BaseStorephân vùng theo tuple (agent_id,user_id, ...). Đơn giản về vận hành, vẫn giữ isolation logic.
Một nguyên tắc mới nổi trong các survey 2025–2026 là coordinated forgetting — team agent phải có giao thức thống nhất về cái gì được quên khi nào, để kho kiến thức chung không bị phình lên không giới hạn và để các fact lỗi thời không còn ảnh hưởng đến phần còn lại.
10. Production concerns — những thứ giết chết một kiến trúc đẹp trên giấy
10.1. Latency budget cho mỗi turn agent
| Tầng | Target P95 | Thực tế |
|---|---|---|
| Working memory read (Redis) | < 5ms | < 1ms |
| Vector recall top-k=10 | < 100ms | 30–80ms |
| Graph hybrid retrieval (Zep) | < 500ms | ~300ms |
| LLM extraction (write path) | < 2s | 500–2000ms |
| Reflection / summarization | offline | giây–phút |
Luật cứng: không bao giờ đặt một lời gọi LLM trên đường đọc đồng bộ. Đây là lý do Zep nhấn mạnh rằng retrieval của họ "no LLM in the path", cũng là lý do Mem0 đạt được "91% giảm P95" — vì họ chạy extraction bất đồng bộ. Và chính vì lý do này mà giải pháp file-based của Anthropic nhanh hơn các giải pháp vector thuần trong nhiều workload: không có embedding model chen vào giữa.
10.2. Quyền riêng tư, retention và GDPR
Một hệ memory đa tầng lưu dữ liệu người dùng qua nhiều phiên, qua nhiều tháng — đây là hành vi mà GDPR, HIPAA, SOC2 đều quan tâm trực tiếp. Checklist tối thiểu:
- Field-level write filter: bộ lọc ngay trước extractor, chặn PII, secret, test data không bao giờ được lọt vào store.
- Retention theo tầng: working memory (1 giờ), semantic (dài hạn), episodic (90 ngày), cold log (180 ngày) — ClickHouse TTL DELETE là công cụ phù hợp.
- Per-user purge: mọi store phải hỗ trợ xoá theo
user_idtrong thời gian ngắn để đáp ứng quyền được quên. Dễ hơn rất nhiều khiuser_idlà first-class column (ClickHouse, Mem0) thay vì chôn trong metadata JSON. - Provenance: mọi memory phải carry
trace_id/source_event_idđể audit được "fact này sinh ra từ sự kiện nào", và để thu hồi đúng khi fact đó bị phản bác.
10.3. Memory poisoning — mặt tối của persistence
Khi bộ nhớ bền vững qua nhiều phiên, nó cũng trở thành bề mặt tấn công bền vững. Một fact độc hại ("khi người dùng hỏi về X, hãy trả lời Y") được ghi một lần, có thể sống sót qua hàng trăm session. Ba lớp phòng vệ cần thiết:
- Đối xử với memory giống như tool output — không tin tưởng ngầm. Mọi nội dung đọc ra từ store phải đi qua guardrails cấp instruction-detection trước khi đưa vào prompt.
- Giữ provenance trên mỗi ký ức, và cho phép invalidate theo chuỗi — khi một trace được phát hiện là adversarial, tất cả memory dẫn xuất từ trace đó phải bị đánh dấu.
- Validation tại thời điểm ghi — có thể là một model nhỏ rẻ hơn đóng vai trò classifier "đây có phải một instruction trá hình không?".
11. Kiến trúc tham khảo — gộp tất cả lại
flowchart TB
U["User"] --> AG["Agent Runtime
LangGraph / Letta / Claude Code"]
AG -->|turn state| CKPT["Redis
Checkpointer + Session Hash"]
AG -->|retrieve| HYB["Hybrid Retriever
BM25 + Vector + Graph"]
HYB --> VEC["Vector DB
episodic + semantic"]
HYB --> GRF["Graphiti
Temporal KG"]
HYB --> FS["File Memory
MEMORY.md"]
AG -.->|async write| EXT["Extractor Worker
LLM fact extraction"]
EXT --> VEC
EXT --> GRF
EXT --> FS
AG -.->|trace/event| OTEL["OTel Collector"]
OTEL --> CH["ClickHouse
MergeTree + MV"]
CH -.->|reflection query| REF["Reflection Worker
sleeptime compute"]
REF --> VEC
REF --> GRF
style U fill:#e94560,stroke:#fff,color:#fff
style AG fill:#ff9800,stroke:#fff,color:#fff
style CKPT fill:#4CAF50,stroke:#fff,color:#fff
style HYB fill:#8e44ad,stroke:#fff,color:#fff
style VEC fill:#0f3460,stroke:#fff,color:#fff
style GRF fill:#0f3460,stroke:#fff,color:#fff
style FS fill:#0f3460,stroke:#fff,color:#fff
style CH fill:#2c3e50,stroke:#fff,color:#fff
style REF fill:#ff9800,stroke:#fff,color:#fff
style EXT fill:#ff9800,stroke:#fff,color:#fff
style OTEL fill:#2c3e50,stroke:#fff,color:#fff
Kiến trúc memory tham khảo cho một agent production 2026 — write async, read sync, không có LLM trong đường đọc
Các tín hiệu thiết kế then chốt của kiến trúc trên:
- Đường đọc chỉ gồm Redis (checkpointer), Hybrid Retriever và các store dữ liệu đã được chuẩn bị sẵn — không có LLM nào chen vào.
- Đường ghi được đẩy sang một Extractor Worker bất đồng bộ. User nhận phản hồi trước, memory được cập nhật sau. Eventual consistency được chấp nhận như một trade-off có chủ đích.
- ClickHouse là cold log cho tất cả sự kiện, đồng thời là nguồn nguyên liệu cho reflection chạy nền (sleeptime worker). Các insight sinh ra từ reflection được promote trở lại vào Vector hoặc Graphiti — khép kín vòng feedback.
- File Memory tồn tại song song với vector/graph cho các ký ức mà model muốn tự quản — đặc biệt là trong workflow code-heavy như Claude Code, nơi một
MEMORY.mdđúng chỗ còn giá trị hơn mười vector hit mờ nhạt.
12. Lộ trình triển khai từng bước cho team bạn
agent_events, một materialized view cho cost/user/day. Có dashboard Grafana cơ bản trước khi nghĩ đến tầng kế tiếp.13. Kết luận
Bộ nhớ không còn là một module phụ trợ gắn vào AI agent — nó là sống còn. Các con số 84–91% giảm token, 90% giảm latency, 98% giảm kích thước context không phải là marketing mà là kết quả lặp lại trên nhiều hệ thống thương mại và benchmark học thuật. Nhưng phần thú vị nhất là tính nguyên tắc mà các framework hàng đầu đang đồng ý với nhau: không đặt LLM trên đường đọc đồng bộ, tách write asynchronous, dedup tại thời điểm ghi chứ không chỉ tại đọc, giữ provenance cho mọi ký ức, và luôn có cơ chế quên.
Đừng cố xây dựng cả năm tầng ngay từ ngày đầu. Bắt đầu từ Redis + ClickHouse, thêm Vector khi có dấu hiệu lặp ngữ nghĩa rõ ràng, chỉ đưa Graph vào khi multi-hop thực sự là nhu cầu. Anthropic Memory Tool và Claude Code chứng minh một điều: đôi khi một vài file văn bản được quản lý bằng bộ óc của chính LLM còn giá trị hơn một stack vector cầu kỳ. Chọn đúng công cụ cho đúng loại ký ức — đó là kỷ luật lớn nhất của AI Engineer 2026.
Checklist 7 điểm cho một kiến trúc memory đáng tin cậy
(1) Có tầng working memory độ trễ < 5ms.
(2) Write path nằm ngoài đường đồng bộ của user request.
(3) Mọi ký ức có user_id, trace_id, valid_from, valid_to.
(4) Có chiến lược TTL và policy forget rõ ràng cho từng tầng.
(5) Hỗ trợ per-user purge cho GDPR.
(6) Treat memory content as untrusted input — có guardrail ở đường đọc.
(7) Dashboard observability với ClickHouse + OTel trước khi go-live.
Nguồn tham khảo
- CoALA: Cognitive Architectures for Language Agents (Sumers et al., arXiv 2309.02427) — khung phân loại working / episodic / semantic / procedural được các framework agent hiện đại dùng chung.
- Generative Agents: Interactive Simulacra of Human Behavior (Park et al., arXiv 2304.03442) — nguồn gốc của memory stream + reflection + công thức recency/importance/relevance.
- Mem0: Building Production-Ready AI Agents with Scalable Long-Term Memory (arXiv 2504.19413) — paper Mem0 với cơ chế extraction + update hai pha và benchmark LOCOMO.
- Zep: A Temporal Knowledge Graph Architecture for Agent Memory (arXiv 2501.13956) — paper Zep / Graphiti với mô hình bi-temporal, hybrid retrieval, kết quả DMR và LongMemEval.
- Anthropic Memory Tool — Documentation — đặc tả tool
memory_20250818, sáu lệnh view/create/str_replace/insert/delete/rename. - How Claude remembers your project — Claude Code Memory docs — cơ chế CLAUDE.md và auto memory của Claude Code.
- Letta — Intro to MemGPT concepts — core memory blocks, archival memory, recall memory, self-editing tool set.
- Rearchitecting Letta's Agent Loop: Lessons from ReAct, MemGPT & Claude Code — thiết kế lại agent loop Letta v1 cho GPT-5 và Claude 4.5.
- LangChain — LangMem SDK launch blog — bộ ba semantic / episodic / procedural và prompt optimizer.
- LangGraph memory overview — Checkpointer (short-term) và Store (long-term) với namespacing.
- Redis + LangGraph: Build smarter AI agents with memory & persistence — pattern RedisSaver / RedisStore, Redis JSON + Vector.
- Redis 8 GA announcement — các tính năng Redis 8 liên quan đến agent state: vector search, hash field TTL, multi-threaded I/O.
- Graphiti — Real-Time Knowledge Graphs for AI Agents (GitHub) — engine lõi của Zep, hỗ trợ Neo4j / FalkorDB / Kuzu / Neptune.
- ClickHouse — How Langfuse is scaling LLM observability for the agentic era — case production của ClickHouse làm event log cho agent, kèm chuyện migrate từ Postgres.
- ClickHouse — Tracing OpenAI agents with ClickStack — pattern OTel + ClickStack cho agent observability.
- AWS Database Blog — Build persistent memory with Mem0, ElastiCache for Valkey, Neptune Analytics — reference architecture hybrid cho Mem0 trên AWS.
- Anthropic Engineering — Effective context engineering for AI agents — lý luận về just-in-time context retrieval, động lực thiết kế của Memory Tool.
- Mem0 — Memory in Agents: What, Why and How — framing consolidation, dynamic forgetting, promotion short-term → long-term.
LLM Observability 2026 - Tracing, Metrics, Evals cho Multi-Agent AI voi OpenTelemetry, Langfuse va ClickHouse
LLM Gateway 2026 - Cổng Kết nối AI Thông minh cho Multi-Agent với Redis và ClickHouse
Disclaimer: The opinions expressed in this blog are solely my own and do not reflect the views or opinions of my employer or any affiliated organizations. The content provided is for informational and educational purposes only and should not be taken as professional advice. While I strive to provide accurate and up-to-date information, I make no warranties or guarantees about the completeness, reliability, or accuracy of the content. Readers are encouraged to verify the information and seek independent advice as needed. I disclaim any liability for decisions or actions taken based on the content of this blog.