Episodic memory
Events are stored as narratives, not raw transcripts. Each episode carries:- Significance — a score reflecting how important the event was. Events below the threshold (
episode_significance_threshold, default 0.3) are not promoted to durable episodes. - Tags — including a compact
soma:snapshot of bar percentages when the episode is saved, so semantic recall can sit next to bodily context. - Emotional imprint — what the entity felt during the event, derived from the soma body state at the time.
- Self-reflection — the entity’s own interpretation of what happened and why it mattered.
- Embedding vector — a semantic representation used for similarity-based recall.
nomic-embed-text) when building context for a new turn. The system retrieves the most relevant episodes — not the most recent — so a conversation about music surfaces music-related memories regardless of when they occurred.
Relational memory
The entity builds a persistent model of each person it interacts with. Relational data is updated after committed turns and injected into the prompt so tone, depth, and content can differ by relationship.Relationship documents (prose-first model)
By default, the harness uses a relationship document per person: a living Markdown prose portrait the entity rewrites over time (first person, reflective), stored in therelational_documents table. This captures texture that scalars cannot — ambivalence, subtext, unresolved threads, communication style, drift — not just “scores.”
After each turn (subject to a minimum gap between passes), a relational reflection call runs on the reflex model: it reads the existing document, the recent exchange, somatic appraisal tags/felt notes, compact body state, and approximate silence since last interaction, then amends or rewrites the document. A second small call optionally derives numeric summaries (familiarity, warmth, trust, tension, investment) and syncs them into the legacy relationships row so drives, wake logic, and older code paths still see coherent numbers.
Turn interaction with other subsystems
- Distillation — If a reflection just ran, experience distillation can skip extracting relational JSON for that window to avoid duplicate work. If distillation still produces relational insights while documents are enabled, they are queued as pending notes on the document and folded into the next reflection (see Experience distillation).
- Consolidation — On each consolidation cycle, eligible people can receive a deeper review (more tokens, episodic snippets involving that person) once enough new interactions have accrued since the last deep pass.
- GEN (noise) — Recent relationship documents contribute short tails to the inner-voice prompt so stray thoughts can echo relational texture.
- Group chats — If the platform supplies
relationship_context_participantsin message metadata (list of{ person_id, person_name }), the preamble can stitch compact lines from several documents instead of one full portrait.
~/.bumblebee/entities/<entity>/relationships/<person_id>.md for operator inspection.
Disable the prose system and fall back to scalar-only behavior:
Legacy relationships row (compatibility)
The relationships table still stores one row per person: familiarity, warmth, trust, dynamic, notes, topics / unresolved lists, timestamps, and interaction count. When relationship documents are enabled, warmth/trust/familiarity are primarily derived from the document after reflection; when disabled, the harness uses the classic scalar updater (decay/bumps per turn) as before.
On Telegram, the /me command shows the current relationship snapshot for the person asking.
Source files: bumblebee/memory/relational.py (scalar store and upserts), bumblebee/memory/relational_document.py (documents + sync), bumblebee/memory/relational_reflection.py (reflection + deep review).
World beliefs
The entity maintains a set of beliefs about the world — things it treats as true, uncertain, or sourced from experience. Beliefs are not facts the developer programs in; they form through conversation and observation. Each belief has:- Confidence — how certain the entity is (0.0–1.0)
- Source — where the belief came from (conversation, observation, inference)
- Reinforcement — beliefs strengthen when repeated or confirmed
- Decay — beliefs weaken over time without reinforcement
Emotional imprints
Significant moments leave emotional imprints — traces of how the entity felt during particularly charged events. Imprints decay slowly over a configurable half-life (default 30 days) and influence recall: emotionally charged memories surface more readily during semantic retrieval. This means the entity does not just remember what happened — it remembers how it felt. A conversation that produced high tension or strong warmth will be more easily recalled than a neutral exchange of the same topic.Knowledge and journal
Two file-based memory systems complement the structured database: Knowledge (knowledge.md) — durable facts, opinions, and context organized into ## sections. Embeddings pull relevant sections into context each turn. Sections marked [locked] cannot be modified by the entity. Unlocked sections can be updated via the update_knowledge tool during deliberate reasoning. During context compaction, the system can also flush extracted facts into knowledge automatically.
Journal (journal.md) — append-only private reflections. The entity writes journal entries after automation runs, significant conversations, or when it has something to record. The journal is readable via tools but is not injected into context automatically — the entity chooses when to consult it.
See Knowledge and journal for setup and usage.
Procedural memory (“skills”)
Procedural memory is how-to the entity saves for itself — repeatable workflows, command sequences, debugging heuristics, or “when X happens, do Y” notes. It is not the same as episodic memory (what happened in past chats) or knowledge (knowledge.md, embedding-ranked sections of durable facts). Think of it as a personal playbook: short Markdown documents the model can pull in when the current conversation looks relevant.
What gets stored
- Each skill is one
.mdfile on disk, named from a human-readable title (slugified for the filename). - Default directory:
~/.bumblebee/entities/<entity_name>/skills/. IfBUMBLEBEE_EXECUTION_WORKSPACE_DIR(or equivalent) points at a Railway volume, skills live under that workspace’sskills/so they persist with the rest of the entity files there. - Content is freeform Markdown: steps, bullet lists, pasted examples, API endpoints — whatever the entity recorded with
update_skill.
How it surfaces each turn (automatic)
On every perceive, the harness runs the same conversation slice used for knowledge retrieval — recent chat turns (plus optional rolling summary) and the current user message — throughProceduralMemoryStore.query().
- Matching is lexical, not semantic: the code scores skills if the query string appears in the skill slug or body, and boosts longer tokens (≥4 chars). There are no embeddings for procedural recall; it is intentionally cheap and predictable.
- Up to three skills with positive score are returned; each excerpt is capped (long bodies are truncated with an ellipsis marker).
- Matching snippets are injected into the turn context preamble (not the static system prompt) under the heading
[Procedural memory that may help right now], alongside body state, projects, faculty, etc. So the model sees “here is know-how that might apply to this exchange” without flooding the system prompt.
Tools (explicit access)
The entity can also manage skills deliberately:| Tool | Role |
|---|---|
list_skills | List all skills, or filter by a substring match on name/content. |
read_skill | Load the full Markdown for one skill by name. |
update_skill | Create or overwrite a skill (the primary way new procedural memory is written). |
When to use procedural vs knowledge
| Procedural memory (skills) | Knowledge (knowledge.md) | |
|---|---|---|
| Shape | One file per skill | Sections inside a single file |
| Recall | Lexical match on current turn text | Embedding similarity on a query |
| Best for | Steps, scripts, “how I fixed this before” | Facts, preferences, stable reference material |
| Host control | Entity-owned files under skills/ | Mix of locked and editable sections |
Implementation
bumblebee/memory/procedural.py—ProceduralMemoryStore(list_skills,read_skill,upsert_skill,query).bumblebee/presence/tools/procedural.py—list_skills,read_skill,update_skilltool definitions.bumblebee/entity.py—_build_promptcallsprocedural.query(..., limit=3)and appends results to the preamble.
Narrative identity
Periodically, a narrative synthesis pass composes a coherent self-story from recent episodes. This narrative feeds back into the entity’s system prompt, giving it a sense of trajectory — not just isolated memories, but a thread connecting them. The narrative answers questions like: what has been happening lately, what matters to the entity, how has it changed, and what does it want. This is resynthesized every few consolidation cycles.Consolidation
Memory consolidation runs on a timer (default every 2 hours). It applies episode significance decay, triggers narrative synthesis on a cadence, and can run deep relational document reviews for people with enough new material since the last pass (when relationship documents are enabled). Distillation and per-turn memory formation are separate from this tick; see Experience distillation. Consolidation is what turns scattered conversations into structured long-term memory. Without it, the entity has only rolling chat history. With it, the entity develops biography.Experience distillation
Consolidation runs on a long interval; knowledge flush during context compaction targets another problem. Experience distillation fills the gap for durable tidbits from ordinary chat — facts about people or projects, corrections, preferences, small relational observations, and occasional self-insights — without waiting for a consolidation tick. TheExperienceDistiller is invoked from Entity.maybe_distill (after committed turns when the trigger fires, and from the daemon) on a hybrid schedule: a time gate (cycle_seconds) or enough new turns since the last run, with a floor (min_turns_absolute). Defaults are 300 seconds and 6 turns (see YAML below). It serializes a recent conversation window, adds participant hints and a soma snapshot, and calls the reflex model for one JSON object with these categories:
| Category | What it captures | Where it goes |
|---|---|---|
| Knowledge | Durable facts, preferences, corrections | knowledge.md sections (then knowledge store refresh) |
| Relational | Person insights, warmth/trust deltas | Classic mode: relationships row via upsert_interaction with notes. Relationship documents on: queued pending distillation lines on the document for the next relational reflection (see Relationship documents). |
| Beliefs | Corrections, opinions, self-discoveries | Beliefs table (with optional embedding) |
| Journal | Self-reflective insights | journal.md with distillation tagging |
soma_urgency_divisor), so charged conversations get distilled sooner.
Distillation is idempotent per window: a hash of the processed slice prevents re-running on identical content. Knowledge deduplicates by section title. Relational note lists on the legacy row are capped. Failures are logged and do not block chatting.
max_extract_tokens and context_char_budget), plus embeddings for new beliefs when extraction succeeds.
Storage
| Backend | When |
|---|---|
| SQLite | Default. Per-entity file at ~/.bumblebee/entities/<name>/memory.db |
| Postgres | When DATABASE_URL is set. Typical for hybrid Railway deployments |
BUMBLEBEE_EXECUTION_WORKSPACE_DIR is set.
Source files
| File | Role |
|---|---|
bumblebee/memory/episodic.py | Episode storage, recall, significance scoring |
bumblebee/memory/relational.py | Per-person relationship rows (scalars, notes) |
bumblebee/memory/relational_document.py | Relationship documents, derived scores, disk mirror |
bumblebee/memory/relational_reflection.py | Reflection passes and consolidation deep review |
bumblebee/memory/beliefs.py | World belief system with reinforcement and decay |
bumblebee/memory/imprints.py | Emotional imprint tracking |
bumblebee/memory/narrative.py | Self-narrative synthesis |
bumblebee/memory/consolidation.py | Consolidation engine |
bumblebee/memory/distillation.py | Experience distillation from conversations |
bumblebee/memory/knowledge.py | Knowledge file operations |
bumblebee/memory/journal.py | Journal file operations |
bumblebee/memory/procedural.py | Procedural skills (file-backed Markdown) |
bumblebee/memory/store.py | SQLite storage layer |
bumblebee/memory/postgres_store.py | Postgres storage layer |
bumblebee/identity/dream.py | Dream consolidation engine (creative memory recombination during idle) |
bumblebee/utils/embeddings.py | Embedding generation for semantic recall |