Skip to main content

OLAP-based memory engine for AI agents

Project description

EpisodicDB

An OLAP-based memory engine for AI agents.

Existing agent memory systems (Mem0, Zep, Letta) are designed as search systems. EpisodicDB treats agent memory as an analytics problem — aggregation, time-series patterns, causal tracing, temporal facts, and vector similarity all in a single query engine.

-- "Which tools failed most this week?"
SELECT tool_name, COUNT(*) AS failures
FROM tool_calls
WHERE outcome = 'failure'
  AND called_at >= NOW() - INTERVAL '7 days'
GROUP BY tool_name
ORDER BY failures DESC;

-- "Find past episodes similar to this context that succeeded"
SELECT *, array_cosine_distance(context_embedding, ?) AS dist
FROM episodes
WHERE status = 'success'
ORDER BY dist ASC
LIMIT 5;

The Problem

Query type Example Vector search?
Similarity "Seen a similar error before?" Yes
Aggregation "How many tool failures this week?" No
Time-series "Do failures spike in the afternoon?" No
Causal trace "What tool ran right before failures?" No
Comparison "Worse than last week?" No
Absence "Tools that never succeeded?" No
Temporal "What was the user's timezone last Tuesday?" No

EpisodicDB answers all of them. Vector similarity is just another SQL operator.

Architecture

EpisodicDB
├── WriterMixin      record_episode / record_tool_call / record_decision / record_fact
├── AnalyticsMixin   6 analytics methods + vector similarity
└── TemporalMixin    facts_as_of / fact_history

Engine: DuckDB (OLAP) + VSS extension (HNSW vector index)
Schema: episodes + tool_calls + decisions + facts

Install

pip install episodicdb

Quick Start

Python SDK

from episodicdb import EpisodicDB

with EpisodicDB(agent_id="my-agent") as db:
    # Record what happened
    ep_id = db.record_episode(
        status="failure",
        task_type="file_edit",
        context={"file": "auth.py", "error": "permission denied"},
    )
    db.record_tool_call(ep_id, "Edit", "failure",
                        duration_ms=120, error_message="permission denied")
    db.record_tool_call(ep_id, "Bash", "success", duration_ms=50)

    # Record temporal facts (auto-supersedes previous values)
    db.record_fact("user_timezone", "Asia/Seoul", episode_id=ep_id)
    db.record_fact("user_timezone", "America/New_York")  # closes previous

    # Analyze patterns
    print(db.top_failing_tools(days=7))
    # [{"tool_name": "Edit", "failures": 5}, ...]

    print(db.before_failure_sequence("Edit"))
    # [{"prev_tool": "Bash", "count": 4}, ...]

    print(db.compare_periods("failure_rate", days=7))
    # {"period_a": 0.32, "period_b": 0.18, "delta": 0.14}

    # Time-travel query
    from datetime import datetime
    print(db.facts_as_of(datetime(2025, 3, 15)))
    # [{"key": "user_timezone", "value": "Asia/Seoul", ...}]

MCP Server (Claude, OpenAI Agents SDK)

EpisodicDB ships an MCP server with 12 tools over stdio.

episodicdb-mcp --agent-id my-agent
episodicdb-mcp --agent-id my-agent --db ./memory.db

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "episodicdb": {
      "command": "episodicdb-mcp",
      "args": ["--agent-id", "my-agent"]
    }
  }
}

Claude Code (.mcp.json):

{
  "mcpServers": {
    "episodicdb": {
      "command": "episodicdb-mcp",
      "args": ["--agent-id", "my-agent"]
    }
  }
}

OpenAI Agents SDK:

from agents import Agent
from agents.mcp import MCPServerStdio

agent = Agent(
    name="my-agent",
    instructions="You have access to episodic memory.",
    mcp_servers=[MCPServerStdio(
        command="episodicdb-mcp",
        args=["--agent-id", "my-agent"],
    )],
)

API

Writer

db.record_episode(status, task_type=None, context=None,
                  embedding=None, tags=None,
                  started_at=None, ended_at=None) -> str  # episode UUID

db.record_tool_call(episode_id, tool_name, outcome,
                    parameters=None, result=None,
                    duration_ms=None, error_message=None) -> str

db.record_decision(episode_id, rationale,
                   decision_type=None, alternatives=None,
                   outcome=None) -> str

db.record_fact(key, value, episode_id=None,
               valid_from=None) -> str  # auto-supersedes previous

Analytics

Method Description
top_failing_tools(days, limit) Most-failed tools in the last N days
hourly_failure_rate(days) Failure count by hour of day
before_failure_sequence(tool_name, lookback) Tools that precede failures
compare_periods(metric, days) Period-over-period comparison
never_succeeded_tools() Tools with zero successful calls
similar_episodes(embedding, status, limit) Vector similarity + SQL filter

Temporal Facts

Facts are key-value pairs with automatic temporal validity. Recording a new value for the same key closes the previous one.

db.record_fact("preferred_model", "gpt-4o")
# later...
db.record_fact("preferred_model", "claude-sonnet")  # supersedes gpt-4o

db.facts_as_of(some_datetime)   # point-in-time snapshot
db.fact_history("preferred_model")  # full change log

Persistence

EpisodicDB(agent_id="my-agent")                    # ~/.episodicdb/my-agent.db
EpisodicDB(agent_id="my-agent", path="./x.db")    # explicit path
EpisodicDB(agent_id="my-agent", path=":memory:")  # in-memory (testing)

Embeddings

Built-in helpers for popular providers (lazy imports, no hard dependencies):

pip install episodicdb[openai]   # OpenAI
pip install episodicdb[voyage]   # Voyage AI
pip install episodicdb[ollama]   # Ollama (local)
pip install episodicdb[all]      # all providers
from episodicdb import embeddings

# OpenAI
vec = embeddings.openai("what the agent was doing")

# Voyage AI
vec = embeddings.voyage("what the agent was doing")

# Local Ollama
vec = embeddings.ollama("what the agent was doing")

db.record_episode(status="success", embedding=vec)
db.similar_episodes(vec, status="failure", limit=5)

Or bring your own:

db.record_episode(status="success", embedding=your_1536_dim_list)

Development

git clone https://github.com/KsPsD/EpisodicDB
cd EpisodicDB
pip install -e ".[dev]"
pytest

Stack

  • DuckDB — embedded OLAP engine
  • DuckDB VSS — HNSW vector index
  • MCP — Model Context Protocol server
  • Python 3.11+

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

episodicdb-0.1.1.tar.gz (15.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

episodicdb-0.1.1-py3-none-any.whl (14.5 kB view details)

Uploaded Python 3

File details

Details for the file episodicdb-0.1.1.tar.gz.

File metadata

  • Download URL: episodicdb-0.1.1.tar.gz
  • Upload date:
  • Size: 15.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for episodicdb-0.1.1.tar.gz
Algorithm Hash digest
SHA256 136c6a008bd992fd79462e8cb4e6f1655f28b63fc4c44257523963e72ea69bd5
MD5 f8aca36448babc2e74aef39325d60264
BLAKE2b-256 3006abb60a4ffbc301a344166b9f18404969a265de49fd337d94ba0e07fd359b

See more details on using hashes here.

Provenance

The following attestation bundles were made for episodicdb-0.1.1.tar.gz:

Publisher: publish.yml on KsPsD/EpisodicDB

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file episodicdb-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: episodicdb-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 14.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for episodicdb-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 662dd2c8f4d8afc60eb23c2647675dd916d8200f1555f6f398484c089cc9d7d8
MD5 737b376e410145aa6ba30b10ca4824e7
BLAKE2b-256 f9de5395084638f80eea308211a4c56c7d7088aa90e66e1197816a0f7eedfc10

See more details on using hashes here.

Provenance

The following attestation bundles were made for episodicdb-0.1.1-py3-none-any.whl:

Publisher: publish.yml on KsPsD/EpisodicDB

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page