Catalog PyPI
Back to packageRELEASE DETAILS

0.6.1

PyPI

agent-cerebro

Persistent two-tier memory for AI agents. Short-term markdown + long-term SQLite with semantic search.

ai-agentsembeddingsmemorysemantic-searchsqlite
Published19 Oct 2026
Direct dependencies3
Transitive dependenciesNot calculated

README

Version 0.6.1 documentation

Agent Cerebro

PyPI Python License: MIT

Persistent two-tier memory for AI agents. Battle-tested across 134 sessions with 10 agent roles.

Short-term (markdown files, always loaded) + Long-term (SQLite + OpenAI embeddings, searched on-demand).

Cerebro Hosted (managed memory) — same two-tier memory, but the long-term store is hosted and shared across machines and agents. No SQLite file to sync, no embeddings key to manage. Join the waitlist →

Install

pip install agent-cerebro

Zero required dependencies. SQLite is Python stdlib.

Optional semantic search:

pip install agent-cerebro[embeddings]
export OPENAI_API_KEY="sk-..."

Quick Start

CLI

# Initialize
cerebro init

# Store a memory (auto-dedup via cosine similarity >0.92)
cerebro store coder gotchas "kamal app exec spawns new container, use docker exec"
cerebro store social exhausted_stories "blue-green deploy order loss" --tags deploy,sqlite

# Search (semantic + keyword fallback)
cerebro search coder gotchas "kamal file not found"
cerebro search coder gotchas "deploy issue" --tag critical
cerebro search coder gotchas "deploy issue" --show-id

# Correct stale memories explicitly; history is preserved
cerebro invalidate 42 --reason "Kamal behavior changed in v2"
cerebro supersede 57 "Use docker exec for live-container queries" --reason "Old command spawned a new container"
cerebro supersede 61 "Current deployment rule" --tags deploy,current

# List categories
cerebro list coder

# Timeline — chronological view of all memories
cerebro timeline coder
cerebro timeline coder --last 7d
cerebro timeline coder --last 2w --category gotchas
cerebro timeline coder --show-id
cerebro timeline coder --include-invalidated --show-id

# Export — dump all memories for a role
cerebro export coder --format md > coder_memories.md
cerebro export coder --format json > coder_memories.json
cerebro export coder --format json --category gotchas
cerebro export coder --format json --include-invalidated > coder_audit.json

# Lossless backup — all roles, embeddings, and lifecycle history, offline
cerebro backup memory-backup.sqlite3
cerebro backup memory-backup.sqlite3 --db /path/to/memory.sqlite3
# Open the snapshot directly, including on another machine
cerebro search coder gotchas "query" --db memory-backup.sqlite3

# Stats — storage metrics and category breakdown
cerebro stats
cerebro stats coder

# Garbage collection — find and remove near-duplicates
cerebro gc coder --dry-run
cerebro gc coder --apply
cerebro gc coder --threshold 0.85 --category gotchas

# Check health
cerebro check --all

Python API

For a lossless long-term database snapshot:

from agentrecall import backup_database

backup_database("memory-backup.sqlite3", db_path="/path/to/memory.sqlite3")

backup captures committed data through SQLite's online backup API, including uncheckpointed WAL writes, every role, stable IDs, embeddings, tags, and invalidated or superseded history. It requires no API key and leaves the source schema unchanged. The destination must be a new file in an existing directory; existing files and symlinks are never overwritten. The snapshot is checked before publication and created with owner-only permissions (0600 on POSIX). A missing or invalid source fails instead of creating an empty database. CLI failures exit 2.

Use --db memory-backup.sqlite3 to read or continue using the snapshot, or copy it to a new memory home's memory.sqlite3 while no processes use that destination. Keep the original until you have verified the copy. This backs up long-term SQLite memory only; copy short-term markdown files separately. Markdown/JSON export remains a readable view and does not contain embeddings. The backup is unencrypted, so protect it like the source database.

from agentrecall import (
    MemoryExport,
    MemoryGC,
    MemoryLifecycle,
    MemorySearch,
    MemoryStats,
    MemoryStore,
    MemoryTimeline,
)

# Store
store = MemoryStore()
entry = store.store(
    "coder", "gotchas", "kamal spawns new container", tags=["kamal", "docker"]
)
another_entry = store.store(
    "coder", "gotchas", "use kamal app exec for live queries", tags=["kamal"]
)

# Search (with optional tag filter)
search = MemorySearch()
results = search.search("coder", "gotchas", "kamal file not found")
results = search.search("coder", "gotchas", "deploy issue", tag="critical")
# search() remains list[str]; search_records() adds stable IDs and metadata
records = search.search_records("coder", "gotchas", "deploy issue")

# Explicit lifecycle changes preserve history
lifecycle = MemoryLifecycle()
lifecycle.invalidate(entry["id"], "Kamal behavior changed in v2")
transition = lifecycle.supersede(
    another_entry["id"],
    "Use docker exec for live-container queries",
    reason="Old command spawned a new container",
)
# → {old_id, new_id, replacement}

# Timeline
timeline = MemoryTimeline()
entries = timeline.timeline("coder", last="7d")
audit_entries = timeline.timeline("coder", include_invalidated=True)

# Export
export = MemoryExport()
markdown = export.export("coder", fmt="md")
json_str = export.export("coder", fmt="json", category="gotchas")
audit_json = export.export("coder", fmt="json", include_invalidated=True)

# Stats
stats = MemoryStats()
metrics = stats.stats(role="coder")
# → {total_entries, total_with_embeddings, embedding_coverage_pct, db_size_bytes, ...}

# Garbage collection
gc = MemoryGC()
result = gc.gc("coder", dry_run=True)
# → {found: 3, removed: 0, duplicates: [...]}
result = gc.gc("coder", dry_run=False)  # actually delete

How It Works

Two-Tier Design

Short-term (memory/<role>.md)Long-term (SQLite + embeddings)
Active learnings, mistakes, feedbackGrowing lists (exhausted topics, defect patterns)
Max 80 lines, pruned regularlyAuditable history; invalidated entries hidden by default
Read in full at session startSearched on-demand per query

Semantic Dedup

Every store call embeds the text via OpenAI text-embedding-3-small and checks cosine similarity against active entries in the same role/category. Similarity > 0.92 blocks the store (raises DuplicateError); it does not silently replace either entry.

Without an API key, falls back to exact text matching.

Memory Lifecycle

Search with --show-id to address a stable entry. invalidate soft-invalidates a known-stale belief. supersede inserts a corrected entry in the same role/category and links the invalidated original to it in one transaction. Omitting --tags on supersede preserves the original tags; supplying it replaces them.

Normal search, timeline, export, dedup, and active counts ignore invalidated entries. Use timeline --include-invalidated or export --include-invalidated for an audit view with timestamps, reasons, and superseded_by linkage. Cerebro never interprets a duplicate write as a truth change: two similar memories can both be valid, so supersession is always explicit.

Opening an existing 0.4.x SQLite database automatically adds the lifecycle columns in place. Existing rows and IDs are preserved; no manual migration command is needed.

  1. Embed the query
  2. Compute cosine similarity against all active entries with embeddings
  3. Return entries above threshold (0.75), sorted by similarity
  4. Append keyword matches from entries without embeddings (>=50% keyword match), so memories saved during an outage remain discoverable after recovery
  5. If no embedding matches, or query embeddings are unavailable: keyword-only search across all candidates. If all candidates lack embeddings, skip the API call entirely
  6. Optional --tag filter narrows results to entries with a specific tag
  7. Optional --limit N caps combined output, with semantic matches first (keeps agent context tight)

Garbage Collection

cerebro gc finds near-duplicate entries within each role/category pair:

  • With embeddings: cosine similarity >= threshold (default 0.92)
  • Without embeddings: exact text match (case-insensitive)
  • Older entry (lower ID) is kept; newer duplicate is removed
  • --dry-run (default) reports without deleting
  • --apply actually removes duplicates

Graceful Degradation

Works fully offline without an OpenAI API key:

  • Store: exact text dedup (case-insensitive)
  • Search: keyword matching (>=50% of query words must appear)
  • GC: exact text match dedup only

Network Resilience

Embedding calls are wrapped in a retry loop with exponential backoff + jitter. Transient failures (timeouts, dropped connections, HTTP 429/5xx) are retried; HTTP 429 honors the Retry-After header. After exhausting retries — or on a non-retryable error (e.g. 401) — store/search print a warning and fall back to keyword/exact-match instead of crashing mid-session. Auth/4xx errors are not retried (no point burning attempts on a bad key).

Tune via CEREBRO_EMBED_MAX_RETRIES (default 3) and CEREBRO_EMBED_TIMEOUT (seconds, default 30).

Agent Skills

Copy skill/agent-recall/ into your project's skills directory for use with Claude Code, Codex, Cursor, Copilot, Cline, or Goose.

cp -r skill/agent-recall/ .claude/skills/agent-recall/

Configuration

Environment variables:

VariableDefaultDescription
AGENT_CEREBRO_HOME~/.agent-cerebroMemory storage directory
OPENAI_API_KEY(none)OpenAI API key for embeddings
UT_OPENAI_API_KEY(none)Preferred over OPENAI_API_KEY
CEREBRO_EMBED_MAX_RETRIES3Retries on transient embedding-API failures
CEREBRO_EMBED_TIMEOUT30Per-request embedding timeout (seconds)

CLI Reference

cerebro store <role> <category> "text" [--tags t1,t2] [--db path]
cerebro search <role> <category> "query" [--tag tagname] [--limit N] [--show-id] [--db path]
cerebro invalidate <entry_id> --reason "why it is stale" [--db path]
cerebro supersede <entry_id> "replacement" [--tags t1,t2] [--reason "why"] [--db path]
cerebro list <role> [--db path]
cerebro timeline <role> [--last 7d] [--category cat] [--limit N] [--show-id] [--include-invalidated] [--db path]
cerebro export <role> [--format md|json] [--category cat] [--include-invalidated] [--db path]
cerebro backup <new-file> [--db source-path]
cerebro stats [role] [--db path]
cerebro gc <role> [--dry-run] [--apply] [--threshold 0.92] [--category cat] [--db path]
cerebro check [--fix] [--long-term] [--all] [--dir path] [--db path]
cerebro init [--dir path]
cerebro migrate [--dry-run] [--rebuild] [--dir path] [--db path]

agentrecall and agentmemory also work as CLI aliases.

Exit codes: 0 = success/found, 1 = not-found/validation-fail, 2 = input error.

Migration from JSONL

If you have existing JSONL memory files:

cerebro migrate --dir /path/to/memory/
cerebro migrate --rebuild  # Re-embed entries missing embeddings

Part of the Ultrathink Agent Suite:

  • Agent Architect Kit — Multi-agent starter kit that uses Cerebro for cross-session memory
  • Agent Orchestra — Task queue + orchestration CLI for spawning and managing agents
  • AgentBrush — Image editing toolkit for AI agents

Built by an AI-run dev shop. Read how →

License

MIT

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 4

Native requirements
3 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
openai
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.9",
  "evaluation": "NOT_EVALUATED"
}
openai>=1.0; extra == "all"runtime
pytest-cov
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.9",
  "evaluation": "NOT_EVALUATED"
}
pytest-cov; extra == "dev"runtime
pytest
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.9",
  "evaluation": "NOT_EVALUATED"
}
pytest>=7.0; extra == "dev"runtime
openai
Environment
{
  "extras": "",
  "marker": "extra == \"embeddings\"",
  "requires_python": ">=3.9",
  "evaluation": "NOT_EVALUATED"
}
openai>=1.0; extra == "embeddings"runtime

Distribution files

2 collected
agent_cerebro-0.6.1-py3-none-any.whl

bdist_wheel · 35.79 KB · Python py3

Source file
agent_cerebro-0.6.1.tar.gz

sdist · 48.38 KB · Python source

Source file

Repository

PENDING
ultrathink-art/agent-cerebro

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 21:37 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:bbf48a2f5a037736e43f35aa960099e4d4b07c960a1b1c06bbc9328caadbbc52

Other collected versions

View all collected versions →