VIP Contextual Narrative Briefs
Context and Problem Statement
The VIP email pipeline (vip-email-received.ts) produces analytical briefs: thread stats, followed links, binary “needs attention: yes/no.” Joel wants narratives — briefs that read like an executive assistant who knows the full history, the project arc, the relationship cadence, and can calibrate urgency precisely.
The infrastructure exists (ADR-0204 shipped semantic recall, Typesense collections, gateway context refresh) but the VIP pipeline doesn’t use it. It runs its own parallel context fan-out (Front thread, Granola, memory recall, GitHub) that’s disconnected from the broader context system.
Current VIP brief output
## VIP: Alex Hillman <alex@indyhall.org> — [aih] Monday email review
Thread: 12 messages, last activity 2h ago
Your last reply: 3d ago
Key links: docs.google.com/... — 2026 Proposal
Needs your attention: yes — Joel has not replied in the cached thread yetWhat Joel wants
## VIP: Alex Hillman — Monday Launch Email Ready
Alex sent the final Monday launch email for Matt's approval. This is the
third touchpoint this week on the AIH launch sequence — Tuesday was sales
page feedback (Excalidraw diagrams, learning environment screenshots),
Wednesday the email copy itself. The sales page feedback is still open.
This email is time-sensitive: it needs Matt's approval and scheduling before
Monday morning. You haven't replied to the sales page thread yet (3 days).
⏰ Reply today — launch email needs approval for Monday send.Decision
Extend the VIP pipeline with four changes that build on ADR-0204’s infrastructure. Each is independently valuable and ships incrementally.
Change 1: Populate email_threads collection
The email_threads Typesense collection schema exists but the collection has never been created or populated. Backfill all VIP sender conversations from the Front API.
Implementation:
- New Inngest function
vip/email-threads.backfill— walks Front API conversations filtered by VIP senders, paginates through messages, indexes intoemail_threads - Each document: conversation_id, subject, participants, messages_json, followed_links, summary, SKOS concept tags
- Runs once for backfill, then the existing VIP pipeline upserts on each new email (the
cache-email-threadstep already exists but the collection doesn’t)
Change 2: SKOS concept tagging on index
When indexing into any Typesense collection (email_threads, channel_messages, system_knowledge, otel_events), tag documents with SKOS concepts for graph traversal:
person:alex-hillman— sender/participantproject:ai-hero— detected from subject/content using operator-relay’s existing project pattern matchingtopic:launch-email— extracted topicrole:collaborator— relationship type
Schema addition to email_threads and channel_messages:
{ name: "skos_concepts", type: "string[]", facet: true, optional: true }This enables queries like: “everything tagged person:alex-hillman AND project:ai-hero in the last 30 days” — graph traversal via faceted search rather than hoping keyword search finds connections.
Change 3: Expand VIP context fan-out
Add three new parallel steps to the existing Promise.all fan-out in vip-email-received.ts:
search-email-history— semantic searchemail_threadsfor this sender + subject. Returns past conversation summaries, reply cadence, open threads.search-channel-history— semantic searchchannel_messagesfor this person/project. Returns relevant Slack/Discord mentions.search-vault-context— semantic searchsystem_knowledgefor project + relationship notes. Returns ADRs, vault notes, contact dossiers.
Each step is ~10 lines using existing Typesense search infrastructure.
Change 4: Narrative synthesis prompt with urgency calibration
Replace the analytical brief prompt with a narrative synthesis prompt:
Urgency scale (calibrated, not binary):
- 🔴 Reply now — deadline within 24h, blocking someone, time-sensitive decision
- 🟠 Reply today — needs response but not immediately blocking
- 🟡 Reply this week — important but not time-pressured
- 🟢 FYI — informational, no response needed
- ✅ Already handled — Joel already replied or action was taken
Prompt structure:
You are briefing an executive who's been away for a day. Given:
- The current email and full thread history
- Past email conversations with this sender (from email_threads)
- Related Slack/channel messages (from channel_messages)
- Vault notes and ADRs about this project (from system_knowledge)
- Recent meeting context (from Granola)
- Memory observations about this person/project
Write a 3-5 sentence narrative that:
1. Situates this email in the arc of the relationship and project
2. Notes what's changed since the last touchpoint
3. Identifies what's open/unresolved from prior threads
4. Ends with a calibrated urgency recommendation (🔴🟠🟡🟢✅) and why
Do NOT use bullet points. Write prose. Be specific about dates, names, and what's at stake.Consequences
Positive
- VIP briefs become narratives with institutional memory — Joel gets context without asking
- Urgency calibration replaces binary “needs attention” — actionable signal
- SKOS tagging enables graph traversal across all collections — future queries can traverse person→project→topic relationships
- Backfilled email_threads becomes a searchable relationship history
- All changes use existing Typesense + recall infrastructure (ADR-0204)
Negative
- Backfill is a one-time Front API cost (~100-200 API calls for all VIP conversations)
- SKOS tagging adds index-time computation (project pattern matching + concept extraction)
- Narrative synthesis prompt is larger than current analytical prompt — more LLM tokens per VIP email
- email_threads collection adds Typesense storage (~1-5MB for typical VIP email volume)
Neutral
- Does not change the VIP sender detection logic (vip-utils.ts)
- Does not change the newsletter auto-archive path
- Does not change Todoist task creation from VIP analysis
- Does not change the stutter fix (ADR-0226 ships after the ingested bucket fix)
Implementation Order
- Change 1 — backfill email_threads (unblocks everything else)
- Change 4 — narrative prompt (immediate brief quality improvement even without new context sources)
- Change 3 — expanded fan-out (richer context for narratives)
- Change 2 — SKOS tagging (enables graph queries, compounds over time)
Files to Modify
| Change | File | Scope |
|---|---|---|
| 1 | packages/system-bus/src/inngest/functions/vip-email-backfill.ts | New backfill function |
| 1 | packages/system-bus/src/lib/typesense.ts | Ensure email_threads collection creation |
| 2 | packages/system-bus/src/lib/typesense.ts | Add skos_concepts field to schemas |
| 2 | packages/system-bus/src/inngest/functions/vip-email-received.ts | Tag on upsert |
| 3 | packages/system-bus/src/inngest/functions/vip-email-received.ts | Add 3 search steps to fan-out |
| 4 | packages/system-bus/src/inngest/functions/vip-email-received.ts | Replace brief/analysis prompts |
Verification
joelclaw send vip/email-threads.backfill— verify email_threads collection populated- Trigger a VIP email → verify narrative brief on Telegram with urgency emoji
- Check email_threads docs have
skos_conceptsfacets - Semantic search:
joelclaw recall "Alex Hillman launch email"returns relevant email thread hits