Skip to content

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:

  1. Status filter — active only (unless include_retracted)
  2. Supersession filter — facts that have been corrected are excluded
  3. Topic filter — exact match if provided
  4. Confidence thresholdmin_confidence (default 0.3)
  5. Age filtermax_age_hours if set
  6. Scope filterlocal, shared, or private
  7. Context keywords — substring matching against fact content
  8. 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

from integrations.openai_schema import get_openai_tools
tools = get_openai_tools()

Anthropic Claude API

from integrations.anthropic_schema import get_anthropic_tools
tools = get_anthropic_tools()

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.