Get from zero to a working recall in 5 minutes.
Install
pip install pensyveInitialize
import pensyve
p = pensyve.Pensyve(namespace="my-agent")Pensyve() accepts an optional path (defaults to ~/.pensyve/) and namespace (defaults to "default").
Create Entities
Entities represent participants — agents, users, teams, or tools.
agent = p.entity("assistant", kind="agent")
user = p.entity("alice", kind="user")kind defaults to "user" if omitted. Entity creation is idempotent: calling p.entity("alice") twice returns the same entity.
Record an Episode
Episodes are bounded interaction sequences. Use them as context managers.
with p.episode(agent, user) as ep:
ep.message("user", "I prefer dark mode and use vim keybindings")
ep.message("assistant", "Got it, noted for future sessions")
ep.outcome("success") # optional: "success", "failure", "partial"When the with block exits, Pensyve automatically extracts memories from the conversation.
Remember a Fact
Store an explicit semantic memory without recording an episode:
mem = p.remember(entity=user, fact="Alice prefers Python over JavaScript", confidence=0.95)
print(mem.memory_type) # "semantic"
print(mem.confidence) # 0.95confidence defaults to 0.8.
Recall Memories
results = p.recall("programming language preference", entity=user)
for m in results:
print(f"[{m.memory_type}] {m.content} (score={m.score:.2f})")Each Memory object has these properties:
| Property | Type | Description |
|---|---|---|
id | str | UUID |
content | str | Memory text |
memory_type | str | "episodic", "semantic", or "procedural" |
confidence | float | Confidence in [0, 1] |
stability | float | FSRS stability in [0, 1] |
score | float | Retrieval relevance score |
Filtering
# Only semantic memories
results = p.recall("vim", entity=user, types=["semantic"])
# Limit results
results = p.recall("vim", entity=user, limit=3)Recall Grouped (for LLM readers)
When you're feeding recalled memories to another LLM as context, use recall_grouped() instead. It returns memories already clustered by source session and ordered chronologically — ready to format as session blocks in a reader prompt with no client-side grouping logic.
groups = p.recall_grouped("How many projects have I led this year?", limit=50)
# Each SessionGroup is one conversation episode, ready to format as a prompt block.
for g in groups:
print(f"### Session {g.session_id} ({g.session_time}):")
for m in g.memories:
print(f" {m.content}")No more OrderedDict clustering, no more reordering by date string, no more boilerplate every consumer has to reinvent.
Consolidation
Run consolidation to promote repeated episodic facts to semantic memories, apply FSRS decay, and archive low-stability memories:
stats = p.consolidate()
print(stats) # {"promoted": 2, "decayed": 5, "archived": 1}Forget
Archive (soft-delete) or permanently delete all memories for an entity:
# Soft delete (archive)
p.forget(entity=user)
# Hard delete
p.forget(entity=user, hard_delete=True)Full Example
import pensyve
p = pensyve.Pensyve(namespace="my-agent")
agent = p.entity("assistant", kind="agent")
user = p.entity("alice", kind="user")
# Record a conversation
with p.episode(agent, user) as ep:
ep.message("user", "I always use dark mode")
ep.message("assistant", "Noted!")
# Store an explicit fact
p.remember(entity=user, fact="Alice is a backend engineer", confidence=0.9)
# Query memories
for m in p.recall("what does alice do?", entity=user):
print(f"[{m.memory_type}] {m.content}")