AI agent đầu tiên tôi đưa vào production quên sạch mọi cuộc hội thoại ngay khi session kết thúc. Người dùng phải giải thích lại preferences, lặp lại context, xác nhận lại các quyết định đã đưa ra tuần trước. Chúng tôi ship tính năng nhanh hơn đối thủ. Nhưng chúng tôi cũng có churn rate cao hơn 40% ở sản phẩm dùng agent. Người dùng không gọi nó là “stateless context management.” Họ gọi nó là “AI của mày vô dụng.”
Đó là 18 tháng trước. Bài toán memory giờ đây là bài toán mà mọi AI team nghiêm túc đều va vào khi đưa vào production. Và ngành này cuối cùng đã có đủ patterns để đưa ra quyết định kiến trúc có nguyên tắc, thay vì duct-tape Redis vào một prompt template.
Đây là những gì tôi học được về agent memory từ kinh nghiệm chạy ở scale.
Cái Bẫy Stateless Mặc Định
Hầu hết LLM đều stateless theo thiết kế. Mỗi API call bắt đầu từ đầu. Context window là toàn bộ thế giới của agent — không có hôm qua, không có tuần trước, không có “bạn có nhớ khi bạn nói với tôi…” Điều này ổn cho demo. Nó thất bại với sản phẩm thực.
Ba failure mode tôi thấy ở mọi team khi lần đầu làm agent:
Amnesia Loop: Người dùng mất 10 phút giải thích context cho agent. Session hết hạn. Người dùng quay lại và bắt đầu từ đầu. Sau lần thứ ba, họ ngừng dùng agent. Bạn đã xây một sản phẩm phạt power users.
Repetition Tax: Không có memory, mọi request phải mang theo toàn bộ lịch sử liên quan trong prompt. Với 1,000 daily active users thực hiện 5 tương tác mỗi ngày với 3,000 tokens context mỗi lần, bạn đốt ~15M tokens/ngày cho thông tin agent đã xử lý hôm qua. Ở $3/triệu token, đó là $45/ngày lãng phí thuần túy và tăng dần theo thời gian.
Personalization Ceiling: Agent xử lý mọi người dùng như nhau vì nó không biết gì về họ. Bạn không thể xây behavior adaptation, preference learning, hay tính năng proactive. Bạn bị kẹt ở chat interface trong khi cần một người cộng tác.
Memory không phải nice-to-have. Đó là architectural primitive phân biệt agent với chatbot.
Bốn Tầng Memory
Kiến trúc agent memory năm 2026 theo phân cấp mượn từ hệ điều hành. Hiểu tầng nào dùng cho thông tin nào là kỹ năng cốt lõi.
Tầng 1: In-Context Memory (Working Memory)
Đây là context window — RAM của agent. Nhanh, đắt, tạm thời. Tất cả những gì agent cần cho task hiện tại nằm ở đây.
Thuộc về đây: cuộc hội thoại hiện tại, trạng thái task đang chạy, các fact được retrieve từ store dài hạn, bước reasoning trung gian, kết quả tool call.
KHÔNG thuộc về đây: lịch sử người dùng nhiều tháng trước, toàn bộ nội dung knowledge base, các sự kiện hệ thống tĩnh. Dump tất cả mọi thứ vào context window là cách làm amateur. Nó thổi phồng token cost, đụng context limit ở task phức tạp, và làm giảm chất lượng reasoning khi model cố gắng attend quá nhiều thứ cùng lúc.
Giới hạn thực tế tôi dùng: giữ in-context memory dưới 20% context window của model cho các operation thông thường. Để dư headroom cho retrieved chunks và tool outputs.
Tầng 2: Episodic Memory (Recent History Store)
Episodic memory lưu những gì đã xảy ra gần đây — 30 ngày tương tác vừa qua, quyết định đã đưa ra, task đã hoàn thành, preferences đã thể hiện. Nó có thể query, không phải luôn luôn inject.
Pattern implementation hoạt động trong production: lưu episodes dưới dạng structured JSON với summary, timestamp, session ID, và embedding vector. Mỗi session mới, retrieve 5-10 episodes có liên quan nhất qua vector search và inject chúng dưới dạng “memory briefing” nén gọn ở đầu system prompt.
interface Episode {
id: string;
sessionId: string;
timestamp: Date;
summary: string; // LLM-generated, 2-3 câu
keyFacts: string[]; // Structured facts được extract
embedding: number[]; // Dùng cho semantic retrieval
userId: string;
}
async function buildMemoryBriefing(userId: string, currentQuery: string): Promise<string> {
const queryEmbedding = await embed(currentQuery);
const relevantEpisodes = await vectorStore.query({
embedding: queryEmbedding,
filter: { userId },
topK: 5,
minSimilarity: 0.75
});
if (relevantEpisodes.length === 0) return '';
return `## Context liên quan từ các session trước:\n${
relevantEpisodes.map(e =>
`- [${formatDate(e.timestamp)}] ${e.summary}`
).join('\n')
}`;
}
Quyết định thiết kế quan trọng: episodes được tạo ra bởi agent, không phải raw conversation logs. Agent tự tóm tắt mỗi session trước khi kết thúc. Chi phí một ít tokens nhưng đem lại lợi ích lớn bằng cách làm retrieval high-signal thay vì nhiễu.
Tầng 3: Semantic Memory (Knowledge Store)
Semantic memory là những gì agent biết — domain knowledge, fact cụ thể của người dùng, context tổ chức. Đây là RAG layer của bạn, nhưng được scope theo từng agent và từng user thay vì global knowledge base.
Sai lầm kiến trúc tôi thấy nhiều nhất: team xây một global knowledge base và retrieve từ đó cho tất cả user. Điều này hoạt động với Q&A bot. Nó thất bại với agent cần tích lũy user-specific knowledge theo thời gian.
Pattern scale được: phân vùng vector store theo user ID và knowledge type. Lưu explicit user preferences riêng biệt với derived insights.
// Ba phân vùng: global, user-specific, và derived
const globalKnowledge = await vectorStore.query({
collection: 'global',
embedding: queryEmbedding,
topK: 3
});
const userKnowledge = await vectorStore.query({
collection: `user_${userId}`,
embedding: queryEmbedding,
topK: 5
});
const userPreferences = await kvStore.get(`prefs:${userId}`);
// Preferences luôn được inject — không có retrieval uncertainty
Với user-specific knowledge, tôi luôn inject preferences (nhỏ, high-signal, luôn liên quan) và retrieve episodic và semantic memory có chọn lọc. Việc tách biệt này ngăn vấn đề “over-injection” khi retrieval bơm generic knowledge vào context cần user-specific facts cụ thể.
Tầng 4: Procedural Memory (Long-Term Behavior Adaptation)
Đây là tầng khó nhất để làm đúng và là tầng mà hầu hết team bỏ qua hoàn toàn. Procedural memory là cách behavior của agent thích nghi với từng user hoặc context theo thời gian — learned preferences, điều chỉnh communication style, tối ưu hóa workflow.
Cách tiếp cận đơn giản nhất khả thi trong production: sau mỗi N tương tác (tôi dùng 20), chạy một offline job phân tích feedback signals của user và tạo ra “behavior profile” update lưu dưới dạng structured JSON.
interface BehaviorProfile {
userId: string;
communicationStyle: 'concise' | 'detailed' | 'technical';
preferredFormats: ('code' | 'bullet-points' | 'prose')[];
domainExpertise: Record<string, 'novice' | 'intermediate' | 'expert'>;
workflowPatterns: string[]; // Recurring tasks được quan sát
lastUpdated: Date;
}
Behavior profile trở thành fixture cố định ở đầu system prompt, inject mỗi lần gọi. Nó nhỏ (dưới 500 tokens), luôn liên quan, và cải thiện đáng kể task alignment mà không cần người dùng tự giải thích lại.
Kiến Trúc Production
Kết hợp bốn tầng lại:
User Request
│
▼
Context Assembly Layer
├── Behavior Profile (luôn inject, <500 tokens)
├── Memory Briefing (retrieve top-k episodes, ~800 tokens)
├── Relevant Knowledge (retrieve, ~1200 tokens)
└── Current Conversation (sliding window, ~2000 tokens)
│
▼
LLM Inference (~4500 tokens in-context)
│
▼
Post-Response Processing (async)
├── Extract key facts → cập nhật semantic memory
├── Cập nhật episode store với session summary
└── Tăng feedback signals → behavior profile job queue
Async post-processing là quan trọng. Đừng bắt user chờ memory writes. Xử lý chúng trong background sau khi trả response. User trải nghiệm agent nhanh hơn; memory store cập nhật trong vòng vài giây.
Failure Mode Trong Production
Memory Poisoning: Agent lưu facts sai hoặc đã lỗi thời. Giảm thiểu: thêm confidence scores vào facts đã lưu và implement TTLs. Facts có confidence thấp hết hạn sau 7 ngày; facts high-confidence tồn tại lâu hơn nhưng được đánh dấu để review nếu bị mâu thuẫn.
Context Overflow ở Task Phức Tạp: Tasks dài tích lũy quá nhiều in-context state và đụng token limits. Giảm thiểu: implement bước “context compression” mỗi N agent turns, tóm tắt intermediate state thành biểu diễn gọn gàng trước khi tiếp tục.
Retrieval Hallucination: Vector search trả về episodes có vẻ đúng nhưng sai, đánh lừa agent. Giảm thiểu: đưa timestamp gốc vào memories được inject. Agent khá giỏi trong việc lý luận về khoảng cách thời gian khi được cho ngày tháng rõ ràng.
Cold Start: User mới không có memory. Agent nên phát hiện trạng thái cold-start và hỏi một vài câu onboarding có mục tiêu để bootstrap behavior profile thay vì đoán mò.
Chi Phí Thực Tế Của Kiến Trúc Này
Cho một production agent phục vụ 1,000 daily active users với 5 tương tác mỗi ngày:
| Thành phần | Chi phí hàng tháng (ước tính) |
|---|---|
| Vector store (Pinecone/Weaviate) | $50-150 |
| KV store cho profiles | $10-30 |
| Memory injection overhead (+2500 tokens/call) | ~$37 ở $3/triệu tokens |
| Episode generation (1 call/session) | ~$8 |
| Tổng overhead memory | ~$100-225/tháng |
So với infrastructure cơ bản ~$450/tháng cho cùng workload không có memory, overhead là 22-50% — nhưng product capability bạn unlock (personalization, continuity, behavior adaptation) chính là thứ biện hộ cho đầu tư vào agent ngay từ đầu. Không có memory, bạn có một search box nhanh hơn, không phải agent.
Điều Một Mà Các Team Làm Sai
Họ xây memory như một tính năng sẽ thêm sau. Memory cần phải có trong kiến trúc từ ngày đầu tiên vì retrofit nó có nghĩa là viết lại prompt assembly layer, thêm async post-processing infrastructure, chọn vector store, và định nghĩa “fact nào đáng nhớ” — tất cả những quyết định lan rộng khắp hệ thống.
Nếu bạn bắt đầu một dự án agent mới hôm nay, hãy bắt đầu bằng memory schema trước khi viết dòng prompt đầu tiên. Quyết định agent nên nhớ gì, nhớ bao lâu, và điều gì khiến nó quên. Những quyết định đó sẽ định hình mọi thứ còn lại.
Các open-source frameworks đã làm đúng production memory: Letta (formerly MemGPT) với approach OS-inspired phân tầng, LangGraph cho checkpointed state management, và Mem0 cho managed agent memory với minimal infrastructure overhead. Nếu bạn xây từ đầu, nghiên cứu cả ba trước khi viết một dòng code.