agent-memory
2
总安装量
2
周安装量
#65987
全站排名
安装命令
npx skills add https://github.com/daniel-da-silva-alves/antigravity-agent-toolkit --skill agent-memory
Agent 安装分布
opencode
2
gemini-cli
2
antigravity
2
claude-code
2
github-copilot
2
codex
2
Skill 文档
ð§ Agent Memory (Beyond the Context Window)
An agent without memory is a stranger every time. This skill teaches how to make agents remember.
1. The 4 Types of Memory
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â AGENT MEMORY â
ââââââââââââââââ¬âââââââââââââââ¬âââââââââââââ¬âââââââââââââââ¤
â SHORT-TERM â LONG-TERM â EPISODIC â SEMANTIC â
â (Buffer) â (Persistent)â (Events) â (Knowledge) â
ââââââââââââââââ¼âââââââââââââââ¼âââââââââââââ¼âââââââââââââââ¤
â Last N msgs â User prefs â "Client X â "Customers â
â Current â Purchase â complainedâ from North â
â session â history â about â prefer Pix" â
â state â Preferences â shipping" â â
ââââââââââââââââ¼âââââââââââââââ¼âââââââââââââ¼âââââââââââââââ¤
â LangGraph â PostgreSQL â PostgreSQL â Vector DB â
â State â / SQLite â + timestampâ (Qdrant) â
â (in-memory) â â â â
ââââââââââââââââ¼âââââââââââââââ¼âââââââââââââ¼âââââââââââââââ¤
â TTL: Session â TTL: Forever â TTL: 90d â TTL: Forever â
ââââââââââââââââ´âââââââââââââââ´âââââââââââââ´âââââââââââââââ
When to Use Each
| Type | Use When | Example |
|---|---|---|
| Short-term | Within a single conversation | “User just said they want a blue shirt” |
| Long-term | Facts that persist forever | “Daniel prefers Dell notebooks” |
| Episodic | Specific events with timestamps | “Order #123 was delayed on 01/10” |
| Semantic | Generalized knowledge from patterns | “80% of returns are size-related” |
2. Storage Backends
Decision Tree
What's your scale?
â
âââ Prototype / Local dev
â âââ SQLite (zero config, file-based)
â
âââ Production (single service)
â âââ PostgreSQL (ACID, reliable, pgvector for semantic)
â
âââ High-frequency reads (session cache)
â âââ Redis (TTL, fast, ephemeral)
â
âââ Semantic search over memories
âââ Qdrant / pgvector (vector similarity)
Schema Design (PostgreSQL/SQLite)
-- Core memory table
CREATE TABLE IF NOT EXISTS agent_memories (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
agent_id TEXT NOT NULL,
memory_type TEXT CHECK(memory_type IN ('long_term', 'episodic', 'semantic')),
content TEXT NOT NULL,
metadata JSON,
embedding BLOB, -- For semantic search (optional)
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP, -- NULL = never expires
access_count INTEGER DEFAULT 0
);
-- Index for fast user lookups
CREATE INDEX IF NOT EXISTS idx_memories_user
ON agent_memories(user_id, memory_type);
-- Index for expiration cleanup
CREATE INDEX IF NOT EXISTS idx_memories_expiry
ON agent_memories(expires_at) WHERE expires_at IS NOT NULL;
3. Implementation Patterns
Pattern A: LangGraph Checkpointer (Short-term â Long-term Bridge)
LangGraph has native persistence via Checkpointers. This saves the entire graph state between invocations.
from langgraph.checkpoint.sqlite import SqliteSaver
# Create a persistent checkpointer
memory = SqliteSaver.from_conn_string(":memory:") # or "memories.db"
# Compile graph WITH memory
app = workflow.compile(checkpointer=memory)
# Invoke with a thread_id to persist across calls
config = {"configurable": {"thread_id": "user-daniel-session-1"}}
result = app.invoke({"messages": [HumanMessage(content="Hi")]}, config)
# Next call with SAME thread_id resumes conversation
result2 = app.invoke({"messages": [HumanMessage(content="What did I say?")]}, config)
# Agent remembers "Hi" from the previous call!
Pattern B: Memory as a Tool (Agent queries its own memory)
from langchain_core.tools import tool
import sqlite3
@tool
def recall_user_preference(user_id: str, topic: str) -> str:
"""Search the memory database for user preferences on a given topic.
Use this when the user asks about something they previously mentioned."""
conn = sqlite3.connect("memories.db")
cursor = conn.execute(
"SELECT content FROM agent_memories WHERE user_id = ? AND content LIKE ? ORDER BY created_at DESC LIMIT 3",
(user_id, f"%{topic}%")
)
results = cursor.fetchall()
conn.close()
if results:
return "\n".join([r[0] for r in results])
return "No memories found for this topic."
@tool
def save_user_preference(user_id: str, preference: str) -> str:
"""Save an important user preference or fact to long-term memory.
Use this when the user explicitly states a preference or important fact."""
conn = sqlite3.connect("memories.db")
conn.execute(
"INSERT INTO agent_memories (id, user_id, agent_id, memory_type, content) VALUES (?, ?, ?, ?, ?)",
(str(uuid4()), user_id, "assistant", "long_term", preference)
)
conn.commit()
conn.close()
return f"Saved: {preference}"
Pattern C: Memory Injection (System Prompt Enrichment)
def build_system_prompt(user_id: str, base_prompt: str) -> str:
"""Inject relevant memories into the system prompt before each call."""
conn = sqlite3.connect("memories.db")
cursor = conn.execute(
"SELECT content FROM agent_memories WHERE user_id = ? AND memory_type = 'long_term' ORDER BY access_count DESC LIMIT 5",
(user_id,)
)
memories = cursor.fetchall()
conn.close()
if memories:
memory_block = "\n".join([f"- {m[0]}" for m in memories])
return f"{base_prompt}\n\n## Known Facts About This User:\n{memory_block}"
return base_prompt
Pattern D: Semantic Memory Search (Embedding + Cosine Similarity)
For generalized knowledge (“customers from North prefer Pix”), use vector similarity:
from openai import OpenAI
import numpy as np
import sqlite3
import json
client = OpenAI()
def get_embedding(text: str) -> list[float]:
"""Generate embedding vector for a text."""
response = client.embeddings.create(
input=text, model="text-embedding-3-small"
)
return response.data[0].embedding
def cosine_similarity(a: list[float], b: list[float]) -> float:
"""Calculate cosine similarity between two vectors."""
a, b = np.array(a), np.array(b)
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
def store_semantic_memory(user_id: str, content: str):
"""Store a memory with its embedding for later semantic search."""
embedding = get_embedding(content)
conn = sqlite3.connect("memories.db")
conn.execute(
"INSERT INTO agent_memories (id, user_id, agent_id, memory_type, content, embedding) VALUES (?, ?, ?, ?, ?, ?)",
(str(uuid4()), user_id, "assistant", "semantic", content, json.dumps(embedding))
)
conn.commit()
conn.close()
def search_semantic_memory(user_id: str, query: str, top_k: int = 3) -> list[str]:
"""Find memories most semantically similar to the query."""
query_embedding = get_embedding(query)
conn = sqlite3.connect("memories.db")
cursor = conn.execute(
"SELECT content, embedding FROM agent_memories WHERE user_id = ? AND memory_type = 'semantic'",
(user_id,)
)
scored = []
for content, emb_json in cursor.fetchall():
stored_embedding = json.loads(emb_json)
score = cosine_similarity(query_embedding, stored_embedding)
scored.append((score, content))
conn.close()
scored.sort(reverse=True)
return [content for _, content in scored[:top_k]]
# Usage:
# store_semantic_memory("daniel", "Customers from North Brazil prefer paying with Pix")
# results = search_semantic_memory("daniel", "payment preferences in Manaus")
# â Returns: ["Customers from North Brazil prefer paying with Pix"]
Production Tip: For large-scale semantic memory (10k+ records), replace SQLite + in-memory cosine with pgvector or Qdrant for hardware-accelerated ANN (Approximate Nearest Neighbor) search. See
vector-databasesskill.
4. Memory Lifecycle Management
Forgetting (Critical for GDPR/LGPD)
# Delete all memories for a user (Right to be Forgotten)
def forget_user(user_id: str):
conn.execute("DELETE FROM agent_memories WHERE user_id = ?", (user_id,))
# Expire old episodic memories (cleanup job)
def cleanup_expired():
conn.execute("DELETE FROM agent_memories WHERE expires_at < CURRENT_TIMESTAMP")
Memory Ranking (Recency + Frequency)
Not all memories are equal. Prioritize by:
- Recency: Recent memories are more relevant.
- Frequency: Memories accessed often are important.
- Relevance: Semantic similarity to current query.
-- Score = recency_weight * (1 / days_old) + frequency_weight * access_count
SELECT *,
(1.0 / (julianday('now') - julianday(created_at) + 1)) * 0.7 +
access_count * 0.3 AS relevance_score
FROM agent_memories
WHERE user_id = ?
ORDER BY relevance_score DESC
LIMIT 5;
5. Security Integration
ð´ MANDATORY: All memories MUST be scrubbed for PII before storage.
Use ai-security skill’s Presidio integration:
from presidio_analyzer import AnalyzerEngine
from presidio_anonymizer import AnonymizerEngine
from uuid import uuid4
from datetime import datetime
import sqlite3
import json
analyzer = AnalyzerEngine()
anonymizer = AnonymizerEngine()
def sanitize_memory(text: str, user_id: str, agent_id: str) -> str:
"""Remove PII before storing in memory DB. Logs anonymization actions."""
results = analyzer.analyze(text=text, language="pt")
if results:
anonymized = anonymizer.anonymize(text=text, analyzer_results=results)
# Log what was anonymized for LGPD Art. 37 compliance
conn = sqlite3.connect("memories.db")
conn.execute(
"INSERT INTO memory_audit_log (id, user_id, agent_id, action, entities_found, original_hash, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?)",
(
str(uuid4()), user_id, agent_id, "pii_anonymization",
json.dumps([{"type": r.entity_type, "score": r.score} for r in results]),
str(hash(text)), # Hash only, never store raw PII
datetime.utcnow().isoformat()
)
)
conn.commit()
conn.close()
return anonymized.text
return text
Audit Log Schema (LGPD Art. 37 Compliance)
-- Tracks all PII anonymization actions for regulatory compliance
CREATE TABLE IF NOT EXISTS memory_audit_log (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
agent_id TEXT NOT NULL,
action TEXT NOT NULL, -- 'pii_anonymization', 'memory_deleted', 'user_forgotten'
entities_found JSON, -- [{"type": "CPF", "score": 0.95}]
original_hash TEXT, -- SHA hash of original (never raw PII)
timestamp TIMESTAMP NOT NULL,
details TEXT -- Optional additional context
);
CREATE INDEX IF NOT EXISTS idx_audit_user
ON memory_audit_log(user_id, timestamp DESC);
Rules:
- Never store raw CPF, email, or phone in memories.
- Use
sanitize_memory()before everyINSERT. - Every anonymization is logged in
memory_audit_logwith entity types and confidence scores. - Use
original_hash(not raw text) to correlate entries without exposing PII.
6. Setup
Use the setup script to create the database:
python .agent/scripts/setup-memory-db.py --backend sqlite --path memories.db
python .agent/scripts/setup-memory-db.py --backend postgres --url postgresql://user:pass@localhost/mydb
ð Related Skills
| Need | Skill |
|---|---|
| Agent architecture | agentic-patterns |
| Vector search for semantic memory | vector-databases |
| PII protection | ai-security |
| Database schema | database-design |