Designs cross-session semantic memory for agents (Mem0, Zep/Graphiti, Letta, Cognee, LangMem) with entity identity, validity windows, and consolidation. Use when choosing a memory framework, temporal knowledge graph, or LoCoMo/LongMemEval/DMR benchmark. Do not use for file scratchpads, conversation compaction, or in-flight token-budget tactics.
Memory provides the persistence layer that allows agents to maintain continuity across sessions and reason over accumulated knowledge. Simple agents rely entirely on context for memory, losing all state when sessions end. Sophisticated agents implement layered memory architectures that balance immediate context needs with long-term knowledge retention. The evolution from vector stores to knowledge graphs to temporal knowledge graphs represents increasing investment in structured memory for improved retrieval and reasoning.
When to Use
Activate this skill when:
Building agents that must persist knowledge across sessions.
Choosing between memory frameworks (Mem0, Zep/Graphiti, Letta, LangMem, Cognee).
Needing to maintain entity consistency across conversations.
Implementing reasoning over accumulated knowledge.
Designing memory architectures that scale in production.
Evaluating memory systems against benchmarks (LoCoMo, LongMemEval, DMR).
Building dynamic memory with automatic entity/relationship extraction and self-improving memory (Cognee).
Do Not Use
Route adjacent work to the skill that owns it:
File-backed scratchpads, run logs, and tool-output offloading → filesystem-context.
Conversation compaction or human-readable handoff summaries → context-compression.
Masking, prefix caching, token budgets, or retrieval scoping inside one trajectory → context-optimization.
Formal belief/desire/intention models over RDF state → bdi-mental-states.
Deprecation & Security Warnings
Encryption at rest is mandatory for PII. Avoid any memory store that does not support encryption at rest (e.g., plain SQLite files) for personally identifiable information. Prefer stores with built-in AES-256 encryption or external vault integration.
Zep/Graphiti cloud OAuth. The cloud-hosted offering now requires OAuth 2.0 scopes memory.read and memory.write; legacy API keys are deprecated as of 2026-03-01.
Validate embedding dimensions. Never accept unchecked user-generated embeddings; always validate vector dimensions against the pinned model to prevent injection attacks.
Network isolation. When using Mem0 or any managed vector store, enable network-level isolation (VPC, private endpoints) to mitigate data exfiltration risks.
Prerequisites
Python 3.11+ for framework examples (Mem0, Cognee, Graphiti, LangMem).
A TLS-capable vector store or graph database endpoint (Redis, Neo4j 5.x, or managed equivalent).
Environment variables for secrets — never hard-code connection strings. Example placeholders: MEM0_STORE_URL, GRAPHITI_API_KEY, COGNEE_DATA_DIR.
Windows host is primary (PowerShell). Use python -m venv and .\.venv\Scripts\Activate.ps1 for virtual environments on Windows.
Load ./references/implementation.md when implementing vector stores, property graphs, temporal queries, or memory consolidation logic from scratch (includes 2026-05 security hardening notes and cryptographic hash-based tamper check).
Procedure
Design memory as a layered system: pick the shallowest layer that meets the persistence need, validate retrieval against benchmarks, and add structure only when a simpler layer demonstrably fails.
Step 1 — Understand the Memory Layer Spectrum
Think of memory as a spectrum from volatile context window to persistent storage. Default to the simplest layer that meets retrieval needs, because benchmark evidence suggests tool complexity matters less than reliable retrieval for some memory workloads (claim-memory-locomo-filesystem-baseline). Add structure (graphs, temporal validity) only when retrieval quality degrades or the agent needs multi-hop reasoning, relationship traversal, or time-travel queries.
Layer
Persistence
Implementation
When to Use
Working
Context window only
Scratchpad in system prompt
Always — optimize with attention-favored positions
Short-term
Session-scoped
File-system, in-memory cache
Intermediate tool results, conversation state
Long-term
Cross-session
Key-value store → graph DB (e.g., RedisJSON, Neo4j 5.x)
User preferences, domain knowledge, entity registries
Entity
Cross-session
Entity registry + properties
Maintaining identity ("John Doe" = same person across conversations)
Temporal KG
Cross-session + history
Graph with validity intervals (Zep/Graphiti v3.1)
Facts that change over time, time-travel queries, preventing context clash
Step 2 — Select a Framework
Select a framework based on the dominant retrieval pattern the agent requires. Use this table to narrow the shortlist, then validate with the benchmark data below.
Framework
Architecture
Best For
Trade-off
Mem0
Vector store + graph memory, pluggable backends (v2.4, 2026-04)
Multi-tenant systems, broad integrations
Less specialized for multi-agent
Zep/Graphiti
Temporal knowledge graph, bi-temporal model (v3.1, 2026-02)
Advanced features cloud-locked; requires OAuth 2.0
Letta
Self-editing memory with tiered storage (in-context/core/archival) (v1.8, 2026-01)
Full agent introspection, stateful services
Complexity for simple use cases
Cognee
Multi-layer semantic graph via customizable ECL pipeline with customizable Tasks (v2.2, 2026-03)
Evolving agent memory that adapts and learns; multi-hop reasoning
Heavier ingest-time processing
LangMem
Memory tools for LangGraph workflows (v0.9, 2025-12)
Teams already on LangGraph
Tightly coupled to LangGraph
File-system
Plain files with naming conventions (v1.0)
Simple agents, prototyping
No semantic search, no relationships
Selection rules:
Choose Zep/Graphiti when the agent needs bi-temporal modeling (tracking both when events occurred and when they were ingested). Its three-tier knowledge graph (episode, semantic entity, community subgraphs) excels at temporal queries.
Choose Mem0 when the priority is fast time-to-production with managed infrastructure.
Choose Letta when the agent needs deep self-introspection through its Agent Development Environment.
Choose Cognee when the agent must build dense multi-layer semantic graphs — it layers text chunks and entity types as nodes with detailed relationship edges, and every core piece (ingestion, entity extraction, post-processing, retrieval) is customizable.
Step 3 — Consult Benchmarks
Consult these benchmarks to set expectations, but treat them as source-specific signals for retrieval dimensions rather than absolute rankings. No single benchmark is definitive.
System
DMR Accuracy
LoCoMo
HotPotQA (multi-hop)
Latency
Cognee
—
—
Published high score (2026-04)
Variable
Zep (Temporal KG)
Published high score (2026-02)
—
Mid-range across metrics
Low-latency reported
Letta (filesystem)
—
Published filesystem baseline (2025-11)
—
—
Mem0
—
Published specialized-tool baseline (2026-03)
Lower in one comparison
—
MemGPT
Published high score (2025-10)
—
—
Variable
GraphRAG
Published mid/high range (2025-09)
—
—
Variable
Vector RAG baseline
Published lower range (2025-08)
—
—
Fast
Key takeaway: Compare memory systems by retrieval shape, not brand. Use benchmark numbers as dated evidence that must be rechecked before making product claims. The stable design rule is to start shallow, measure retrieval quality, then add semantic or graph structure only when a simpler layer fails.
Step 4 — Match Retrieval Strategy to Query Shape
Strategy
Use When
Limitation
Semantic (embedding similarity, OpenAI text-embedding-3-large or Cohere embed-multilingual-v3)
Direct factual queries
Degrades on multi-hop reasoning
Entity-based (graph traversal)
"Tell me everything about X"
Requires graph structure
Temporal (validity filter)
Facts change over time
Requires validity metadata
Hybrid (semantic + keyword + graph)
Best overall accuracy
Most infrastructure
Hybrid approaches reduce active context by retrieving only relevant subgraphs or memories. Cognee implements hybrid retrieval through multiple search modes across graph, vector, and relational stores, letting agents select the retrieval strategy that fits the query type rather than using a one-size-fits-all approach.
Step 5 — Follow the Escalation Path
Prototype: Use file-system memory. Store facts as structured JSON with ISO-8601 timestamps and optional HMAC signatures for integrity. This validates agent behavior before committing to infrastructure.
Scale: Move to Mem0 or a vector store with metadata when the agent needs semantic search and multi-tenant isolation, because file-based lookup cannot handle similarity queries.
Complex reasoning: Add Zep/Graphiti when the agent needs relationship traversal, temporal validity, or cross-session synthesis. Graphiti uses structured ties with generic relations, keeping graphs simple and easy to reason about; Cognee builds denser multi-layer semantic graphs with detailed relationship edges — choose based on whether the agent needs temporal bi-modeling (Graphiti) or richer interconnected knowledge structures (Cognee).
Full control: Use Letta or Cognee when the agent must self-manage its own memory with deep introspection, because these frameworks expose memory operations as first-class agent actions.
Step 6 — Implement Memory Consolidation
Run consolidation periodically to prevent unbounded growth, because unchecked memory accumulation degrades retrieval quality over time. Invalidate but do not discard — preserving history matters for temporal queries that need to reconstruct past states. Trigger consolidation on memory count thresholds, degraded retrieval quality, or scheduled intervals.
Load ./references/implementation.md for working consolidation code that includes a cryptographic hash-based tamper check (added 2026-05).
Step 7 — Integrate with Context
Load memories just-in-time rather than preloading everything, because large context payloads are expensive and degrade attention quality. Place retrieved memories in attention-favored positions (beginning or end of context) to maximize their influence on generation. When using OpenAI gpt-4o-2024-08-06 or Claude 3.5-sonnet-2024-10, prepend a memory header that includes a SHA-256 hash of the retrieved chunk for downstream verification.
Step 8 — Implement Error Recovery
Handle retrieval failures gracefully because memory systems are inherently noisy. Apply these recovery strategies in order:
Empty retrieval: Fall back to broader search (remove entity filter, widen time range). If still empty, prompt user for clarification.
Stale results: Check valid_until timestamps. If most results are expired, trigger consolidation before retrying.
Conflicting facts: Prefer the fact with the most recent valid_from. Surface the conflict to the user if confidence is low.
Storage failure: Queue writes for retry with exponential back-off. Never block the agent's response on a memory write.
Guidelines
These are defaults, not dogma. Each one carries the reason it exists so you can recognize when a deliberate exception is warranted.
Start with file-system memory and escalate only when retrieval quality demands it. Why: every deeper layer (vector, graph, temporal KG) adds infrastructure, operational burden, and new failure modes, and benchmark evidence shows a simple filesystem baseline can match specialized tooling on some workloads (claim-memory-locomo-filesystem-baseline). Pay that cost only once a simpler layer measurably falls short.
Track temporal validity (valid_from/valid_until) for any fact that can change. Why: without it the agent cannot distinguish a current fact from a superseded one, so stale data silently poisons the context and the agent acts on outdated assumptions.
Prefer hybrid retrieval (semantic + keyword + graph) when accuracy matters most. Why: each single strategy has a blind spot — semantic search degrades on multi-hop reasoning, keyword misses paraphrases, graph traversal needs structure — and combining them covers each other's gaps. The trade-off is more infrastructure, so reserve hybrid for high-stakes retrieval.
Consolidate periodically and invalidate rather than discard. Why: unbounded growth degrades retrieval precision over time, but hard-deleting history breaks the time-travel queries that need to reconstruct a past state. Invalidation preserves both retrieval quality and auditability.
Design for retrieval failure with explicit fallbacks. Why: memory systems are inherently noisy and will return empty, stale, or conflicting results in production; an agent that assumes a clean hit will hallucinate or stall the moment a lookup misses.
Treat persistence as a privacy obligation, not just a feature. Why: storing user data across sessions creates retention, deletion-right, and regulatory exposure (GDPR/CCPA). Define retention windows, honor deletion requests, and encrypt PII at rest before data accumulates, because retrofitting compliance onto a populated store is far harder.
Benchmark against LoCoMo or LongMemEval before and after every change. Why: a new embedding model or consolidation policy can regress retrieval invisibly; a before/after measurement turns "it feels better" into evidence and catches silent regressions early.
Monitor memory growth and retrieval latency in production. Why: latency creep and unbounded memory size degrade quietly until they hurt user-facing response time, so treat them as leading indicators and page someone before users feel it — for instance, alert on > 200 ms latency per query.
Pin one embedding model per store and re-embed on any upgrade. Why: vectors written by one model are not comparable to vectors written by another, so mixing them — e.g., reading text-embedding-3-large entries with text-embedding-3-xl — quietly wrecks similarity scores. On an upgrade, batch re-index every entry so the whole store shares one vector space.
Pitfalls
Stuffing everything into context: Loading all available memories into the prompt is expensive and degrades attention quality. Use just-in-time retrieval with relevance filtering instead.
Ignoring temporal validity: Facts go stale. Without validity tracking, outdated information poisons the context and the agent acts on wrong assumptions.
Over-engineering early: Simple filesystem-backed memory can outperform more specialized tooling on some benchmarks (claim-memory-locomo-filesystem-baseline). Add sophistication only when simple approaches demonstrably fail.
No consolidation strategy: Unbounded memory growth degrades retrieval quality over time. Set memory count thresholds or scheduled intervals to trigger consolidation.
Embedding model mismatch: Writing memories with one embedding model and reading with another produces poor retrieval because vector spaces are not interchangeable. Pin a single embedding model for each memory store and re-embed all entries if the model changes.
Graph schema rigidity: Over-structured graph schemas (rigid node types, fixed relationship labels) break when the domain evolves. Prefer generic relation types and flexible property bags so new entity kinds do not require schema migrations.
Stale memory poisoning: Old memories that contradict the current state corrupt agent behavior silently. Implement expiry policies or confidence decay so the agent deprioritizes aged facts, and surface contradictions explicitly when detected.
Memory-context mismatch: Retrieving memories that are topically related but contextually wrong (e.g., a memory about "Python" the snake when the agent is discussing Python the language). Mitigate by including session or domain metadata in memory entries and filtering on it during retrieval.
Security oversight: Never store raw PII without encryption-at-rest and access-control checks. Use field-level encryption for sensitive attributes (e.g., email, SSN).
Examples
Example 1: Mem0 Integration (v2.4)
A production wrapper with typed signatures, input validation, secrets read from the environment, and memory writes that degrade gracefully instead of blocking the agent.
from __future__ import annotations
import logging
import os
from datetime import datetime, timezone
from mem0 import Memory
logger = logging.getLogger("memory.mem0")
def utc_now_iso() -> str:
"""Return the current UTC time as an ISO-8601 string."""
return datetime.now(timezone.utc).isoformat()
def build_memory(store_url: str | None = None) -> Memory:
"""Construct a Mem0 client backed by an encrypted, TLS-only store."""
resolved = store_url or os.environ.get("MEM0_STORE_URL")
if not resolved:
raise ValueError(
"MEM0_STORE_URL is not set. Provide a TLS connection string, "
"e.g. 'rediss://:<password>@mem0-redis:6379/0'."
)
if not resolved.startswith(("rediss://", "redis://")):
raise ValueError(f"Unsupported store URL scheme: {resolved!r}")
if not resolved.startswith("rediss://") and "tls=true" not in resolved:
raise ValueError("Refusing to connect without TLS; use 'rediss://' or add 'tls=true'.")
return Memory(store_url=resolved)
def remember(memory: Memory, text: str, user_id: str) -> None:
"""Persist one fact for a user. Never blocks the agent on store failure."""
if not text.strip():
raise ValueError("Refusing to store an empty memory.")
if not user_id.strip():
raise ValueError("user_id is required to scope memories per tenant.")
try:
memory.add(text, user_id=user_id, metadata={"timestamp": utc_now_iso()})
except Exception as exc: # noqa: BLE001
logger.warning("Mem0 write failed for user %s: %s", user_id, exc)
def current_preference(
memory: Memory,
question: str,
user_id: str,
top_k: int = 3,
) -> list[dict[str, object]]:
"""Return only the still-valid memories for a question."""
if not question.strip():
raise ValueError("Refusing to search with an empty query.")
if top_k <= 0:
raise ValueError("top_k must be a positive integer.")
try:
results = memory.search(query=question, user_id=user_id, limit=top_k)
except Exception as exc: # noqa: BLE001
logger.warning("Mem0 search failed for user %s: %s", user_id, exc)
return []
# Filter out expired entries
now = utc_now_iso()
valid = [r for r in results if r.get("metadata", {}).get("valid_until", None) is None
or r["metadata"]["valid_until"] > now]
return valid
Example 2: Zep/Graphiti Temporal KG (v3.1)
Recording a residence fact with validity intervals and querying at a specific point in time.
from __future__ import annotations
import logging
from datetime import datetime, timezone
from graphiti import GraphitiClient
logger = logging.getLogger("memory.graphiti")
def build_graphiti_client() -> GraphitiClient:
"""Construct a Graphiti client using OAuth 2.0 (legacy API keys deprecated 2026-03-01)."""
return GraphitiClient.from_oauth(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
scopes=["memory.read", "memory.write"],
)
def _require_aware(name: str, value: datetime) -> None:
if value.tzinfo is None:
raise ValueError(f"{name} must be timezone-aware; got naive {value!r}")
def record_residence(
client: GraphitiClient,
user_id: str,
address_id: str,
valid_from: datetime,
valid_until: datetime | None,
) -> None:
"""Record a LIVES_AT edge with bi-temporal validity."""
_require_aware("valid_from", valid_from)
if valid_until is not None:
_require_aware("valid_until", valid_until)
try:
client.add_edge(
source=user_id,
target=address_id,
relation="LIVES_AT",
valid_from=valid_from,
valid_until=valid_until,
)
except Exception as exc: # noqa: BLE001
logger.error("Failed to record residence for user %s: %s", user_id, exc)
raise
def residence_at(client: GraphitiClient, query_time: datetime) -> list[dict[str, object]]:
"""Return the residence facts that were valid at a specific instant."""
_require_aware("query_time", query_time)
try:
results = client.query_at_time(
{"type": "LIVES_AT", "source_label": "User"},
query_time=query_time,
)
except Exception as exc: # noqa: BLE001
logger.warning("Temporal query failed at %s: %s", query_time.isoformat(), exc)
return []
return list(results)
client = build_graphiti_client()
user_node = "user:alice"
address_node = "address:berlin-flat-12"
record_residence(
client,
user_id=user_node,
address_id=address_node,
valid_from=datetime(2024, 1, 15, tzinfo=timezone.utc),
valid_until=datetime(2024, 9, 1, tzinfo=timezone.utc),
)
results = residence_at(client, query_time=datetime(2024, 3, 1, tzinfo=timezone.utc))
print(results)
Example 3: Cognee Memory Ingestion and Search (v2.2)
The ECL pipeline (add → cognify → memify → search) wrapped in async functions with source validation, typed returns, and an empty-result fallback on search failure.
from __future__ import annotations
import logging
from pathlib import Path
import cognee
from cognee.modules.search.types import SearchType
logger = logging.getLogger("memory.cognee")
async def ingest_knowledge(sources: list[str | Path]) -> None:
"""Run Cognee's ECL pipeline over real sources."""
if not sources:
raise ValueError("Provide at least one source to ingest.")
for source in sources:
candidate = Path(source)
if candidate.exists():
await cognee.add(str(candidate))
elif isinstance(source, str):
await cognee.add(source)
else:
raise FileNotFoundError(f"Source path does not exist: {candidate}")
try:
await cognee.cognify()
await cognee.memify()
except Exception as exc: # noqa: BLE001
logger.error("Cognee ingestion pipeline failed: %s", exc)
raise
async def recall(question: str, top_k: int = 5) -> list[dict[str, object]]:
"""Retrieve relationship-aware context for a question."""
if not question.strip():
raise ValueError("Refusing to search with an empty query.")
if top_k <= 0:
raise ValueError("top_k must be a positive integer.")
try:
results = await cognee.search(
query_text=question,
query_type=SearchType.GRAPH_COMPLETION,
top_k=top_k,
filters={"valid_until": None},
)
except Exception as exc: # noqa: BLE001
logger.warning("Cognee search failed for query %r: %s", question, exc)
return []
return list(results)
async def main() -> None:
await ingest_knowledge(
[
"./docs/",
"Alice leads the payments team and prefers async standups.",
]
)
answers = await recall("Who leads the payments team?")
print(answers)
Verification
Test the skill end-to-end with at least two different memory frameworks.
Confirm the shallowest viable memory layer was chosen — working/file-system was used before escalating to vector, graph, or temporal KG.
Confirm the selected framework matches the dominant retrieval pattern and was validated against a benchmark (LoCoMo, LongMemEval, or DMR) before any product claim.
Confirm temporal validity (valid_from/valid_until) is tracked for every fact that can change over time.
Confirm a single embedding model is pinned per memory store, with a re-embedding plan if the model changes (no read/write vector-space mismatch).
Confirm a consolidation trigger exists (count threshold, degraded retrieval, or schedule) and that it invalidates rather than discards history.
Confirm retrieval-failure fallbacks are implemented for empty, stale, conflicting, and storage-failure paths, and that memory writes never block the agent's response.
Confirm memories are loaded just-in-time into attention-favored positions rather than preloaded wholesale.
Confirm session/domain metadata is attached to entries and filtered on retrieval to prevent context mismatch.
Confirm privacy, retention, and deletion policies are defined and enforced for persistent memory (including encryption-at-rest).
Confirm memory growth and retrieval latency are monitored in production; alerts fire if latency > 200 ms or size grows > 2× baseline.
Checkable commands:
# Verify environment variables are set (no secrets in source)
echo $env:MEM0_STORE_URL # should print rediss://... (not empty, not http://)
echo $env:GRAPHITI_API_KEY # should be set for OAuth flow
# Verify embedding model pinning — check store metadata
python -c "from mem0 import Memory; m = Memory(store_url='$env:MEM0_STORE_URL'); print(m.config.embedding_model)"
# Run a smoke-test retrieval and check latency
python -c "import time; from mem0 import Memory; m = Memory(store_url='$env:MEM0_STORE_URL'); t=time.time(); r=m.search('test', user_id='smoke'); print(f'latency_ms={int((time.time()-t)*1000)}'); assert len(r) >= 0"
Related Skills
filesystem-context: file-backed scratchpads, logs, and simple run state before semantic retrieval is needed.
context-compression: summaries and handoffs that preserve session state in prose.
context-optimization: just-in-time memory loading and retrieval scoping inside active context budgets.
context-degradation: stale or conflicting memories as context poisoning or clash.
bdi-mental-states: formal mental-state modeling when beliefs, desires, intentions, and provenance chains matter.
multi-agent-patterns: shared memory across agents.
evaluation: memory quality, retrieval correctness, and benchmark selection.
References
Internal references:
./references/implementation.md — Read when: implementing vector stores, property graphs, temporal queries, or memory consolidation logic from scratch (includes 2026-05 security hardening notes and cryptographic hash-based tamper check).
Related skills in this collection:
context-fundamentals — Read when: designing the context layer that memory feeds into.
multi-agent-patterns — Read when: multiple agents need to share or coordinate memory state.
External resources:
Zep temporal knowledge graph paper (arXiv:2501.13956) — 2026-01
Mem0 production architecture paper (arXiv:2504.19413) — 2026-04
1---2name: memory-systems3description: Designs cross-session semantic memory for agents (Mem0, Zep/Graphiti, Letta, Cognee, LangMem) with entity identity, validity windows, and consolidation. Use when choosing a memory framework, temporal knowledge graph, or LoCoMo/LongMemEval/DMR benchmark. Do not use for file scratchpads, conversation compaction, or in-flight token-budget tactics.4---56# Memory System Design
78Memory provides the persistence layer that allows agents to maintain continuity across sessions and reason over accumulated knowledge. Simple agents rely entirely on context for memory, losing all state when sessions end. Sophisticated agents implement layered memory architectures that balance immediate context needs with long-term knowledge retention. The evolution from vector stores to knowledge graphs to temporal knowledge graphs represents increasing investment in structured memory for improved retrieval and reasoning.
910## When to Use
1112Activate this skill when:
1314- Building agents that must persist knowledge across sessions.
15- Choosing between memory frameworks (Mem0, Zep/Graphiti, Letta, LangMem, Cognee).
16- Needing to maintain entity consistency across conversations.
17- Implementing reasoning over accumulated knowledge.
18- Designing memory architectures that scale in production.
19- Evaluating memory systems against benchmarks (LoCoMo, LongMemEval, DMR).
20- Building dynamic memory with automatic entity/relationship extraction and self-improving memory (Cognee).
2122### Do Not Use
2324Route adjacent work to the skill that owns it:
2526- File-backed scratchpads, run logs, and tool-output offloading → `filesystem-context`.
27- Conversation compaction or human-readable handoff summaries → `context-compression`.
28- Masking, prefix caching, token budgets, or retrieval scoping inside one trajectory → `context-optimization`.
29- Formal belief/desire/intention models over RDF state → `bdi-mental-states`.
3031### Deprecation & Security Warnings
3233- **Encryption at rest is mandatory for PII.** Avoid any memory store that does not support encryption at rest (e.g., plain SQLite files) for personally identifiable information. Prefer stores with built-in AES-256 encryption or external vault integration.
34- **Zep/Graphiti cloud OAuth.** The cloud-hosted offering now requires OAuth 2.0 scopes `memory.read` and `memory.write`; legacy API keys are deprecated as of 2026-03-01.
35- **Validate embedding dimensions.** Never accept unchecked user-generated embeddings; always validate vector dimensions against the pinned model to prevent injection attacks.
36- **Network isolation.** When using Mem0 or any managed vector store, enable network-level isolation (VPC, private endpoints) to mitigate data exfiltration risks.
3738## Prerequisites
3940- Python 3.11+ for framework examples (Mem0, Cognee, Graphiti, LangMem).
41- A TLS-capable vector store or graph database endpoint (Redis, Neo4j 5.x, or managed equivalent).
42- Environment variables for secrets — never hard-code connection strings. Example placeholders: `MEM0_STORE_URL`, `GRAPHITI_API_KEY`, `COGNEE_DATA_DIR`.
43- Windows host is primary (PowerShell). Use `python -m venv` and `.\.venv\Scripts\Activate.ps1` for virtual environments on Windows.
44- Load `./references/implementation.md` when implementing vector stores, property graphs, temporal queries, or memory consolidation logic from scratch (includes 2026-05 security hardening notes and cryptographic hash-based tamper check).
4546## Procedure
4748Design memory as a layered system: pick the shallowest layer that meets the persistence need, validate retrieval against benchmarks, and add structure only when a simpler layer demonstrably fails.
4950### Step 1 — Understand the Memory Layer Spectrum
5152Think of memory as a spectrum from volatile context window to persistent storage. Default to the simplest layer that meets retrieval needs, because benchmark evidence suggests tool complexity matters less than reliable retrieval for some memory workloads (claim-memory-locomo-filesystem-baseline). Add structure (graphs, temporal validity) only when retrieval quality degrades or the agent needs multi-hop reasoning, relationship traversal, or time-travel queries.
5354| Layer | Persistence | Implementation | When to Use |
55|-------|------------|----------------|-------------|
56| **Working** | Context window only | Scratchpad in system prompt | Always — optimize with attention-favored positions |
57| **Short-term** | Session-scoped | File-system, in-memory cache | Intermediate tool results, conversation state |
58| **Long-term** | Cross-session | Key-value store → graph DB (e.g., RedisJSON, Neo4j 5.x) | User preferences, domain knowledge, entity registries |
59| **Entity** | Cross-session | Entity registry + properties | Maintaining identity ("John Doe" = same person across conversations) |
60| **Temporal KG** | Cross-session + history | Graph with validity intervals (Zep/Graphiti v3.1) | Facts that change over time, time-travel queries, preventing context clash |
6162### Step 2 — Select a Framework
6364Select a framework based on the dominant retrieval pattern the agent requires. Use this table to narrow the shortlist, then validate with the benchmark data below.
6566| Framework | Architecture | Best For | Trade-off |
67|-----------|-------------|----------|-----------|
68| **Mem0** | Vector store + graph memory, pluggable backends (v2.4, 2026-04) | Multi-tenant systems, broad integrations | Less specialized for multi-agent |
69| **Zep/Graphiti** | Temporal knowledge graph, bi-temporal model (v3.1, 2026-02) | Enterprise requiring relationship modeling + temporal reasoning | Advanced features cloud-locked; requires OAuth 2.0 |
70| **Letta** | Self-editing memory with tiered storage (in-context/core/archival) (v1.8, 2026-01) | Full agent introspection, stateful services | Complexity for simple use cases |
71| **Cognee** | Multi-layer semantic graph via customizable ECL pipeline with customizable Tasks (v2.2, 2026-03) | Evolving agent memory that adapts and learns; multi-hop reasoning | Heavier ingest-time processing |
72| **LangMem** | Memory tools for LangGraph workflows (v0.9, 2025-12) | Teams already on LangGraph | Tightly coupled to LangGraph |
73| **File-system** | Plain files with naming conventions (v1.0) | Simple agents, prototyping | No semantic search, no relationships |
7475**Selection rules:**
7677- Choose **Zep/Graphiti** when the agent needs bi-temporal modeling (tracking both when events occurred and when they were ingested). Its three-tier knowledge graph (episode, semantic entity, community subgraphs) excels at temporal queries.
78- Choose **Mem0** when the priority is fast time-to-production with managed infrastructure.
79- Choose **Letta** when the agent needs deep self-introspection through its Agent Development Environment.
80- Choose **Cognee** when the agent must build dense multi-layer semantic graphs — it layers text chunks and entity types as nodes with detailed relationship edges, and every core piece (ingestion, entity extraction, post-processing, retrieval) is customizable.
8182### Step 3 — Consult Benchmarks
8384Consult these benchmarks to set expectations, but treat them as source-specific signals for retrieval dimensions rather than absolute rankings. No single benchmark is definitive.
8586| System | DMR Accuracy | LoCoMo | HotPotQA (multi-hop) | Latency |
87|--------|-------------|--------|---------------------|---------|
88| Cognee | — | — | Published high score (2026-04) | Variable |
89| Zep (Temporal KG) | Published high score (2026-02) | — | Mid-range across metrics | Low-latency reported |
90| Letta (filesystem) | — | Published filesystem baseline (2025-11) | — | — |
91| Mem0 | — | Published specialized-tool baseline (2026-03) | Lower in one comparison | — |
92| MemGPT | Published high score (2025-10) | — | — | Variable |
93| GraphRAG | Published mid/high range (2025-09) | — | — | Variable |
94| Vector RAG baseline | Published lower range (2025-08) | — | — | Fast |
9596**Key takeaway:** Compare memory systems by retrieval shape, not brand. Use benchmark numbers as dated evidence that must be rechecked before making product claims. The stable design rule is to start shallow, measure retrieval quality, then add semantic or graph structure only when a simpler layer fails.
9798### Step 4 — Match Retrieval Strategy to Query Shape
99100| Strategy | Use When | Limitation |
101|----------|----------|------------|
102| **Semantic** (embedding similarity, OpenAI `text-embedding-3-large` or Cohere `embed-multilingual-v3`) | Direct factual queries | Degrades on multi-hop reasoning |
103| **Entity-based** (graph traversal) | "Tell me everything about X" | Requires graph structure |
104| **Temporal** (validity filter) | Facts change over time | Requires validity metadata |
105| **Hybrid** (semantic + keyword + graph) | Best overall accuracy | Most infrastructure |
106107Hybrid approaches reduce active context by retrieving only relevant subgraphs or memories. Cognee implements hybrid retrieval through multiple search modes across graph, vector, and relational stores, letting agents select the retrieval strategy that fits the query type rather than using a one-size-fits-all approach.
108109### Step 5 — Follow the Escalation Path
1101111. **Prototype:** Use file-system memory. Store facts as structured JSON with ISO-8601 timestamps and optional HMAC signatures for integrity. This validates agent behavior before committing to infrastructure.
1122. **Scale:** Move to Mem0 or a vector store with metadata when the agent needs semantic search and multi-tenant isolation, because file-based lookup cannot handle similarity queries.
1133. **Complex reasoning:** Add Zep/Graphiti when the agent needs relationship traversal, temporal validity, or cross-session synthesis. Graphiti uses structured ties with generic relations, keeping graphs simple and easy to reason about; Cognee builds denser multi-layer semantic graphs with detailed relationship edges — choose based on whether the agent needs temporal bi-modeling (Graphiti) or richer interconnected knowledge structures (Cognee).
1144. **Full control:** Use Letta or Cognee when the agent must self-manage its own memory with deep introspection, because these frameworks expose memory operations as first-class agent actions.
115116### Step 6 — Implement Memory Consolidation
117118Run consolidation periodically to prevent unbounded growth, because unchecked memory accumulation degrades retrieval quality over time. **Invalidate but do not discard** — preserving history matters for temporal queries that need to reconstruct past states. Trigger consolidation on memory count thresholds, degraded retrieval quality, or scheduled intervals.
119120Load `./references/implementation.md` for working consolidation code that includes a cryptographic hash-based tamper check (added 2026-05).
121122### Step 7 — Integrate with Context
123124Load memories just-in-time rather than preloading everything, because large context payloads are expensive and degrade attention quality. Place retrieved memories in attention-favored positions (beginning or end of context) to maximize their influence on generation. When using OpenAI `gpt-4o-2024-08-06` or Claude `3.5-sonnet-2024-10`, prepend a memory header that includes a SHA-256 hash of the retrieved chunk for downstream verification.
125126### Step 8 — Implement Error Recovery
127128Handle retrieval failures gracefully because memory systems are inherently noisy. Apply these recovery strategies in order:
129130- **Empty retrieval:** Fall back to broader search (remove entity filter, widen time range). If still empty, prompt user for clarification.
131- **Stale results:** Check `valid_until` timestamps. If most results are expired, trigger consolidation before retrying.
132- **Conflicting facts:** Prefer the fact with the most recent `valid_from`. Surface the conflict to the user if confidence is low.
133- **Storage failure:** Queue writes for retry with exponential back-off. Never block the agent's response on a memory write.
134135## Guidelines
136137These are defaults, not dogma. Each one carries the reason it exists so you can recognize when a deliberate exception is warranted.
1381391. **Start with file-system memory and escalate only when retrieval quality demands it.** Why: every deeper layer (vector, graph, temporal KG) adds infrastructure, operational burden, and new failure modes, and benchmark evidence shows a simple filesystem baseline can match specialized tooling on some workloads (claim-memory-locomo-filesystem-baseline). Pay that cost only once a simpler layer measurably falls short.
1402. **Track temporal validity (`valid_from`/`valid_until`) for any fact that can change.** Why: without it the agent cannot distinguish a current fact from a superseded one, so stale data silently poisons the context and the agent acts on outdated assumptions.
1413. **Prefer hybrid retrieval (semantic + keyword + graph) when accuracy matters most.** Why: each single strategy has a blind spot — semantic search degrades on multi-hop reasoning, keyword misses paraphrases, graph traversal needs structure — and combining them covers each other's gaps. The trade-off is more infrastructure, so reserve hybrid for high-stakes retrieval.
1424. **Consolidate periodically and invalidate rather than discard.** Why: unbounded growth degrades retrieval precision over time, but hard-deleting history breaks the time-travel queries that need to reconstruct a past state. Invalidation preserves both retrieval quality and auditability.
1435. **Design for retrieval failure with explicit fallbacks.** Why: memory systems are inherently noisy and will return empty, stale, or conflicting results in production; an agent that assumes a clean hit will hallucinate or stall the moment a lookup misses.
1446. **Treat persistence as a privacy obligation, not just a feature.** Why: storing user data across sessions creates retention, deletion-right, and regulatory exposure (GDPR/CCPA). Define retention windows, honor deletion requests, and encrypt PII at rest before data accumulates, because retrofitting compliance onto a populated store is far harder.
1457. **Benchmark against LoCoMo or LongMemEval before and after every change.** Why: a new embedding model or consolidation policy can regress retrieval invisibly; a before/after measurement turns "it feels better" into evidence and catches silent regressions early.
1468. **Monitor memory growth and retrieval latency in production.** Why: latency creep and unbounded memory size degrade quietly until they hurt user-facing response time, so treat them as leading indicators and page someone before users feel it — for instance, alert on > 200 ms latency per query.
1479. **Pin one embedding model per store and re-embed on any upgrade.** Why: vectors written by one model are not comparable to vectors written by another, so mixing them — e.g., reading `text-embedding-3-large` entries with `text-embedding-3-xl` — quietly wrecks similarity scores. On an upgrade, batch re-index every entry so the whole store shares one vector space.
148149## Pitfalls
1501511. **Stuffing everything into context:** Loading all available memories into the prompt is expensive and degrades attention quality. Use just-in-time retrieval with relevance filtering instead.
1522. **Ignoring temporal validity:** Facts go stale. Without validity tracking, outdated information poisons the context and the agent acts on wrong assumptions.
1533. **Over-engineering early:** Simple filesystem-backed memory can outperform more specialized tooling on some benchmarks (claim-memory-locomo-filesystem-baseline). Add sophistication only when simple approaches demonstrably fail.
1544. **No consolidation strategy:** Unbounded memory growth degrades retrieval quality over time. Set memory count thresholds or scheduled intervals to trigger consolidation.
1555. **Embedding model mismatch:** Writing memories with one embedding model and reading with another produces poor retrieval because vector spaces are not interchangeable. Pin a single embedding model for each memory store and re-embed all entries if the model changes.
1566. **Graph schema rigidity:** Over-structured graph schemas (rigid node types, fixed relationship labels) break when the domain evolves. Prefer generic relation types and flexible property bags so new entity kinds do not require schema migrations.
1577. **Stale memory poisoning:** Old memories that contradict the current state corrupt agent behavior silently. Implement expiry policies or confidence decay so the agent deprioritizes aged facts, and surface contradictions explicitly when detected.
1588. **Memory-context mismatch:** Retrieving memories that are topically related but contextually wrong (e.g., a memory about "Python" the snake when the agent is discussing Python the language). Mitigate by including session or domain metadata in memory entries and filtering on it during retrieval.
1599. **Security oversight:** Never store raw PII without encryption-at-rest and access-control checks. Use field-level encryption for sensitive attributes (e.g., email, SSN).
160161## Examples
162163### Example 1: Mem0 Integration (v2.4)
164165A production wrapper with typed signatures, input validation, secrets read from the environment, and memory writes that degrade gracefully instead of blocking the agent.
166167```python
168from __future__ import annotations
169170import logging
171import os
172from datetime import datetime, timezone
173174from mem0 import Memory
175176logger = logging.getLogger("memory.mem0")
177178179def utc_now_iso() -> str:
180 """Return the current UTC time as an ISO-8601 string."""
181 return datetime.now(timezone.utc).isoformat()
182183184def build_memory(store_url: str | None = None) -> Memory:
185 """Construct a Mem0 client backed by an encrypted, TLS-only store."""
186 resolved = store_url or os.environ.get("MEM0_STORE_URL")
187 if not resolved:
188 raise ValueError(
189 "MEM0_STORE_URL is not set. Provide a TLS connection string, "
190 "e.g. 'rediss://:<password>@mem0-redis:6379/0'."
191 )
192 if not resolved.startswith(("rediss://", "redis://")):
193 raise ValueError(f"Unsupported store URL scheme: {resolved!r}")
194 if not resolved.startswith("rediss://") and "tls=true" not in resolved:
195 raise ValueError("Refusing to connect without TLS; use 'rediss://' or add 'tls=true'.")
196 return Memory(store_url=resolved)
197198199def remember(memory: Memory, text: str, user_id: str) -> None:
200 """Persist one fact for a user. Never blocks the agent on store failure."""
201 if not text.strip():
202 raise ValueError("Refusing to store an empty memory.")
203 if not user_id.strip():
204 raise ValueError("user_id is required to scope memories per tenant.")
205 try:
206 memory.add(text, user_id=user_id, metadata={"timestamp": utc_now_iso()})
207 except Exception as exc: # noqa: BLE001
208 logger.warning("Mem0 write failed for user %s: %s", user_id, exc)
209210211def current_preference(
212 memory: Memory,
213 question: str,
214 user_id: str,
215 top_k: int = 3,
216) -> list[dict[str, object]]:
217 """Return only the still-valid memories for a question."""
218 if not question.strip():
219 raise ValueError("Refusing to search with an empty query.")
220 if top_k <= 0:
221 raise ValueError("top_k must be a positive integer.")
222 try:
223 results = memory.search(query=question, user_id=user_id, limit=top_k)
224 except Exception as exc: # noqa: BLE001
225 logger.warning("Mem0 search failed for user %s: %s", user_id, exc)
226 return []
227 # Filter out expired entries
228 now = utc_now_iso()
229 valid = [r for r in results if r.get("metadata", {}).get("valid_until", None) is None
230 or r["metadata"]["valid_until"] > now]
231 return valid
232```
233234### Example 2: Zep/Graphiti Temporal KG (v3.1)
235236Recording a residence fact with validity intervals and querying at a specific point in time.
237238```python
239from __future__ import annotations
240241import logging
242from datetime import datetime, timezone
243244from graphiti import GraphitiClient
245246logger = logging.getLogger("memory.graphiti")
247248249def build_graphiti_client() -> GraphitiClient:
250 """Construct a Graphiti client using OAuth 2.0 (legacy API keys deprecated 2026-03-01)."""
251 return GraphitiClient.from_oauth(
252 client_id="YOUR_CLIENT_ID",
253 client_secret="YOUR_CLIENT_SECRET",
254 scopes=["memory.read", "memory.write"],
255 )
256257258def _require_aware(name: str, value: datetime) -> None:
259 if value.tzinfo is None:
260 raise ValueError(f"{name} must be timezone-aware; got naive {value!r}")
261262263def record_residence(
264 client: GraphitiClient,
265 user_id: str,
266 address_id: str,
267 valid_from: datetime,
268 valid_until: datetime | None,
269) -> None:
270 """Record a LIVES_AT edge with bi-temporal validity."""
271 _require_aware("valid_from", valid_from)
272 if valid_until is not None:
273 _require_aware("valid_until", valid_until)
274 try:
275 client.add_edge(
276 source=user_id,
277 target=address_id,
278 relation="LIVES_AT",
279 valid_from=valid_from,
280 valid_until=valid_until,
281 )
282 except Exception as exc: # noqa: BLE001
283 logger.error("Failed to record residence for user %s: %s", user_id, exc)
284 raise
285286287def residence_at(client: GraphitiClient, query_time: datetime) -> list[dict[str, object]]:
288 """Return the residence facts that were valid at a specific instant."""
289 _require_aware("query_time", query_time)
290 try:
291 results = client.query_at_time(
292 {"type": "LIVES_AT", "source_label": "User"},
293 query_time=query_time,
294 )
295 except Exception as exc: # noqa: BLE001
296 logger.warning("Temporal query failed at %s: %s", query_time.isoformat(), exc)
297 return []
298 return list(results)
299300301client = build_graphiti_client()
302user_node = "user:alice"
303address_node = "address:berlin-flat-12"
304305record_residence(
306 client,
307 user_id=user_node,
308 address_id=address_node,
309 valid_from=datetime(2024, 1, 15, tzinfo=timezone.utc),
310 valid_until=datetime(2024, 9, 1, tzinfo=timezone.utc),
311)
312313results = residence_at(client, query_time=datetime(2024, 3, 1, tzinfo=timezone.utc))
314print(results)
315```
316317### Example 3: Cognee Memory Ingestion and Search (v2.2)
318319The ECL pipeline (add → cognify → memify → search) wrapped in async functions with source validation, typed returns, and an empty-result fallback on search failure.
320321```python
322from __future__ import annotations
323324import logging
325from pathlib import Path
326327import cognee
328from cognee.modules.search.types import SearchType
329330logger = logging.getLogger("memory.cognee")
331332333async def ingest_knowledge(sources: list[str | Path]) -> None:
334 """Run Cognee's ECL pipeline over real sources."""
335 if not sources:
336 raise ValueError("Provide at least one source to ingest.")
337 for source in sources:
338 candidate = Path(source)
339 if candidate.exists():
340 await cognee.add(str(candidate))
341 elif isinstance(source, str):
342 await cognee.add(source)
343 else:
344 raise FileNotFoundError(f"Source path does not exist: {candidate}")
345 try:
346 await cognee.cognify()
347 await cognee.memify()
348 except Exception as exc: # noqa: BLE001
349 logger.error("Cognee ingestion pipeline failed: %s", exc)
350 raise
351352353async def recall(question: str, top_k: int = 5) -> list[dict[str, object]]:
354 """Retrieve relationship-aware context for a question."""
355 if not question.strip():
356 raise ValueError("Refusing to search with an empty query.")
357 if top_k <= 0:
358 raise ValueError("top_k must be a positive integer.")
359 try:
360 results = await cognee.search(
361 query_text=question,
362 query_type=SearchType.GRAPH_COMPLETION,
363 top_k=top_k,
364 filters={"valid_until": None},
365 )
366 except Exception as exc: # noqa: BLE001
367 logger.warning("Cognee search failed for query %r: %s", question, exc)
368 return []
369 return list(results)
370371372async def main() -> None:
373 await ingest_knowledge(
374 [
375 "./docs/",
376 "Alice leads the payments team and prefers async standups.",
377 ]
378 )
379 answers = await recall("Who leads the payments team?")
380 print(answers)
381```
382383## Verification
384385- [ ] Test the skill end-to-end with at least two different memory frameworks.
386- [ ] Confirm the shallowest viable memory layer was chosen — working/file-system was used before escalating to vector, graph, or temporal KG.
387- [ ] Confirm the selected framework matches the dominant retrieval pattern and was validated against a benchmark (LoCoMo, LongMemEval, or DMR) before any product claim.
388- [ ] Confirm temporal validity (`valid_from`/`valid_until`) is tracked for every fact that can change over time.
389- [ ] Confirm a single embedding model is pinned per memory store, with a re-embedding plan if the model changes (no read/write vector-space mismatch).
390- [ ] Confirm a consolidation trigger exists (count threshold, degraded retrieval, or schedule) and that it invalidates rather than discards history.
391- [ ] Confirm retrieval-failure fallbacks are implemented for empty, stale, conflicting, and storage-failure paths, and that memory writes never block the agent's response.
392- [ ] Confirm memories are loaded just-in-time into attention-favored positions rather than preloaded wholesale.
393- [ ] Confirm session/domain metadata is attached to entries and filtered on retrieval to prevent context mismatch.
394- [ ] Confirm privacy, retention, and deletion policies are defined and enforced for persistent memory (including encryption-at-rest).
395- [ ] Confirm memory growth and retrieval latency are monitored in production; alerts fire if latency > 200 ms or size grows > 2× baseline.
396397Checkable commands:
398399```powershell
400# Verify environment variables are set (no secrets in source)
401echo $env:MEM0_STORE_URL # should print rediss://... (not empty, not http://)
402echo $env:GRAPHITI_API_KEY # should be set for OAuth flow
403404# Verify embedding model pinning — check store metadata
405python -c "from mem0 import Memory; m = Memory(store_url='$env:MEM0_STORE_URL'); print(m.config.embedding_model)"
406407# Run a smoke-test retrieval and check latency
408python -c "import time; from mem0 import Memory; m = Memory(store_url='$env:MEM0_STORE_URL'); t=time.time(); r=m.search('test', user_id='smoke'); print(f'latency_ms={int((time.time()-t)*1000)}'); assert len(r) >= 0"
409```
410411## Related Skills
412413- `filesystem-context`: file-backed scratchpads, logs, and simple run state before semantic retrieval is needed.
414- `context-compression`: summaries and handoffs that preserve session state in prose.
415- `context-optimization`: just-in-time memory loading and retrieval scoping inside active context budgets.
416- `context-degradation`: stale or conflicting memories as context poisoning or clash.
417- `bdi-mental-states`: formal mental-state modeling when beliefs, desires, intentions, and provenance chains matter.
418- `multi-agent-patterns`: shared memory across agents.
419- `evaluation`: memory quality, retrieval correctness, and benchmark selection.
420421## References
422423Internal references:
424425- `./references/implementation.md` — Read when: implementing vector stores, property graphs, temporal queries, or memory consolidation logic from scratch (includes 2026-05 security hardening notes and cryptographic hash-based tamper check).
426427Related skills in this collection:
428429- `context-fundamentals` — Read when: designing the context layer that memory feeds into.
430- `multi-agent-patterns` — Read when: multiple agents need to share or coordinate memory state.
431432External resources:
433434- Zep temporal knowledge graph paper (arXiv:2501.13956) — 2026-01
435- Mem0 production architecture paper (arXiv:2504.19413) — 2026-04
436- Cognee optimized knowledge graph + LLM reasoning paper (arXiv:2505.24478) — 2026-05
437- LoCoMo benchmark (Snap Research) — 2025-11
438- MemBench evaluation framework (ACL 2025) — 2025-07
439- Graphiti open-source temporal KG engine (github.com/getzep/graphiti) — latest release v3.1 (2026-02)
440- Cognee open-source knowledge graph memory (github.com/topoteretes/cognee) — latest release v2.2 (2026-03)
441- [Cognee comparison: Form vs Function](https://www.cognee.ai/blog/deep-dives/competition-comparison-form-vs-function) — 2026-04
Run npx skillmds@latest add kayforkind/memory-systems in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Designs cross-session semantic memory for agents (Mem0, Zep/Graphiti, Letta, Cognee, LangMem) with entity identity, validity windows, and consolidation. Use when choosing a memory framework, temporal knowledge graph, or LoCoMo/LongMemEval/DMR benchmark. Do not use for file scratchpads, conversation compaction, or in-flight token-budget tactics. It is listed under Finance & Business on SkillMD.
This skill has not completed SkillMD's automated safety review yet. Capability flags: executes scripts, makes network calls, reads secrets. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
Kayforkind (@kayforkind) published this skill. Their other Agent Skills are listed on their SkillMD profile.