Documentation Index
Fetch the complete documentation index at: https://docs.bumbleagi.com/llms.txt
Use this file to discover all available pages before exploring further.
Memory gives the entity a lived history. Not chat logs — narratives with emotional coloring, per-person relationship models, world beliefs, reusable procedural know-how, and a coherent self-story that evolves over time.
Memory is retrieved automatically during the perceive pipeline. Before building the prompt for each turn, the system pulls relevant episodes, relationship context for the current speaker (scalar model and/or an LLM-maintained prose portrait — see Relational memory), active beliefs, emotional imprints, procedural memory snippets matched to the current turn, and the most recent narrative synthesis. This context is injected alongside the body state so the entity responds with awareness of its own past.
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.
Episodes are recalled via cosine similarity against the embedding model (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.
memory:
episode_significance_threshold: 0.3
max_recall_results: 10
embedding_dimensions: 768
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 the relational_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_participants in message metadata (list of { person_id, person_name }), the preamble can stitch compact lines from several documents instead of one full portrait.
Optional filesystem mirror: when enabled, each document is also written under ~/.bumblebee/entities/<entity>/relationships/<person_id>.md for operator inspection.
Disable the prose system and fall back to scalar-only behavior:
memory:
relational:
enabled: false
memory:
relational:
enabled: true
reflection_temperature: 0.4
reflection_max_tokens: 800
reflection_min_gap_seconds: 30
score_derivation: true
flush_to_disk: true
max_context_tokens: 800
deep_review_on_consolidation: true
amendment_mode_threshold: 0.3
deep_review_min_new_interactions: 3
deep_review_max_tokens: 1200
gen_recent_hours: 24
gen_tail_sentences: 3
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
A belief like “Kai works on infrastructure” might start at low confidence after a single mention, strengthen after multiple conversations about deploys, and eventually become stable background knowledge the entity treats as given.
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.
memory:
imprint_decay_half_life_seconds: 2592000 # 30 days
imprint_recall_weight: 0.35
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
.md file on disk, named from a human-readable title (slugified for the filename).
- Default directory:
~/.bumblebee/entities/<entity_name>/skills/. If BUMBLEBEE_EXECUTION_WORKSPACE_DIR (or equivalent) points at a Railway volume, skills live under that workspace’s skills/ 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 — through ProceduralMemoryStore.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.
If nothing scores, that block is omitted.
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). |
Use these when the user asks “what did you save about…?” or when the entity wants to refine a playbook after a successful multi-step task.
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_skill tool definitions.
bumblebee/entity.py — _build_prompt calls procedural.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.
memory:
narrative_every_n_consolidations: 3
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.
memory:
consolidation_interval: 7200
memory_decay_rate: 0.0001
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.
The ExperienceDistiller 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 |
Avoiding duplicate relational work: If a relational reflection already ran for the same turn, distillation can use a slimmer JSON schema without the relational array, so the model does not re-extract the same relational facts in one beat.
The distiller is soma-influenced: when emotional intensity is high, the effective turn threshold drops (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.
memory:
distillation:
enabled: true
cycle_seconds: 300 # time gate
min_turns: 6 # or this many new turns since last index
min_turns_absolute: 4 # never fire below this history depth
soma_urgency_divisor: 1.5
max_extract_tokens: 800
temperature: 0.15
context_char_budget: 6000
Rough cost: one reflex completion per window (bounded by 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 |
Schema migrations run automatically on startup. Both backends store the same data: episodes, relationships, relational_documents, beliefs, imprints, automations, and reminders.
Knowledge and journal files are always on disk — they are not stored in the database. On Railway, they live on the volume when 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/utils/embeddings.py | Embedding generation for semantic recall |