episodicdb 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,36 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.pyo
5
+ *.pyd
6
+ .Python
7
+ *.so
8
+ *.egg
9
+ *.egg-info/
10
+ dist/
11
+ build/
12
+ .eggs/
13
+
14
+ # Virtual environments
15
+ .venv/
16
+ venv/
17
+ env/
18
+
19
+ # Testing
20
+ .pytest_cache/
21
+ .coverage
22
+ htmlcov/
23
+
24
+ # EpisodicDB runtime
25
+ ~/.episodicdb/
26
+
27
+ # Internal / agent config
28
+ docs/superpowers/
29
+ CLAUDE.md
30
+
31
+ # IDE
32
+ .idea/
33
+ .vscode/
34
+ *.swp
35
+ *.swo
36
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 KsPsD
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,260 @@
1
+ Metadata-Version: 2.4
2
+ Name: episodicdb
3
+ Version: 0.1.0
4
+ Summary: OLAP-based memory engine for AI agents
5
+ Project-URL: Homepage, https://github.com/KsPsD/EpisodicDB
6
+ Project-URL: Repository, https://github.com/KsPsD/EpisodicDB
7
+ Project-URL: Issues, https://github.com/KsPsD/EpisodicDB/issues
8
+ Author: KsPsD
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agents,ai,duckdb,mcp,memory,olap,vector
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Database
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Requires-Python: >=3.11
22
+ Requires-Dist: duckdb>=1.2.0
23
+ Requires-Dist: mcp[cli]>=1.0.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest>=8.0; extra == 'dev'
26
+ Description-Content-Type: text/markdown
27
+
28
+ # EpisodicDB
29
+
30
+ **An OLAP-based memory engine for AI agents.**
31
+
32
+ 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.
33
+
34
+ ```sql
35
+ -- "Which tools failed most this week?"
36
+ SELECT tool_name, COUNT(*) AS failures
37
+ FROM tool_calls
38
+ WHERE outcome = 'failure'
39
+ AND called_at >= NOW() - INTERVAL '7 days'
40
+ GROUP BY tool_name
41
+ ORDER BY failures DESC;
42
+
43
+ -- "Find past episodes similar to this context that succeeded"
44
+ SELECT *, array_cosine_distance(context_embedding, ?) AS dist
45
+ FROM episodes
46
+ WHERE status = 'success'
47
+ ORDER BY dist ASC
48
+ LIMIT 5;
49
+ ```
50
+
51
+ ## The Problem
52
+
53
+ | Query type | Example | Vector search? |
54
+ |------------|---------|----------------|
55
+ | Similarity | "Seen a similar error before?" | Yes |
56
+ | Aggregation | "How many tool failures this week?" | No |
57
+ | Time-series | "Do failures spike in the afternoon?" | No |
58
+ | Causal trace | "What tool ran right before failures?" | No |
59
+ | Comparison | "Worse than last week?" | No |
60
+ | Absence | "Tools that never succeeded?" | No |
61
+ | Temporal | "What was the user's timezone last Tuesday?" | No |
62
+
63
+ EpisodicDB answers all of them. Vector similarity is just another SQL operator.
64
+
65
+ ## Architecture
66
+
67
+ ```
68
+ EpisodicDB
69
+ ├── WriterMixin record_episode / record_tool_call / record_decision / record_fact
70
+ ├── AnalyticsMixin 6 analytics methods + vector similarity
71
+ └── TemporalMixin facts_as_of / fact_history
72
+
73
+ Engine: DuckDB (OLAP) + VSS extension (HNSW vector index)
74
+ Schema: episodes + tool_calls + decisions + facts
75
+ ```
76
+
77
+ ## Install
78
+
79
+ ```bash
80
+ pip install episodicdb
81
+ ```
82
+
83
+ ## Quick Start
84
+
85
+ ### Python SDK
86
+
87
+ ```python
88
+ from episodicdb import EpisodicDB
89
+
90
+ with EpisodicDB(agent_id="my-agent") as db:
91
+ # Record what happened
92
+ ep_id = db.record_episode(
93
+ status="failure",
94
+ task_type="file_edit",
95
+ context={"file": "auth.py", "error": "permission denied"},
96
+ )
97
+ db.record_tool_call(ep_id, "Edit", "failure",
98
+ duration_ms=120, error_message="permission denied")
99
+ db.record_tool_call(ep_id, "Bash", "success", duration_ms=50)
100
+
101
+ # Record temporal facts (auto-supersedes previous values)
102
+ db.record_fact("user_timezone", "Asia/Seoul", episode_id=ep_id)
103
+ db.record_fact("user_timezone", "America/New_York") # closes previous
104
+
105
+ # Analyze patterns
106
+ print(db.top_failing_tools(days=7))
107
+ # [{"tool_name": "Edit", "failures": 5}, ...]
108
+
109
+ print(db.before_failure_sequence("Edit"))
110
+ # [{"prev_tool": "Bash", "count": 4}, ...]
111
+
112
+ print(db.compare_periods("failure_rate", days=7))
113
+ # {"period_a": 0.32, "period_b": 0.18, "delta": 0.14}
114
+
115
+ # Time-travel query
116
+ from datetime import datetime
117
+ print(db.facts_as_of(datetime(2025, 3, 15)))
118
+ # [{"key": "user_timezone", "value": "Asia/Seoul", ...}]
119
+ ```
120
+
121
+ ### MCP Server (Claude, OpenAI Agents SDK)
122
+
123
+ EpisodicDB ships an MCP server with 12 tools over stdio.
124
+
125
+ ```bash
126
+ episodicdb-mcp --agent-id my-agent
127
+ episodicdb-mcp --agent-id my-agent --db ./memory.db
128
+ ```
129
+
130
+ **Claude Desktop** (`claude_desktop_config.json`):
131
+
132
+ ```json
133
+ {
134
+ "mcpServers": {
135
+ "episodicdb": {
136
+ "command": "episodicdb-mcp",
137
+ "args": ["--agent-id", "my-agent"]
138
+ }
139
+ }
140
+ }
141
+ ```
142
+
143
+ **Claude Code** (`.mcp.json`):
144
+
145
+ ```json
146
+ {
147
+ "mcpServers": {
148
+ "episodicdb": {
149
+ "command": "episodicdb-mcp",
150
+ "args": ["--agent-id", "my-agent"]
151
+ }
152
+ }
153
+ }
154
+ ```
155
+
156
+ **OpenAI Agents SDK**:
157
+
158
+ ```python
159
+ from agents import Agent
160
+ from agents.mcp import MCPServerStdio
161
+
162
+ agent = Agent(
163
+ name="my-agent",
164
+ instructions="You have access to episodic memory.",
165
+ mcp_servers=[MCPServerStdio(
166
+ command="episodicdb-mcp",
167
+ args=["--agent-id", "my-agent"],
168
+ )],
169
+ )
170
+ ```
171
+
172
+ ## API
173
+
174
+ ### Writer
175
+
176
+ ```python
177
+ db.record_episode(status, task_type=None, context=None,
178
+ embedding=None, tags=None,
179
+ started_at=None, ended_at=None) -> str # episode UUID
180
+
181
+ db.record_tool_call(episode_id, tool_name, outcome,
182
+ parameters=None, result=None,
183
+ duration_ms=None, error_message=None) -> str
184
+
185
+ db.record_decision(episode_id, rationale,
186
+ decision_type=None, alternatives=None,
187
+ outcome=None) -> str
188
+
189
+ db.record_fact(key, value, episode_id=None,
190
+ valid_from=None) -> str # auto-supersedes previous
191
+ ```
192
+
193
+ ### Analytics
194
+
195
+ | Method | Description |
196
+ |--------|-------------|
197
+ | `top_failing_tools(days, limit)` | Most-failed tools in the last N days |
198
+ | `hourly_failure_rate(days)` | Failure count by hour of day |
199
+ | `before_failure_sequence(tool_name, lookback)` | Tools that precede failures |
200
+ | `compare_periods(metric, days)` | Period-over-period comparison |
201
+ | `never_succeeded_tools()` | Tools with zero successful calls |
202
+ | `similar_episodes(embedding, status, limit)` | Vector similarity + SQL filter |
203
+
204
+ ### Temporal Facts
205
+
206
+ Facts are key-value pairs with automatic temporal validity. Recording a new value for the same key closes the previous one.
207
+
208
+ ```python
209
+ db.record_fact("preferred_model", "gpt-4o")
210
+ # later...
211
+ db.record_fact("preferred_model", "claude-sonnet") # supersedes gpt-4o
212
+
213
+ db.facts_as_of(some_datetime) # point-in-time snapshot
214
+ db.fact_history("preferred_model") # full change log
215
+ ```
216
+
217
+ ### Persistence
218
+
219
+ ```python
220
+ EpisodicDB(agent_id="my-agent") # ~/.episodicdb/my-agent.db
221
+ EpisodicDB(agent_id="my-agent", path="./x.db") # explicit path
222
+ EpisodicDB(agent_id="my-agent", path=":memory:") # in-memory (testing)
223
+ ```
224
+
225
+ ### Embeddings
226
+
227
+ EpisodicDB does not generate embeddings. Pass them in:
228
+
229
+ ```python
230
+ import openai
231
+
232
+ response = openai.embeddings.create(
233
+ model="text-embedding-3-small",
234
+ input="what the agent was doing"
235
+ )
236
+ embedding = response.data[0].embedding # 1536 dims
237
+
238
+ db.record_episode(status="success", embedding=embedding)
239
+ db.similar_episodes(embedding, status="failure", limit=5)
240
+ ```
241
+
242
+ ## Development
243
+
244
+ ```bash
245
+ git clone https://github.com/KsPsD/EpisodicDB
246
+ cd EpisodicDB
247
+ pip install -e ".[dev]"
248
+ pytest
249
+ ```
250
+
251
+ ## Stack
252
+
253
+ - [DuckDB](https://duckdb.org/) — embedded OLAP engine
254
+ - [DuckDB VSS](https://duckdb.org/docs/extensions/vss) — HNSW vector index
255
+ - [MCP](https://modelcontextprotocol.io/) — Model Context Protocol server
256
+ - Python 3.11+
257
+
258
+ ## License
259
+
260
+ MIT
@@ -0,0 +1,233 @@
1
+ # EpisodicDB
2
+
3
+ **An OLAP-based memory engine for AI agents.**
4
+
5
+ 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.
6
+
7
+ ```sql
8
+ -- "Which tools failed most this week?"
9
+ SELECT tool_name, COUNT(*) AS failures
10
+ FROM tool_calls
11
+ WHERE outcome = 'failure'
12
+ AND called_at >= NOW() - INTERVAL '7 days'
13
+ GROUP BY tool_name
14
+ ORDER BY failures DESC;
15
+
16
+ -- "Find past episodes similar to this context that succeeded"
17
+ SELECT *, array_cosine_distance(context_embedding, ?) AS dist
18
+ FROM episodes
19
+ WHERE status = 'success'
20
+ ORDER BY dist ASC
21
+ LIMIT 5;
22
+ ```
23
+
24
+ ## The Problem
25
+
26
+ | Query type | Example | Vector search? |
27
+ |------------|---------|----------------|
28
+ | Similarity | "Seen a similar error before?" | Yes |
29
+ | Aggregation | "How many tool failures this week?" | No |
30
+ | Time-series | "Do failures spike in the afternoon?" | No |
31
+ | Causal trace | "What tool ran right before failures?" | No |
32
+ | Comparison | "Worse than last week?" | No |
33
+ | Absence | "Tools that never succeeded?" | No |
34
+ | Temporal | "What was the user's timezone last Tuesday?" | No |
35
+
36
+ EpisodicDB answers all of them. Vector similarity is just another SQL operator.
37
+
38
+ ## Architecture
39
+
40
+ ```
41
+ EpisodicDB
42
+ ├── WriterMixin record_episode / record_tool_call / record_decision / record_fact
43
+ ├── AnalyticsMixin 6 analytics methods + vector similarity
44
+ └── TemporalMixin facts_as_of / fact_history
45
+
46
+ Engine: DuckDB (OLAP) + VSS extension (HNSW vector index)
47
+ Schema: episodes + tool_calls + decisions + facts
48
+ ```
49
+
50
+ ## Install
51
+
52
+ ```bash
53
+ pip install episodicdb
54
+ ```
55
+
56
+ ## Quick Start
57
+
58
+ ### Python SDK
59
+
60
+ ```python
61
+ from episodicdb import EpisodicDB
62
+
63
+ with EpisodicDB(agent_id="my-agent") as db:
64
+ # Record what happened
65
+ ep_id = db.record_episode(
66
+ status="failure",
67
+ task_type="file_edit",
68
+ context={"file": "auth.py", "error": "permission denied"},
69
+ )
70
+ db.record_tool_call(ep_id, "Edit", "failure",
71
+ duration_ms=120, error_message="permission denied")
72
+ db.record_tool_call(ep_id, "Bash", "success", duration_ms=50)
73
+
74
+ # Record temporal facts (auto-supersedes previous values)
75
+ db.record_fact("user_timezone", "Asia/Seoul", episode_id=ep_id)
76
+ db.record_fact("user_timezone", "America/New_York") # closes previous
77
+
78
+ # Analyze patterns
79
+ print(db.top_failing_tools(days=7))
80
+ # [{"tool_name": "Edit", "failures": 5}, ...]
81
+
82
+ print(db.before_failure_sequence("Edit"))
83
+ # [{"prev_tool": "Bash", "count": 4}, ...]
84
+
85
+ print(db.compare_periods("failure_rate", days=7))
86
+ # {"period_a": 0.32, "period_b": 0.18, "delta": 0.14}
87
+
88
+ # Time-travel query
89
+ from datetime import datetime
90
+ print(db.facts_as_of(datetime(2025, 3, 15)))
91
+ # [{"key": "user_timezone", "value": "Asia/Seoul", ...}]
92
+ ```
93
+
94
+ ### MCP Server (Claude, OpenAI Agents SDK)
95
+
96
+ EpisodicDB ships an MCP server with 12 tools over stdio.
97
+
98
+ ```bash
99
+ episodicdb-mcp --agent-id my-agent
100
+ episodicdb-mcp --agent-id my-agent --db ./memory.db
101
+ ```
102
+
103
+ **Claude Desktop** (`claude_desktop_config.json`):
104
+
105
+ ```json
106
+ {
107
+ "mcpServers": {
108
+ "episodicdb": {
109
+ "command": "episodicdb-mcp",
110
+ "args": ["--agent-id", "my-agent"]
111
+ }
112
+ }
113
+ }
114
+ ```
115
+
116
+ **Claude Code** (`.mcp.json`):
117
+
118
+ ```json
119
+ {
120
+ "mcpServers": {
121
+ "episodicdb": {
122
+ "command": "episodicdb-mcp",
123
+ "args": ["--agent-id", "my-agent"]
124
+ }
125
+ }
126
+ }
127
+ ```
128
+
129
+ **OpenAI Agents SDK**:
130
+
131
+ ```python
132
+ from agents import Agent
133
+ from agents.mcp import MCPServerStdio
134
+
135
+ agent = Agent(
136
+ name="my-agent",
137
+ instructions="You have access to episodic memory.",
138
+ mcp_servers=[MCPServerStdio(
139
+ command="episodicdb-mcp",
140
+ args=["--agent-id", "my-agent"],
141
+ )],
142
+ )
143
+ ```
144
+
145
+ ## API
146
+
147
+ ### Writer
148
+
149
+ ```python
150
+ db.record_episode(status, task_type=None, context=None,
151
+ embedding=None, tags=None,
152
+ started_at=None, ended_at=None) -> str # episode UUID
153
+
154
+ db.record_tool_call(episode_id, tool_name, outcome,
155
+ parameters=None, result=None,
156
+ duration_ms=None, error_message=None) -> str
157
+
158
+ db.record_decision(episode_id, rationale,
159
+ decision_type=None, alternatives=None,
160
+ outcome=None) -> str
161
+
162
+ db.record_fact(key, value, episode_id=None,
163
+ valid_from=None) -> str # auto-supersedes previous
164
+ ```
165
+
166
+ ### Analytics
167
+
168
+ | Method | Description |
169
+ |--------|-------------|
170
+ | `top_failing_tools(days, limit)` | Most-failed tools in the last N days |
171
+ | `hourly_failure_rate(days)` | Failure count by hour of day |
172
+ | `before_failure_sequence(tool_name, lookback)` | Tools that precede failures |
173
+ | `compare_periods(metric, days)` | Period-over-period comparison |
174
+ | `never_succeeded_tools()` | Tools with zero successful calls |
175
+ | `similar_episodes(embedding, status, limit)` | Vector similarity + SQL filter |
176
+
177
+ ### Temporal Facts
178
+
179
+ Facts are key-value pairs with automatic temporal validity. Recording a new value for the same key closes the previous one.
180
+
181
+ ```python
182
+ db.record_fact("preferred_model", "gpt-4o")
183
+ # later...
184
+ db.record_fact("preferred_model", "claude-sonnet") # supersedes gpt-4o
185
+
186
+ db.facts_as_of(some_datetime) # point-in-time snapshot
187
+ db.fact_history("preferred_model") # full change log
188
+ ```
189
+
190
+ ### Persistence
191
+
192
+ ```python
193
+ EpisodicDB(agent_id="my-agent") # ~/.episodicdb/my-agent.db
194
+ EpisodicDB(agent_id="my-agent", path="./x.db") # explicit path
195
+ EpisodicDB(agent_id="my-agent", path=":memory:") # in-memory (testing)
196
+ ```
197
+
198
+ ### Embeddings
199
+
200
+ EpisodicDB does not generate embeddings. Pass them in:
201
+
202
+ ```python
203
+ import openai
204
+
205
+ response = openai.embeddings.create(
206
+ model="text-embedding-3-small",
207
+ input="what the agent was doing"
208
+ )
209
+ embedding = response.data[0].embedding # 1536 dims
210
+
211
+ db.record_episode(status="success", embedding=embedding)
212
+ db.similar_episodes(embedding, status="failure", limit=5)
213
+ ```
214
+
215
+ ## Development
216
+
217
+ ```bash
218
+ git clone https://github.com/KsPsD/EpisodicDB
219
+ cd EpisodicDB
220
+ pip install -e ".[dev]"
221
+ pytest
222
+ ```
223
+
224
+ ## Stack
225
+
226
+ - [DuckDB](https://duckdb.org/) — embedded OLAP engine
227
+ - [DuckDB VSS](https://duckdb.org/docs/extensions/vss) — HNSW vector index
228
+ - [MCP](https://modelcontextprotocol.io/) — Model Context Protocol server
229
+ - Python 3.11+
230
+
231
+ ## License
232
+
233
+ MIT
@@ -0,0 +1,8 @@
1
+ from episodicdb.db import EpisodicDB
2
+
3
+
4
+ class EpisodicDBError(Exception):
5
+ """Base exception for EpisodicDB."""
6
+
7
+
8
+ __all__ = ["EpisodicDB", "EpisodicDBError"]