agentic-memory-architect · diff
v4.2.0 to v4.2.0
769 added, 22 removed. Audit A to A.
---
name: agentic-memory-architect
- description: Expert guide for long-term episodic memory integration (Mem0, Letta/MemGPT, Zep) and unified context management for autonomous AI agents / Panduan ahli untuk integrasi memori episodik jangka panjang dan manajemen konteks agen AI otonom.
- version: "4.2.0"
+ description: Expert guide for long-term episodic memory integration (Mem0 v2, Letta/MemGPT, Zep v2), memory tier architecture, pgvector HNSW storage, and unified context management for autonomous AI agents / Panduan ahli untuk integrasi memori episodik jangka panjang (Mem0 v2, Letta/MemGPT, Zep v2), arsitektur tier memori, penyimpanan pgvector HNSW, dan manajemen konteks terpadu untuk agen AI otonom.
author: "Roedy Rustam"
+ version: "4.2.0"
---
# Agentic Memory Architect & Episodic Memory Guide
[English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
---
<a name="english"></a>
## English
### Orchestration & Integration
- Connects and orchestrates with `multi-agent-orchestration`, `pydantic-ai-expert`, `session-memory-manager`, and `zero-to-prod-orchestrator`.
+ Connects and orchestrates with:
+ - `multi-agent-orchestration` — shared memory state across agent swarms
+ - `pydantic-ai-expert` — type-safe memory injection into Pydantic AI agents
+ - `session-memory-manager` — short-term session checkpoint layer
+ - `vector-db-rag-expert` — pgvector/HNSW for long-term episodic retrieval
+ - `database-orm-expert` — Prisma/Drizzle schema for memory persistence
+ - `ai-llm-integration-expert` — context window injection at inference time
+ - `zero-to-prod-orchestrator` — memory layer provisioned in Phase 2 (Foundation)
+
+ ---
+
### Purpose
- To design and implement persistent, long-term episodic memory systems for autonomous AI agents, moving beyond simple context windows or localized session checkpoints.
- ### Key Technologies
- - **Mem0**: For cross-session entity memory and user preference persistence.
- - **Letta (formerly MemGPT)**: For unbounded memory management allowing LLMs to page memory in and out.
- - **Zep (v2)**: Fast, scalable memory service for AI applications, including temporal memory.
+ Design and implement persistent, multi-tier memory systems for autonomous AI agents that transcend simple context windows. Enable agents to **remember users across sessions**, recall past decisions, maintain knowledge graphs, and operate with human-like episodic continuity — all while remaining within token budget constraints.
- ### Architectural Guidelines
- 1. **Memory Tiers**: Segregate memory into short-term (working context), mid-term (session graph), and long-term (vector-backed episodic memory).
- 2. **Context Paging**: Implement mechanisms for agents to proactively recall and summarize past interactions without overwhelming the token budget.
- 3. **User Knowledge Graphs**: Continually update the graph of user preferences, project constraints, and architectural decisions over time.
+ ---
+ ### Memory Tier Architecture
+
+ ```
+ ┌─────────────────────────────────────────────────────────────────┐
+ │ AGENT MEMORY HIERARCHY │
+ ├─────────────────────────────────────────────────────────────────┤
+ │ TIER 0 │ In-Context Working Memory (current conversation) │
+ │ │ ≤ 128K tokens │ Lost on session end │
+ │ │ Implementation: Raw messages array in LLM call │
+ ├─────────────────────────────────────────────────────────────────┤
+ │ TIER 1 │ Session Memory (within-session graph) │
+ │ │ Hours to days │ Redis / Zep session store │
+ │ │ Implementation: Zep v2 session + entity graph │
+ ├─────────────────────────────────────────────────────────────────┤
+ │ TIER 2 │ Episodic Memory (cross-session, user-scoped) │
+ │ │ Weeks to months │ Mem0 + pgvector HNSW │
+ │ │ Implementation: Mem0 Memory.add() / Memory.search() │
+ ├─────────────────────────────────────────────────────────────────┤
+ │ TIER 3 │ Semantic / Procedural Memory (agent knowledge base) │
+ │ │ Permanent │ pgvector + structured KB tables │
+ │ │ Implementation: RAG pipeline over domain knowledge │
+ └─────────────────────────────────────────────────────────────────┘
+ ```
+
+ ```mermaid
+ flowchart TD
+ IN["User Input"] --> T0["Tier 0: In-Context\n(current messages)"]
+ T0 --> AGENT["Agent LLM Call"]
+ AGENT --> OUT["Response"]
+ AGENT <-->|"recall + store"| T1["Tier 1: Zep Session\n(entity + temporal graph)"]
+ AGENT <-->|"recall + store"| T2["Tier 2: Mem0 Episodic\n(cross-session user memories)"]
+ AGENT <-->|"retrieve only"| T3["Tier 3: pgvector RAG\n(domain knowledge base)"]
+ T1 -->|"promotes key facts"| T2
+ T2 -->|"populates embeddings"| T3
+ ```
+
---
+ ### 1. Mem0 v2 — Cross-Session Episodic Memory
+
+ Mem0 provides a managed memory layer that extracts and stores entities, preferences, and facts from conversations, making them searchable across sessions.
+
+ ```bash
+ pip install mem0ai
+ # OR for self-hosted:
+ pip install mem0ai[oss]
+ ```
+
+ #### Python: Full CRUD Memory Operations
+
+ ```python
+ import os
+ from mem0 import Memory
+
+ # Initialize with custom vector store (pgvector)
+ config = {
+ "vector_store": {
+ "provider": "pgvector",
+ "config": {
+ "dbname": "mem0_db",
+ "collection_name": "agent_memories",
+ "embedding_model_dims": 1536,
+ "host": os.environ["PGVECTOR_HOST"],
+ "port": 5432,
+ "user": os.environ["PGVECTOR_USER"],
+ "password": os.environ["PGVECTOR_PASSWORD"],
+ },
+ },
+ "llm": {
+ "provider": "anthropic",
+ "config": {
+ "model": "claude-sonnet-4-5",
+ "api_key": os.environ["ANTHROPIC_API_KEY"],
+ },
+ },
+ "embedder": {
+ "provider": "openai",
+ "config": {
+ "model": "text-embedding-3-small",
+ "api_key": os.environ["OPENAI_API_KEY"],
+ },
+ },
+ }
+
+ memory = Memory.from_config(config)
+
+ # ADD: Store memories from a conversation turn
+ def add_conversation_memory(user_id: str, messages: list[dict]) -> list[dict]:
+ """
+ Extract and store memories from a conversation.
+ Mem0 automatically identifies entities, preferences, and facts.
+ Returns list of memory entries created.
+ """
+ result = memory.add(
+ messages=messages,
+ user_id=user_id,
+ metadata={"source": "conversation", "app": "my-agent"},
+ )
+ return result # [{"id": "uuid", "memory": "User prefers TypeScript over Python", ...}]
+
+
+ # SEARCH: Retrieve relevant memories for the current query
+ def recall_memories(user_id: str, query: str, top_k: int = 5) -> list[dict]:
+ """
+ Vector-similarity search over user's episodic memories.
+ Returns ranked list of relevant memories.
+ """
+ results = memory.search(
+ query=query,
+ user_id=user_id,
+ limit=top_k,
+ )
+ return results # [{"id": "...", "memory": "...", "score": 0.92, ...}]
+
+
+ # GET ALL: List all memories for a user
+ def get_all_memories(user_id: str) -> list[dict]:
+ return memory.get_all(user_id=user_id)
+
+
+ # UPDATE: Correct or expand an existing memory
+ def update_memory(memory_id: str, new_data: str) -> dict:
+ return memory.update(memory_id=memory_id, data=new_data)
+
+
+ # DELETE: Remove a specific memory
+ def delete_memory(memory_id: str) -> None:
+ memory.delete(memory_id=memory_id)
+
+
+ # RESET: Clear all memories for a user (use with caution)
+ def reset_user_memories(user_id: str) -> None:
+ memory.delete_all(user_id=user_id)
+
+
+ # --- AGENT LOOP INTEGRATION ---
+ async def agent_with_memory(user_id: str, user_input: str) -> str:
+ import anthropic
+
+ # 1. Recall relevant past memories
+ memories = recall_memories(user_id, user_input, top_k=5)
+ memory_context = "\n".join(
+ f"- {m['memory']}" for m in memories if m.get("score", 0) > 0.7
+ )
+
+ system_prompt = f"""You are a helpful AI assistant.
+ You have the following relevant memories about this user:
+ {memory_context if memory_context else "No prior memories found."}
+ Use these memories to personalize your response."""
+
+ client = anthropic.Anthropic()
+ response = client.messages.create(
+ model="claude-sonnet-4-5",
+ max_tokens=2048,
+ system=system_prompt,
+ messages=[{"role": "user", "content": user_input}],
+ )
+ assistant_reply = response.content[0].text
+
+ # 2. Store this turn in Mem0 for future sessions
+ add_conversation_memory(
+ user_id,
+ [
+ {"role": "user", "content": user_input},
+ {"role": "assistant", "content": assistant_reply},
+ ],
+ )
+
+ return assistant_reply
+ ```
+
+ #### TypeScript: Mem0 Client
+
+ ```typescript
+ import MemoryClient from "mem0ai";
+
+ const mem0 = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
+
+ export interface Memory {
+ id: string;
+ memory: string;
+ score?: number;
+ created_at: string;
+ updated_at: string;
+ }
+
+ export async function addMemory(
+ userId: string,
+ messages: Array<{ role: "user" | "assistant"; content: string }>,
+ ): Promise<Memory[]> {
+ const result = await mem0.add(messages, { user_id: userId });
+ return result as Memory[];
+ }
+
+ export async function searchMemory(
+ userId: string,
+ query: string,
+ limit = 5,
+ ): Promise<Memory[]> {
+ const results = await mem0.search(query, { user_id: userId, limit });
+ return results as Memory[];
+ }
+
+ export async function deleteMemory(memoryId: string): Promise<void> {
+ await mem0.delete(memoryId);
+ }
+
+ export async function getAllMemories(userId: string): Promise<Memory[]> {
+ const result = await mem0.getAll({ user_id: userId });
+ return result as Memory[];
+ }
+ ```
+
+ ---
+
+ ### 2. Letta (MemGPT) — Unbounded In-Context Memory Management
+
+ Letta enables LLMs to manage their own memory by providing explicit memory blocks (`core_memory`, `archival_memory`) that the model can read/write through tool calls, effectively giving LLMs unlimited memory.
+
+ ```bash
+ pip install letta-client
+ letta server start # starts local Letta server on :8283
+ ```
+
+ #### Python: Persisted Agent with Custom Memory
+
+ ```python
+ from letta_client import Letta
+
+ client = Letta(base_url="http://localhost:8283")
+
+ # Create a persisted agent with custom memory blocks
+ agent = client.agents.create(
+ name="research-assistant",
+ model="anthropic/claude-sonnet-4-5",
+ embedding="openai/text-embedding-3-small",
+ memory_blocks=[
+ {
+ "label": "human",
+ "value": "Name: Unknown\nPreferences: Unknown\nProjects: None yet.",
+ "limit": 2000,
+ },
+ {
+ "label": "persona",
+ "value": (
+ "I am a research assistant with persistent memory. "
+ "I remember user preferences, past discussions, and project context "
+ "across all sessions."
+ ),
+ "limit": 2000,
+ },
+ ],
+ tools=["core_memory_append", "core_memory_replace", "archival_memory_insert",
+ "archival_memory_search"],
+ )
+
+ print(f"Agent ID: {agent.id}") # Save this for future sessions
+
+
+ def chat_with_persisted_agent(agent_id: str, message: str) -> str:
+ """Send a message to a persisted Letta agent and get a response."""
+ resp = client.agents.messages.create(
+ agent_id=agent_id,
+ messages=[{"role": "user", "content": message}],
+ )
+ # Extract the assistant text from the response
+ for msg in resp.messages:
+ if msg.message_type == "assistant_message":
+ return msg.content
+ return ""
+
+
+ def get_agent_memory(agent_id: str) -> dict:
+ """Inspect current in-context memory blocks of the agent."""
+ memory = client.agents.core_memory.retrieve(agent_id=agent_id)
+ return {block.label: block.value for block in memory.memory.values()}
+
+
+ def search_archival_memory(agent_id: str, query: str) -> list[str]:
+ """Search the agent's long-term archival memory store."""
+ results = client.agents.archival_memory.list(agent_id=agent_id, query=query)
+ return [r.text for r in results.archival_memory]
+ ```
+
+ ---
+
+ ### 3. Zep v2 — Temporal Memory & User Knowledge Graph
+
+ Zep provides a fast memory service with temporal awareness, entity extraction, and user knowledge graph construction. It handles the Tier 1 (session) and bridges to Tier 2 (episodic).
+
+ ```bash
+ pip install zep-cloud
+ # OR self-hosted:
+ docker run -p 8000:8000 ghcr.io/getzep/zep:latest
+ ```
+
+ #### Python: Zep Session + Graph Memory
+
+ ```python
+ import os
+ from zep_cloud.client import AsyncZep
+ from zep_cloud.types import Message, RoleType
+
+ zep = AsyncZep(api_key=os.environ["ZEP_API_KEY"])
+
+
+ async def ensure_user_and_session(user_id: str, session_id: str) -> None:
+ """Idempotently create user and session in Zep."""
+ try:
+ await zep.user.add(user_id=user_id)
+ except Exception:
+ pass # User already exists
+
+ try:
+ await zep.memory.add_session(
+ session_id=session_id,
+ user_id=user_id,
+ metadata={"app": "my-agent", "version": "1.0"},
+ )
+ except Exception:
+ pass # Session already exists
+
+
+ async def store_turn(
+ session_id: str,
+ user_message: str,
+ assistant_message: str,
+ ) -> None:
+ """Persist a conversation turn to Zep for memory extraction."""
+ await zep.memory.add(
+ session_id=session_id,
+ messages=[
+ Message(role_type=RoleType.UserRole, role="user", content=user_message),
+ Message(role_type=RoleType.AssistantRole, role="assistant", content=assistant_message),
+ ],
+ )
+
+
+ async def recall_session_context(session_id: str) -> str:
+ """Retrieve Zep's synthesized memory summary + relevant facts."""
+ memory = await zep.memory.get(session_id=session_id)
+ parts = []
+ if memory.summary and memory.summary.content:
+ parts.append(f"Session Summary:\n{memory.summary.content}")
+ if memory.facts:
+ facts_text = "\n".join(f"- {fact}" for fact in memory.facts[:10])
+ parts.append(f"Key Facts:\n{facts_text}")
+ return "\n\n".join(parts)
+
+
+ async def search_user_graph(user_id: str, query: str) -> list[dict]:
+ """
+ Search the user's temporal knowledge graph for entities and relations.
+ Returns enriched context about what Zep knows about this user.
+ """
+ results = await zep.graph.search(
+ user_id=user_id,
+ query=query,
+ scope="edges", # 'nodes' | 'edges' — edges capture relations
+ limit=10,
+ reranker="rrf", # Reciprocal Rank Fusion for hybrid search
+ )
+ return [
+ {
+ "source": edge.source_node_name,
+ "relation": edge.relation,
+ "target": edge.target_node_name,
+ "fact": edge.fact,
+ "created_at": edge.created_at.isoformat() if edge.created_at else None,
+ }
+ for edge in (results.edges or [])
+ ]
+
+
+ async def add_structured_data_to_graph(user_id: str, data: str, data_type: str = "text") -> None:
+ """
+ Inject structured information (e.g., user profile JSON) into Zep's graph.
+ Zep will extract entities and relations automatically.
+ """
+ await zep.graph.add(user_id=user_id, data=data, type=data_type)
+ ```
+
+ ---
+
+ ### 4. pgvector + HNSW — Long-Term Episodic Storage
+
+ For Tier 2/3 storage, use PostgreSQL with pgvector and HNSW indexes for sub-millisecond similarity search over millions of memory embeddings.
+
+ #### SQL Schema
+
+ ```sql
+ -- Enable pgvector extension
+ CREATE EXTENSION IF NOT EXISTS vector;
+
+ -- Episodic memory table
+ CREATE TABLE agent_memories (
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
+ user_id TEXT NOT NULL,
+ agent_id TEXT,
+ content TEXT NOT NULL,
+ embedding VECTOR(1536) NOT NULL, -- OpenAI text-embedding-3-small
+ tier SMALLINT NOT NULL DEFAULT 2, -- 1=session, 2=episodic, 3=semantic
+ source TEXT NOT NULL DEFAULT 'conversation',
+ metadata JSONB NOT NULL DEFAULT '{}',
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
+ expires_at TIMESTAMPTZ -- NULL = permanent
+ );
+
+ -- HNSW index for cosine similarity (outperforms IVFFlat at recall@10)
+ CREATE INDEX idx_memories_embedding_hnsw ON agent_memories
+ USING hnsw (embedding vector_cosine_ops)
+ WITH (m = 16, ef_construction = 64);
+
+ -- B-tree for user-scoped filtering
+ CREATE INDEX idx_memories_user_id ON agent_memories (user_id);
+
+ -- Composite for time-scoped recall
+ CREATE INDEX idx_memories_user_created ON agent_memories (user_id, created_at DESC);
+ ```
+
+ #### TypeScript: pgvector Memory Repository
+
+ ```typescript
+ import { Pool } from "pg";
+ import OpenAI from "openai";
+
+ const pool = new Pool({ connectionString: process.env.DATABASE_URL });
+ const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
+
+ export interface EpisodicMemory {
+ id: string;
+ userId: string;
+ content: string;
+ metadata: Record<string, unknown>;
+ createdAt: Date;
+ similarity?: number;
+ }
+
+ async function embed(text: string): Promise<number[]> {
+ const resp = await openai.embeddings.create({
+ model: "text-embedding-3-small",
+ input: text,
+ });
+ return resp.data[0].embedding;
+ }
+
+ export async function storeMemory(
+ userId: string,
+ content: string,
+ metadata: Record<string, unknown> = {},
+ tier: 1 | 2 | 3 = 2,
+ ): Promise<string> {
+ const embedding = await embed(content);
+ const vectorLiteral = `[${embedding.join(",")}]`;
+
+ const result = await pool.query<{ id: string }>(
+ `INSERT INTO agent_memories (user_id, content, embedding, tier, metadata)
+ VALUES ($1, $2, $3::vector, $4, $5)
+ RETURNING id`,
+ [userId, content, vectorLiteral, tier, JSON.stringify(metadata)],
+ );
+
+ return result.rows[0].id;
+ }
+
+ export async function recallMemories(
+ userId: string,
+ query: string,
+ topK = 5,
+ minSimilarity = 0.70,
+ ): Promise<EpisodicMemory[]> {
+ const embedding = await embed(query);
+ const vectorLiteral = `[${embedding.join(",")}]`;
+
+ const result = await pool.query<EpisodicMemory & { similarity: number }>(
+ `SELECT
+ id,
+ user_id AS "userId",
+ content,
+ metadata,
+ created_at AS "createdAt",
+ 1 - (embedding <=> $1::vector) AS similarity
+ FROM agent_memories
+ WHERE user_id = $2
+ AND (expires_at IS NULL OR expires_at > NOW())
+ AND 1 - (embedding <=> $1::vector) >= $3
+ ORDER BY embedding <=> $1::vector
+ LIMIT $4`,
+ [vectorLiteral, userId, minSimilarity, topK],
+ );
+
+ return result.rows;
+ }
+
+ export async function deleteExpiredMemories(): Promise<number> {
+ const result = await pool.query(
+ `DELETE FROM agent_memories WHERE expires_at IS NOT NULL AND expires_at <= NOW()`,
+ );
+ return result.rowCount ?? 0;
+ }
+ ```
+
+ ---
+
+ ### 5. Memory Injection Template — RAG Pipeline Integration
+
+ ```typescript
+ import { recallMemories } from "./memory-repository";
+ import { searchMemory } from "./mem0-client";
+
+ export async function buildMemoryAugmentedPrompt(
+ userId: string,
+ userInput: string,
+ systemBase: string,
+ ): Promise<{ system: string; injectedMemoryCount: number }> {
+ // Parallel recall from Tier 2 (pgvector) and Mem0
+ const [pgMemories, mem0Memories] = await Promise.all([
+ recallMemories(userId, userInput, 5, 0.72),
+ searchMemory(userId, userInput, 5),
+ ]);
+
+ const allMemories = [
+ ...pgMemories.map((m) => ({ content: m.content, score: m.similarity ?? 0, source: "episodic" })),
+ ...mem0Memories
+ .filter((m) => (m.score ?? 0) > 0.7)
+ .map((m) => ({ content: m.memory, score: m.score ?? 0, source: "mem0" })),
+ ]
+ .sort((a, b) => b.score - a.score)
+ .slice(0, 8); // Top 8 memories across both sources
+
+ const memoryBlock =
+ allMemories.length > 0
+ ? `\n\n## Relevant Memories About This User\n${allMemories
+ .map((m) => `- [${m.source}] ${m.content}`)
+ .join("\n")}`
+ : "";
+
+ return {
+ system: `${systemBase}${memoryBlock}`,
+ injectedMemoryCount: allMemories.length,
+ };
+ }
+ ```
+
+ ---
+
+ ### 6. Memory CRUD — Full TypeScript Interface
+
+ ```typescript
+ // memory-manager.ts — unified interface over Mem0 + pgvector
+ import { addMemory, searchMemory, getAllMemories, deleteMemory } from "./mem0-client";
+ import { storeMemory, recallMemories } from "./memory-repository";
+
+ export type MemoryBackend = "mem0" | "pgvector" | "both";
+
+ export async function createMemory(
+ userId: string,
+ content: string,
+ backend: MemoryBackend = "both",
+ metadata: Record<string, unknown> = {},
+ ): Promise<{ mem0Ids?: string[]; pgvectorId?: string }> {
+ const results: { mem0Ids?: string[]; pgvectorId?: string } = {};
+
+ if (backend === "mem0" || backend === "both") {
+ const mem0Result = await addMemory(userId, [
+ { role: "user", content: `Remember this: ${content}` },
+ ]);
+ results.mem0Ids = mem0Result.map((m) => m.id);
+ }
+
+ if (backend === "pgvector" || backend === "both") {
+ results.pgvectorId = await storeMemory(userId, content, metadata);
+ }
+
+ return results;
+ }
+
+ export async function queryMemory(
+ userId: string,
+ query: string,
+ backend: MemoryBackend = "both",
+ ): Promise<Array<{ content: string; score: number; source: string }>> {
+ const results: Array<{ content: string; score: number; source: string }> = [];
+
+ if (backend === "mem0" || backend === "both") {
+ const mem0Results = await searchMemory(userId, query, 5);
+ results.push(
+ ...mem0Results.map((m) => ({
+ content: m.memory,
+ score: m.score ?? 0.5,
+ source: "mem0",
+ })),
+ );
+ }
+
+ if (backend === "pgvector" || backend === "both") {
+ const pgResults = await recallMemories(userId, query, 5);
+ results.push(
+ ...pgResults.map((m) => ({
+ content: m.content,
+ score: m.similarity ?? 0.5,
+ source: "pgvector",
+ })),
+ );
+ }
+
+ return results.sort((a, b) => b.score - a.score).slice(0, 10);
+ }
+
+ export async function purgeUserMemory(
+ userId: string,
+ backend: MemoryBackend = "both",
+ ): Promise<void> {
+ const { Pool } = await import("pg");
+ const pool = new Pool({ connectionString: process.env.DATABASE_URL });
+
+ const tasks: Promise<void>[] = [];
+
+ if (backend === "mem0" || backend === "both") {
+ const { default: MemoryClient } = await import("mem0ai");
+ const mem0 = new MemoryClient({ apiKey: process.env.MEM0_API_KEY! });
+ tasks.push(mem0.deleteAll({ user_id: userId }).then(() => undefined));
+ }
+
+ if (backend === "pgvector" || backend === "both") {
+ tasks.push(
+ pool
+ .query("DELETE FROM agent_memories WHERE user_id = $1", [userId])
+ .then(() => undefined),
+ );
+ }
+
+ await Promise.all(tasks);
+ }
+ ```
+
+ ---
+
<a name="bahasa-indonesia"></a>
## Bahasa Indonesia
### Integrasi Orkestrasi
- Terhubung dan mengorkestrasi bersama `multi-agent-orchestration`, `pydantic-ai-expert`, `session-memory-manager`, dan `zero-to-prod-orchestrator`.
+ Terhubung dan mengorkestrasi bersama:
+ - `multi-agent-orchestration` — state memori bersama di seluruh agent swarm
+ - `pydantic-ai-expert` — injeksi memori type-safe ke agen Pydantic AI
+ - `session-memory-manager` — lapisan checkpoint sesi jangka pendek
+ - `vector-db-rag-expert` — pgvector/HNSW untuk retrieval episodik jangka panjang
+ - `database-orm-expert` — skema Prisma/Drizzle untuk persistensi memori
+ - `ai-llm-integration-expert` — injeksi context window saat inferensi
+ - `zero-to-prod-orchestrator` — lapisan memori diprovisioning di Phase 2 (Foundation)
+
+ ---
+
### Tujuan
- Merancang dan mengimplementasikan sistem memori episodik jangka panjang yang persisten untuk agen AI otonom, bergerak melampaui jendela konteks sederhana atau checkpoint sesi lokal.
- ### Teknologi Utama
- - **Mem0**: Untuk memori entitas lintas-sesi dan persistensi preferensi pengguna.
- - **Letta (sebelumnya MemGPT)**: Untuk manajemen memori tak terbatas yang memungkinkan LLM mengambil/menyimpan memori.
- - **Zep (v2)**: Layanan memori cepat dan skalabel untuk aplikasi AI, termasuk memori temporal.
+ Merancang dan mengimplementasikan sistem memori multi-tier yang persisten untuk agen AI otonom yang melampaui context window sederhana. Memungkinkan agen untuk **mengingat pengguna lintas sesi**, memanggil keputusan masa lalu, mempertahankan knowledge graph, dan beroperasi dengan kontinuitas episodik menyerupai manusia — sambil tetap dalam batas anggaran token.
- ### Panduan Arsitektur
- 1. **Tingkatan Memori**: Pisahkan memori menjadi jangka pendek (konteks kerja), jangka menengah (grafik sesi), dan jangka panjang (memori episodik berbasis vektor).
- 2. **Context Paging**: Implementasikan mekanisme agar agen secara proaktif memanggil dan merangkum interaksi masa lalu tanpa menghabiskan anggaran token.
- 3. **User Knowledge Graph**: Terus perbarui graf preferensi pengguna, batasan proyek, dan keputusan arsitektur seiring waktu.
+ ---
+
+ ### Arsitektur Tier Memori
+
+ | Tier | Nama | Durasi | Teknologi | Kapasitas |
+ |------|------|---------|-----------|-----------|
+ | 0 | In-Context Working Memory | Sesi saat ini | Array messages LLM | ≤ 128K token |
+ | 1 | Session Memory | Jam hingga hari | Zep v2 session + entity graph | Tak terbatas (ringkasan) |
+ | 2 | Episodic Memory | Minggu hingga bulan | Mem0 + pgvector HNSW | Jutaan memori |
+ | 3 | Semantic / Procedural | Permanen | pgvector RAG + tabel KB terstruktur | Basis pengetahuan domain |
+
+ ---
+
+ ### 1. Mem0 v2 — Memori Episodik Lintas Sesi
+
+ Mem0 menyediakan lapisan memori terkelola yang mengekstrak dan menyimpan entitas, preferensi, dan fakta dari percakapan, sehingga dapat dicari lintas sesi.
+
+ **Konsep kunci:**
+ - `Memory.add(messages, user_id)`: ekstrak dan simpan memori dari percakapan — Mem0 secara otomatis mengidentifikasi entitas (nama, preferensi, kendala proyek)
+ - `Memory.search(query, user_id, limit)`: pencarian vektor-kemiripan atas memori episodik pengguna — kembalikan daftar berperingkat fakta yang relevan
+ - **Multi-user isolation**: setiap memori terikat pada `user_id` — tidak ada kebocoran antar pengguna
+ - **Entity extraction**: Mem0 menggunakan LLM untuk mengekstrak entitas terstruktur (nama, preferensi, batasan) dari percakapan mentah
+
+ **Dukungan backend:** Mem0 Cloud (API), atau self-hosted dengan pgvector, Qdrant, Pinecone, atau Chroma.
+
+ Lihat implementasi lengkap Python dan TypeScript di [seksi English](#english).
+
+ ---
+
+ ### 2. Letta/MemGPT — Manajemen Memori In-Context Tak Terbatas
+
+ Letta memungkinkan LLM mengelola memori sendiri melalui tool calls eksplisit ke blok memori:
+ - **`core_memory_append`**: tambahkan fakta baru ke blok memori inti (persona, human profile)
+ - **`core_memory_replace`**: perbarui fakta yang sudah ada di memori inti
+ - **`archival_memory_insert`**: simpan informasi ke penyimpanan arsip jangka panjang (vektor)
+ - **`archival_memory_search`**: cari arsip menggunakan pencarian semantik
+
+ **Pola penggunaan:**
+ 1. Buat agen persisten dengan `client.agents.create()` — simpan `agent_id`
+ 2. Gunakan `agent_id` yang sama di semua sesi masa depan — agen ingat konteks sebelumnya
+ 3. Agen secara proaktif mengelola memorinya sendiri melalui tool calls saat konteks penuh
+
+ ---
+
+ ### 3. Zep v2 — Memori Temporal & Knowledge Graph Pengguna
+
+ Zep menyediakan layanan memori cepat dengan kesadaran temporal, ekstraksi entitas, dan konstruksi knowledge graph pengguna.
+
+ **Fitur utama:**
+ - **Temporal memory**: setiap fakta dicap waktu — agen dapat mempertanyakan "apa yang pengguna katakan minggu lalu tentang X?"
+ - **Entity graph**: Zep secara otomatis membangun graf pengetahuan entitas dari percakapan (orang, tempat, preferensi, keputusan)
+ - **`graph.add()`**: injeksikan data terstruktur (JSON profil pengguna) ke grafik — Zep mengekstrak entitas dan relasi
+ - **`graph.search(scope="edges")`**: cari relasi di knowledge graph menggunakan hybrid search (vektor + kata kunci) + RRF reranking
+ - **Session summary**: Zep secara otomatis merangkum sesi panjang menjadi ringkasan yang dapat diinjeksikan ke konteks agen
+
+ ---
+
+ ### 4. pgvector + HNSW — Penyimpanan Episodik Jangka Panjang
+
+ Untuk penyimpanan Tier 2/3, gunakan PostgreSQL dengan pgvector dan indeks HNSW untuk pencarian kemiripan sub-milidetik atas jutaan embedding memori.
+
+ **Mengapa HNSW daripada IVFFlat?**
+ - HNSW: recall@10 = 99%+, latensi stabil tanpa perlu `VACUUM`
+ - IVFFlat: recall@10 = 95%, memerlukan pemilihan `nlist` yang tepat dan `VACUUM` rutin
+
+ **Parameter HNSW yang direkomendasikan:**
+ - `m = 16`: koneksi per lapisan — keseimbangan antara performa recall dan penggunaan memori
+ - `ef_construction = 64`: kualitas indeks saat build — nilai lebih tinggi = recall lebih baik, build lebih lambat
+ - `ef_search = 40` (opsional via `SET hnsw.ef_search = 40`): kualitas pencarian saat query
+
+ ---
+
+ ### 5. Template Injeksi Memori ke RAG Pipeline
+
+ **Alur retrieval memori optimal:**
+
+ ```
+ Query pengguna
+ ↓
+ [Parallel Recall]
+ ├── pgvector HNSW search (Tier 2 episodic)
+ └── Mem0 semantic search (cross-session)
+ ↓
+ [Merge & Rerank by similarity score]
+ ↓
+ [Filter: min_similarity = 0.70, top_k = 8]
+ ↓
+ [Inject ke system prompt sebagai "Relevant Memories" block]
+ ↓
+ LLM call → response
+ ↓
+ [Store turn to Mem0 + pgvector async]
+ ```
+
+ ---
+
+ ### Anti-Slop Checklist Memori
+
+ - [ ] `user_id` selalu unik dan konsisten antar sesi — gunakan UUID deterministik (mis. `uuid5(NAMESPACE_DNS, email)`)
+ - [ ] Minimal similarity threshold 0.70 untuk menghindari injeksi memori tidak relevan
+ - [ ] Memori yang disimpan tidak melebihi `expires_at` — implementasikan TTL untuk memori sementara
+ - [ ] Zep session dibuat sebelum `memory.add()` dipanggil — validasi idempoten
+ - [ ] Letta `agent_id` disimpan di database untuk reuse lintas sesi
+ - [ ] Purge memori pengguna tersedia untuk kepatuhan GDPR/PDPA
+ - [ ] Semua operasi memori async — tidak memblokir response agen
+ - [ ] Indeks HNSW di-`REINDEX` setelah lebih dari 10% baris dihapus