Agent Memory¶
Trails Agent Memory is a persistent, structured, queryable knowledge store that AI agents use as shared memory across sessions and tools. Instead of flat markdown files or vector databases, agents read and write to a knowledge graph with provenance, confidence scoring, and federation.
See ADR-0051 for the full design rationale.
Quickstart¶
import trails
# Learn a fact
trails.invoke("memory.learn", {
"content": "The SPARQL proxy rejects SERVICE queries",
"confidence": 0.99,
"topic": "security",
"source": "code review of sparql_proxy.py",
"agent_did": "did:key:z6MkClaude",
"scope": "shared",
})
# Recall by context
result = trails.invoke("memory.recall", {
"context": "SPARQL security",
"min_confidence": 0.5,
})
# → Facts ranked by relevance, with provenance
Capability Surface¶
Write¶
| Capability | Description |
|---|---|
memory.learn |
Store a fact with confidence, topic, source, scope, staleness, agent DID |
memory.correct |
Supersede a fact — records reason, creates audit trail |
memory.forget |
Retract a fact (soft delete — never hard-deletes) |
memory.link |
Create typed relationship: causes, requires, contradicts, supports, related_to |
Read¶
| Capability | Description |
|---|---|
memory.recall |
Context-aware retrieval — keyword match + topic + confidence + recency |
memory.query |
Structured query by topic, agent, source, confidence, tags |
memory.explain |
Full provenance chain: who learned it, corrections, links |
memory.diff |
What changed since timestamp: learned, retracted, corrected |
Meta¶
| Capability | Description |
|---|---|
memory.status |
Graph health: fact counts, topics, agents, confidence distribution |
memory.compact |
Prune stale and low-confidence facts (dry_run supported) |
Fact Properties¶
Every fact carries metadata beyond its content:
trails.invoke("memory.learn", {
"content": "VC issuance requires Ed25519 keypair", # what was learned
"confidence": 0.95, # how sure [0.0, 1.0]
"topic": "configuration", # subject area for filtering
"source": "debugging vc.py", # where it came from
"scope": "shared", # local | shared | private
"staleness": "weekly", # stable | weekly | daily | hourly | volatile
"agent_did": "did:key:...", # who learned it
"tags": ["vc", "config"], # labels for filtering
})
Recall Strategy¶
memory.recall combines multiple signals:
- Status filter — active only (unless
include_retracted) - Supersession filter — facts that have been corrected are excluded
- Topic filter — exact match if provided
- Confidence threshold —
min_confidence(default 0.3) - Age filter —
max_age_hoursif set - Scope filter —
local,shared, orprivate - Context keywords — substring matching against fact content
- Ranking — confidence desc, then recency desc
Corrections and Audit Trail¶
Facts are never hard-deleted. When corrected, the original is marked
as superseded and a Correction record links old → new with the reason:
trails.invoke("memory.correct", {
"fact_iri": "https://trails.dev/.../Fact/...",
"new_content": "Health checks run every 60s (not 30s)",
"reason": "Verified in federation.py:L187",
"new_confidence": 0.95,
})
Use memory.explain to trace the full provenance chain:
trails.invoke("memory.explain", {"fact_iri": "..."})
# → fact details + provenance + correction chain + links
Cross-Agent Sharing¶
Facts with scope: "shared" are visible to all agents connected to
the same memory instance. Different agents are identified by their DIDs:
# Claude Code learns at 9am
trails.invoke("memory.learn", {
"content": "VC keypair must be in trails.toml",
"agent_did": "did:key:z6MkClaude",
"scope": "shared",
})
# Copilot recalls at 3pm
trails.invoke("memory.recall", {
"context": "VC keypair",
"scope": "shared",
})
# → Returns Claude's fact with full attribution
For cross-instance sharing (different organizations), use
Federation — shared-scope facts are queryable via
the SERVICE keyword, gated by Cedar policies.
Staleness and Compaction¶
Facts carry a decay policy:
| Policy | TTL | Behavior |
|---|---|---|
stable |
∞ | Never auto-pruned |
weekly |
7d | Pruned on compact after 7d |
daily |
24h | Pruned after 24h |
hourly |
1h | Pruned after 1h |
volatile |
0 | Pruned on next compact |
Run compaction to clean up:
# Preview what would be pruned
trails.invoke("memory.compact", {"min_confidence": 0.3, "dry_run": True})
# Actually prune
trails.invoke("memory.compact", {"min_confidence": 0.3, "dry_run": False})
Framework Integrations¶
The memory works with any AI agent framework:
MCP (Claude Code, Copilot, Cursor)¶
{
"mcpServers": {
"trails-memory": {
"command": "trails",
"args": ["server", "--transport", "stdio"],
"cwd": "/path/to/memory"
}
}
}
Python SDK¶
from integrations.sdk import memory
memory.learn("fact", topic="test", confidence=0.9)
facts = memory.recall(context="test")
LangChain / LangGraph¶
from integrations.langchain_adapter import get_langchain_tools
from langgraph.prebuilt import create_react_agent
tools = get_langchain_tools()
graph = create_react_agent(llm, tools)
OpenAI function calling¶
Anthropic Claude API¶
HTTP (any language)¶
from integrations.http_client import BrainClient
client = BrainClient("http://localhost:8086")
client.learn("fact from remote agent")
Configuration¶
[project]
name = "my-memory"
base_iri = "https://trails.dev/memory/my-project/"
[graph]
backend = "oxigraph"
mode = "persistent" # use "memory" for ephemeral
path = ".trails/memory.db"
[memory]
default_scope = "local"
default_staleness = "weekly"
compact_on_startup = false
max_facts = 100000
Example¶
See examples/agent-memory/ for a complete
working implementation with 43 tests and an interactive demo.