Tanpa memory, setiap sesi dengan AI Agent dimulai dari nol. User harus mengulangi konteks, preferensi, dan history setiap kali — ini adalah pengalaman yang buruk dan sebenarnya tidak perlu.
Memory architecture yang tepat adalah yang menentukan apakah agent terasa "cerdas" dan "mengenal user" atau seperti chatbot yang pelupa.
Empat Tipe Memory — Analog dengan Memori Manusia
Episodic Memory dengan PostgreSQL
Untuk agent yang perlu "mengingat" riwayat interaksi user, episodic memory di PostgreSQL adalah pendekatan yang paling pragmatis untuk production Indonesia:
-- Schema untuk episodic memory
CREATE TABLE agent_memory (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id UUID NOT NULL,
user_id UUID NOT NULL,
event_type TEXT, -- 'message' | 'tool_call' | 'decision' | 'error'
content TEXT,
metadata JSONB,
embedding vector(1536), -- untuk semantic retrieval
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_memory_user ON agent_memory(user_id, created_at DESC);
CREATE INDEX idx_memory_embedding ON agent_memory USING ivfflat(embedding vector_cosine_ops);
from datetime import datetime, timedelta
class AgentMemoryManager:
def __init__(self, db, embedding_model):
self.db = db
self.embed = embedding_model
def save(self, session_id: str, user_id: str, event_type: str, content: str):
embedding = self.embed.encode(content).tolist()
self.db.execute("""
INSERT INTO agent_memory (session_id, user_id, event_type, content, embedding)
VALUES (%s, %s, %s, %s, %s)
""", [session_id, user_id, event_type, content, embedding])
def retrieve_relevant(self, user_id: str, query: str, k: int = 5) -> list:
query_embedding = self.embed.encode(query).tolist()
# Semantic retrieval dari semua history user
return self.db.fetch_all("""
SELECT content, event_type, created_at,
1 - (embedding <=> %s::vector) AS similarity
FROM agent_memory
WHERE user_id = %s
AND created_at > NOW() - INTERVAL '90 days'
ORDER BY embedding <=> %s::vector
LIMIT %s
""", [query_embedding, user_id, query_embedding, k])
def build_context_from_memory(self, user_id: str, current_query: str) -> str:
# 1. Recent history (last 10 events, temporal)
recent = self.db.fetch_all("""
SELECT content, event_type, created_at FROM agent_memory
WHERE user_id = %s ORDER BY created_at DESC LIMIT 10
""", [user_id])
# 2. Semantically relevant history
relevant = self.retrieve_relevant(user_id, current_query)
# 3. Build context string for injection ke system prompt
context = "RIWAYAT USER:\n"
for r in recent[:5]:
context += f"- [{r['created_at'].strftime('%d %b')}] {r['content']}\n"
context += "\nKONTEKS RELEVAN:\n"
for r in relevant:
if r['similarity'] > 0.75:
context += f"- {r['content']}\n"
return context
Entity Memory — Ingat Tentang Orang dan Hal
Entity memory menyimpan fakta tentang entitas spesifik (user, produk, lokasi) yang secara bertahap diperbarui seiring percakapan:
def extract_and_update_entities(llm, conversation: str, existing_entities: dict) -> dict:
"""Extract entitas dari percakapan dan merge dengan yang sudah ada."""
result = llm.invoke(f"""Extract informasi penting tentang user dari percakapan ini.
Hanya fakta yang eksplisit disebutkan — jangan berasumsi.
Entitas yang sudah diketahui:
{existing_entities}
Percakapan baru:
{conversation}
Update entitas dalam format JSON. Jika ada konflik dengan data lama,
gunakan informasi terbaru. Return HANYA JSON, tidak ada penjelasan.""")
try:
new_entities = json.loads(result.content)
# Merge dengan existing — informasi baru override yang lama
return {**existing_entities, **new_entities}
except:
return existing_entities # fallback ke yang sudah ada
Memory Compression — Jaga Agar Tidak Membengkak
Memory yang baik bukan tentang mengingat segalanya — tapi tentang mengingat hal yang tepat pada waktu yang tepat. Kualitas retrieval lebih penting dari jumlah yang disimpan.
Kesimpulan
Implementasi memory untuk agent production membutuhkan kombinasi: working memory (in-context untuk sesi aktif), episodic memory (PostgreSQL + pgvector untuk riwayat), semantic memory (ChromaDB untuk knowledge base), dan entity memory (JSON di PostgreSQL untuk profil user). Mulai dari episodic memory saja — sudah cukup untuk 80% use case agent.