⚠️ Experimental research project. Karta is a novel, actively-evolving approach to AI agent memory. APIs, data formats, and benchmark numbers will change. Not production-ready. We're building this in the open because we think agent memory is one of the most important unsolved problems in AI — and our goal is to build the best AI memory system.
An agentic memory system that thinks, not just stores.
Karta is a novel approach that combines structured knowledge graphs with active background reasoning to build memory that organizes itself at write time, links associatively, evolves retroactively, and periodically "dreams" to surface deductions, patterns, gaps, and contradictions that no retrieval system could find because they were never explicitly stored.
- Self-organizing note graph — notes are enriched with LLM-generated context, semantically linked, and retroactively evolved when new information arrives
- Dream engine — 5 types of background inference: deduction, induction, abduction, consolidation, contradiction detection
- First-class contradictions — structured
Contradictionobjects with lifecycle (open → resolved/ignored), per-entity and per-scope queries, source-note protection from forgetting - Structured output with reasoning — forces chain-of-thought before answers, enabling reliable abstention and contradiction flagging
- Cross-encoder reranking — Jina AI reranker for precise relevance scoring and intelligent abstention
- Temporal awareness — exponential decay scoring, foresight signals with validity windows
- Provenance tracking — every note tagged as FACT or INFERRED with confidence scores
- Forgetting engine —
Karta::run_forgetting()/Karta::preview_forgetting(): archives stale low-activation notes using access-based exponential decay scoring with protected notes (profiles, episodes); lifecycle: Active → Deprecated → Superseded → Archived - Procedural memory —
RuleEnginewith safeProceduralRuleDSL (query/session/contradiction conditions → prompt/retrieval actions only), fire-count tracking, note-sourced rules protected from forgetting - Evidence packets —
AskResultexposes an optionalEvidencePacketslot for per-channel rank traces, fired rule IDs, contradiction IDs, and human-readable "why retrieved" explanations; current read paths returnevidence: Noneuntil ACTIVATE populates it - Deterministic extractors —
Extractortrait with Markdown (headings, links, code fences), JSON (recursive paths), YAML (key-value), and Cargo.toml (metadata, dependency edges) extractors that run before LLM extraction - Embedded by default — LanceDB + SQLite, zero infrastructure.
cargo add kartaand go.
use karta_core::{Karta, config::KartaConfig};
#[tokio::main]
async fn main() {
let config = KartaConfig::default();
let karta = Karta::with_defaults(config).await.unwrap();
// Add memories
karta.add_note("Sarah prefers Slack notifications over email").await.unwrap();
karta.add_note("Brightline requires all integrations on the approved vendor list").await.unwrap();
// Query with synthesis
let result = karta.ask("What should I know about Sarah's notification preferences?", 5).await.unwrap();
println!("{}", result.answer);
// Run background reasoning
let dream_run = karta.run_dreaming("workspace", "default").await.unwrap();
println!("Dreams: {} attempted, {} written", dream_run.dreams_attempted, dream_run.dreams_written);
}Write Path: content → LLM attributes → embed → ANN search → link → evolve → store
Read Path: query → embed → ANN → rerank → multi-hop traverse → synthesize
Dream Path: cluster notes → deduction/induction/abduction/consolidation/contradiction → persist
| Layer | Default | Production Options |
|---|---|---|
| Vector + metadata | LanceDB (embedded) | pgvector, Qdrant |
| Graph + state | SQLite (WAL mode) | Postgres, Dolt |
| Provider | Status |
|---|---|
| OpenAI / Azure OpenAI | Built |
| Any OpenAI-compatible (Ollama, vLLM, Groq, Together) | Built |
| Anthropic | Planned |
| Provider | Status |
|---|---|
| Jina AI (cross-encoder) | Built |
| LLM-based (fallback) | Built |
| Noop (disabled) | Built |
cp .env.example .env
# Fill in your LLM credentials# Per-operation model flexibility
[llm.default]
provider = "openai"
model = "gpt-4o-mini"
[llm.dream.abduction]
model = "claude-sonnet-4-6"
# Reranker
# Runtime provider via env: KARTA_RERANKER_PROVIDER=auto|jina|fastembed|llm|noop
# FastEmbed runs locally when built with --features fastembed-reranker, but the
# first use may download model / ONNX Runtime artifacts unless they are already cached.
# Pre-cache those assets in your image/host if you need fully offline startup.
# CUDA attempt + CPU fallback requires --features fastembed-reranker-cuda.
# Recalibrate abstention_threshold when switching providers; Jina and FastEmbed scores differ.
[reranker]
enabled = true
abstention_threshold = 0.1BEAM 100K — 20 conversations, 400 questions, single run, arithmetic mean of per-question rubric scores with the BEAM nugget LLM judge:
| Ability | P1 (2026-04-14) |
|---|---|
| Preference Following | 92% |
| Contradiction Resolution | 74% |
| Temporal Reasoning | 71% |
| Instruction Following | 69% |
| Summarization | 66% |
| Multi-session Reasoning | 65% |
| Abstention | 62% |
| Information Extraction | 59% |
| Knowledge Update | 43% |
| Event Ordering | 35% |
| Overall | 61.6% |
Up from a 53.0% P0 baseline (+8.6pp). P1 fixes: expand-then-rerank, killing the synthesis-level abstention gate, and recency scoring against source note timestamps instead of dream write time.
Active development targeting 90%+ via atomic fact decomposition,
episode-aware retrieval, and improved write-time organization. See
benchmarks/beam-100k.md for the full
experiment log, failure catalogue, and per-ability history.
karta/
├── crates/
│ ├── karta-core/ # Core engine (Rust)
│ │ ├── src/
│ │ │ ├── note.rs # MemoryNote, Provenance, NoteStatus
│ │ │ ├── write.rs # Write path (index, link, evolve)
│ │ │ ├── read.rs # Search, multi-hop traversal, synthesis
│ │ │ ├── rerank.rs # Cross-encoder reranking + abstention
│ │ │ ├── dream/ # Dream engine (5 inference types)
│ │ │ ├── store/ # LanceDB + SQLite implementations
│ │ │ └── llm/ # Provider trait + OpenAI + structured output
│ │ └── tests/ # Eval suites + BEAM/LOCOMO/LongMem harnesses
│ └── karta-cli/ # CLI for local automation and agent integrations
├── data/ # Benchmark preprocessing scripts
├── Cargo.toml
└── README.md
# Install the CLI
./install.sh
# Use the CLI (requires LLM credentials for commands that write/search/ask)
karta --help
cargo run -p karta-cli -- --help
cargo run -p karta-cli -- --json add-note --content "Sarah prefers Slack notifications"
cargo run -p karta-cli -- --json search --query "Sarah notification preferences" --top-k 5
# Install Karta into AI clients
# claude: skill + global CLAUDE.md + project UserPromptSubmit hook
# codex: skill + AGENTS.md + project hooks.json/config.toml
# gemini: skill + GEMINI.md + project BeforeAgent hook
# pi: skill + global pi extension
# hermes: skill (Hermes exposes skills as the integration surface)
karta install --platform claude # also: codex, gemini, hermes, pi
karta uninstall --platform claude
# Run tests (mock LLM, no API keys needed)
cargo test
# Run synthetic memory evals (zero API keys, deterministic)
cargo test -p karta-core --test synthetic_memory_eval
# Run real eval (requires .env credentials)
cargo test -p karta-core --features eval-harnesses --test real_eval -- --ignored --nocapture
# Run BEAM benchmark
BEAM_DATASET_PATH=data/beam-100k.json cargo test -p karta-core --features eval-harnesses --test beam_100k beam_100k_single -- --ignored --nocaptureCI gates on every PR: cargo fmt --all -- --check, cargo clippy --workspace --all-targets -- -D warnings, and cargo nextest run --workspace --no-fail-fast.
This repository includes a pi extension at .pi/extensions/karta.ts.
./install.sh installs or updates it globally at ~/.pi/agent/extensions/karta.ts.
When loaded, the extension registers Karta memory tools backed by the CLI:
karta_add_note— store durable memorieskarta_search— semantic memory searchkarta_ask— synthesized Q&A over memorykarta_get_note— retrieve a note by IDkarta_note_count— count stored noteskarta_health— check embedded store healthkarta_dream— run background reasoning
By default the extension uses KARTA_BIN when set, otherwise an installed karta
on PATH, otherwise it falls back to cargo run -q -p karta-cli -- --json ...
so it still works directly from a checkout.
./install.sh
piUseful environment variables:
export KARTA_DATA_DIR=.karta # storage directory used by the CLI
export KARTA_LANCE_URI=.karta/lance # optional LanceDB URI override
export KARTA_TIMEOUT_MS=120000 # extension command timeoutThe pi extension also performs automatic memory recall before each agent turn. It builds a search query from the user prompt, cwd, and exact-match tokens such as paths, symbols, constants, issue IDs, and code spans, then injects a compact, provenance-rich memory message. Configure it with:
export KARTA_AUTO_CONTEXT=0 # disable automatic recall
export KARTA_AUTO_CONTEXT_TOP_K=5 # retrieved memories, 1-20
export KARTA_AUTO_CONTEXT_MAX_CHARS=4000 # injected context budget
export KARTA_AUTO_CONTEXT_DISPLAY=1 # show injected memory messages in the TUIMemory policy instructions for pi live in .pi/APPEND_SYSTEM.md. Automatic
recall is intentionally read-only; writes still happen through explicit memory
tools so durable memory promotion remains conservative.
benchmarks/— benchmark results, reproduction commands, experiment logsdocs/landscape.md— AI memory systems landscape researchdocs/retrieval-plan.md— open retrieval experiment backlogCONTRIBUTING.md— how to contributeCHANGELOG.md— release notes
MIT