Skip to content

feat(bot): episodic memory context in thinking partner#45

Merged
Mathews-Tom merged 2 commits into
mainfrom
feat/episodic-thinking-context
Mar 25, 2026
Merged

feat(bot): episodic memory context in thinking partner#45
Mathews-Tom merged 2 commits into
mainfrom
feat/episodic-thinking-context

Conversation

@Mathews-Tom

Copy link
Copy Markdown
Owner

Summary

Connect episodic memory to the thinking partner so past decisions surface alongside vault notes and graph context when thinking about a topic. Previously, the episodic store existed in isolation — episodes could be created and queried via bot commands, but the thinking partner never accessed them. Now, when a user thinks about "kubernetes scaling", relevant past decisions about kubernetes or scaling are automatically injected as context.

Inspired by memora-lab/memory-service-public's retrieval agent which pulls observations, people, and context into a unified prompt.

How It Works

User: /think kubernetes scaling strategy
                    ↓
ThinkingPartner._build_vault_context():
  1. Semantic search → vault notes about kubernetes
  2. Graph lookup → entity connections for kubernetes
  3. [NEW] Episodic search → past decisions mentioning "kubernetes" or "scaling"
                    ↓
Context sent to LLM:
  ## Relevant Notes from Vault
  ...
  ## Knowledge Graph Context
  ...
  ## Past Decisions                              ← NEW
  - **Adopt Kubernetes for deployment** → Reduced downtime by 50% (success)
    Lessons: Container orchestration simplifies scaling

Episodic Context Assembly

  1. Extract topic words (>= 3 characters, first 5 words)
  2. For each word, query EpisodeStore.search_by_entity(word, limit=3)
  3. Deduplicate episodes across overlapping entity searches
  4. Format as "Past Decisions" section with decision, outcome, status, and up to 3 lessons

Short words (< 3 chars like "ai", "ml") are skipped to avoid noisy broad matches.

Changes

Modified Files

  • src/vaultmind/bot/thinking.py — Added episode_store: object | None = None parameter to think() and _build_vault_context(). New _add_episodic_context() helper queries episodes by topic keywords, deduplicates, and formats the "Past Decisions" section. Uses lazy EpisodeStore import with isinstance check to avoid circular deps
  • src/vaultmind/bot/handlers/context.py — Added episode_store: object | None = field(default=None) to HandlerContext dataclass
  • src/vaultmind/bot/handlers/think.py — Passes ctx.episode_store to ctx.thinking.think()

New Files

  • tests/test_episodic_thinking.py (321 lines) — 9 integration tests using real EpisodeStore with tmp_path

Backward Compatibility

  • episode_store defaults to None in all signatures — existing callers unaffected
  • HandlerContext.episode_store defaults to None — existing handler construction unchanged
  • When episode_store is None, no episodic section is generated (graceful skip)
  • All existing thinking tests pass unchanged (no episode store configured)

Test plan

  • 9 new tests in test_episodic_thinking.py:
    • Entity match surfaces episodes with decision, outcome, and lessons
    • No matching episodes → no "Past Decisions" section
    • Deduplication: same episode matched by multiple keywords shown only once
    • None episode store → graceful skip
    • Multiple episodes all shown
    • Pending episodes display "pending" status
    • Lessons truncated at 3 per episode
    • think() passes episode_store through to context builder
    • Short words (< 3 chars) skipped in entity search
  • All existing thinking/session tests pass unchanged (8 in test_thinking.py)
  • Full suite: 966/966 tests pass, 0 regressions
  • ruff check — clean
  • mypy --ignore-missing-imports — clean
  • Manual: create episodes via /decide + /outcome, then /think about related topic — verify episodes surface

Surface relevant past decisions alongside vault notes and graph context
when thinking about a topic. Queries episode store by entity keywords
from the topic (words >= 3 chars, top 5), deduplicates across searches,
and injects a "Past Decisions" section with decision, outcome, status,
and up to 3 lessons per episode.

Add episode_store parameter to think() and _build_vault_context().
Add _add_episodic_context() helper with lazy EpisodeStore import.
Add episode_store field to HandlerContext. Wire through think handler.
9 tests covering: entity match surfaces episodes, no matches produces
no section, deduplication across overlapping entity searches, None
episode store graceful skip, multiple episodes all shown, pending
status display, lesson truncation at 3, think() passes episode store
through, and short words (< 3 chars) skipped in entity search.
@Mathews-Tom Mathews-Tom merged commit ecfe5d7 into main Mar 25, 2026
3 checks passed
@Mathews-Tom Mathews-Tom deleted the feat/episodic-thinking-context branch March 25, 2026 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant