AI Episodic Memory Protocol - Structured episodic memory sharing between AI agents
Project description
AEMP — AI Episodic Memory Protocol
A lightweight, structured protocol for AI agents to share episodic memories, learned insights, and failure records — with confidence scoring and temporal validity.
AEMP gives multi-agent systems a shared memory layer so that one agent's hard-won experience becomes every agent's knowledge.
Features
- Three memory types — Episodes (what happened), Insights (patterns learned), and Failures (what went wrong)
- Confidence scoring — Every memory carries a 0.0–1.0 confidence value
- Temporal validity — Memories can expire; garbage collection cleans them up
- Publisher / Subscriber API — Clean separation between writing and reading memories
- File-based storage — JSON Lines format, no database required
- Tag-based queries — Filter by agent, type, tags, time range, or confidence
- Relational links —
caused_by,supersedes, andrelated_tobetween entries - Legacy log import — Import from
partner_work_log.mdformat via compatibility layer - CLI included —
aempcommand for terminal-based memory operations - Zero dependencies — Pure Python, stdlib only
Installation
pip install aemp
Quick Start
from pathlib import Path
from aemp import MemoryStore, Publisher, Subscriber
from aemp.schema import Outcome
# 1. Create a store (directory is created automatically)
store = MemoryStore(Path("./my_memories"))
# 2. Publish memories as an agent
pub = Publisher(store, agent_name="MyAgent")
pub.record_episode(
summary="Fixed Gateway startup timeout",
action="Modified timeout parameter in startup script",
result="Gateway now starts within 5 seconds",
outcome=Outcome.SUCCESS,
tags=["maintenance", "gateway"],
lessons=["Sleep unit is milliseconds, not seconds"],
)
pub.record_insight(
summary="VBS script changes require task scheduler restart",
pattern="Windows Task Scheduler caches old VBS versions",
conditions="Only when VBS is triggered via scheduled tasks",
confidence=0.9,
tags=["windows", "vbs"],
)
pub.record_failure(
summary="Selenium scraping blocked by Cloudflare",
attempted="Headless Chrome to scrape dynamic page",
expected="Full page HTML",
actual="403 Forbidden — bot detection triggered",
root_cause="Target site uses Cloudflare bot protection",
workaround="Use official API or manual retrieval",
tags=["web-scraping"],
)
# 3. Query memories as another agent
sub = Subscriber(store, agent_name="AnotherAgent")
for mem in sub.recent(limit=5):
print(f"[{mem.agent}] {mem.summary} (confidence: {mem.confidence})")
for fail in sub.failures():
print(f"[{fail.agent}] {fail.summary} — workaround: {fail.workaround}")
for insight in sub.insights(min_confidence=0.8):
print(f"[{insight.agent}] {insight.pattern}")
Memory Types
Episode
A record of something that happened — an action and its result.
| Field | Type | Description |
|---|---|---|
action |
str |
What was done |
result |
str |
What happened as a result |
outcome |
Outcome |
SUCCESS, FAILURE, PARTIAL, or UNKNOWN |
lessons |
list[str] |
Takeaways from this episode |
Insight
A pattern or rule learned from one or more episodes.
| Field | Type | Description |
|---|---|---|
pattern |
str |
The pattern description |
conditions |
str |
When this insight applies |
evidence |
list[str] |
Episode IDs supporting this insight |
counter_examples |
list[str] |
IDs of counter-evidence |
Failure
A record of something that didn't work, with root-cause analysis.
| Field | Type | Description |
|---|---|---|
attempted |
str |
What was tried |
expected |
str |
What was expected to happen |
actual |
str |
What actually happened |
root_cause |
str |
Why it failed (if known) |
workaround |
str |
How to avoid this in the future |
All three types share a common base (MemoryEntry) with: id, agent, timestamp, expires, confidence, tags, summary, context, and relations.
API Reference
Core Classes
| Class | Module | Description |
|---|---|---|
MemoryEntry |
aemp.schema |
Base dataclass for all memory entries |
Episode |
aemp.schema |
Episode memory (action + result) |
Insight |
aemp.schema |
Insight memory (pattern + evidence) |
Failure |
aemp.schema |
Failure memory (attempted + root cause) |
MemoryType |
aemp.schema |
Enum: EPISODE, INSIGHT, FAILURE |
MemoryStore |
aemp.store |
File-based JSON Lines storage backend |
Publisher |
aemp.publisher |
High-level API for recording memories |
Subscriber |
aemp.subscriber |
High-level API for querying memories |
MemoryStore
store = MemoryStore(path)
store.publish(entry) # Store a MemoryEntry, returns ID
store.get(entry_id) # Retrieve by ID
store.query( # Filtered query
agent=None, # filter by agent name
memory_type=None, # filter by MemoryType
tags=None, # filter by tags (any match)
after=None, # ISO8601 lower bound
before=None, # ISO8601 upper bound
min_confidence=0.0, # minimum confidence
include_expired=False, # include expired entries
limit=100, # max results
)
store.forget(entry_id) # Soft-delete (set expiry to now)
store.gc() # Garbage collect expired entries
store.count() # Count non-expired entries
Publisher
pub = Publisher(store, agent_name="MyAgent")
pub.record_episode(summary, action, result, outcome=..., confidence=..., tags=..., lessons=..., context=..., caused_by=...)
pub.record_insight(summary, pattern, conditions=..., confidence=..., tags=..., evidence=..., expires=...)
pub.record_failure(summary, attempted, expected, actual, root_cause=..., workaround=..., confidence=..., tags=..., context=...)
Subscriber
sub = Subscriber(store, agent_name="MyAgent")
sub.recent(limit=20) # Most recent memories
sub.from_agent(agent, limit=50) # From a specific agent
sub.from_others(limit=50) # Exclude own memories
sub.episodes(**kwargs) # Episode-type only
sub.insights(min_confidence=0.5) # Insights above threshold
sub.failures(**kwargs) # Failure records
sub.by_tags(tags, limit=50) # Filter by tags
sub.related_to(entry_id) # Find related entries
sub.search(keyword, limit=20) # Keyword search in summaries
CLI
AEMP ships with a command-line interface:
aemp recent [n] # Show recent n memories (default 10)
aemp search <keyword> # Search memories by keyword
aemp failures # Show known failure records
aemp insights [min_conf] # Show insights (default >50%)
aemp from <agent> [n] # Show memories from a specific agent
aemp publish <agent> <text> # Record a quick episode
aemp status # Show store status
aemp import [path] # Import from partner_work_log.md
Compatibility
AEMP includes a compatibility layer (aemp.compat) to import and export entries from legacy partner_work_log.md format:
from aemp.compat import import_log_file, export_to_log_format
episodes = import_log_file("partner_work_log.md")
for ep in episodes:
print(export_to_log_format(ep))
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aemp-0.1.0.tar.gz.
File metadata
- Download URL: aemp-0.1.0.tar.gz
- Upload date:
- Size: 19.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
977a00acb1bcc357113cf20cc843d5427a758c5ef837ad3f0e5753107e742ad4
|
|
| MD5 |
f1458c08daa7813e43299ce57e64ee82
|
|
| BLAKE2b-256 |
9c6704ba02cb8f6249643532dc07b240e7e002003931f3c726e99316a03ce8c1
|
File details
Details for the file aemp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: aemp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
57a2dd710e13ff7a4c8e96f43e4a957fb6d03e5eed537afe993b9c969c259248
|
|
| MD5 |
11df4172694e86666f7c33446439d729
|
|
| BLAKE2b-256 |
2bc4bc0ca29c223871a215821bc35d250aa2f699b1316f0539a9ad9a2085dda5
|