Context Memory System — Architecture
Passive intelligence layer that listens to Slack channel messages, extracts structured facts using Claude Haiku, stores them as vector-embedded observations, and synthesizes per-entity summaries nightly. The bot uses these at query time to inject relevant organizational context into LLM prompts.1. Data Flow — End to End
2. Entity Relationship Diagram
3. Ingestion Detail
Message Flow
- Bot receives every Slack channel message (not DMs)
- Fires
POST /context/ingestwithorganizationId,channelId,channelName,platformUserId,messageTs,threadTs,text - Message inserted into
channel_messageswithprocessedAt = null - URLs extracted from message text via regex, cleaned of Slack formatting (
<url|display>->url) - Each URL queued as
process-urlBullMQ job -> Jina Reader API fetches content -> Claude Haiku summarizes -> stored as observation
Batch Triggers
| Trigger | Condition | Mechanism |
|---|---|---|
| Volume-based | >= 20 unprocessed messages | Immediate process-batch BullMQ job |
| Timer-based | 30 minutes since last message | Delayed BullMQ job (deterministic jobId per org, no stacking) |
Extraction Pipeline
- Fetch unprocessed messages (limit
BATCH_SIZE, default 20) - Resolve
platformUserId-> user names viaplatform_identities+userstables - Group messages by channel, format with timestamps and display names
- Send to Claude Haiku 4.5 with extraction prompt
- Parse JSON array of
{ entityType, entityId, category, observation, confidence } - For each observation: generate embedding via OpenAI, insert into
context_observations - Mark source messages as processed (
processedAt = now) - Evaluate proactive actions via
context-actions.tsrules
4. Query Flow — How the Bot Retrieves Context
Context String Format
5. Entity Types and Observation Categories
Entity Types
Observation Categories
| Category | Description | Confidence Threshold | Proactive Action |
|---|---|---|---|
commitment | User promised to deliver something | > 0.85 | Auto-create task |
blocker | User is blocked on something | > 0.7 | Create blocker record |
handoff | Work transferred between people | > 0.75 | DM receiving user |
deadline_mention | Deadline referenced in conversation | > 0.8 | Alert ops channel |
risk_signal | Missed deadlines, scope changes | > 0.7 | Create blocker, notify ops |
mood_signal | Frustration, burnout, excitement | > 0.7 | Flag to ops channel |
status_update | Substantive progress update | > 0.5 | None |
reference | URL content or web search result | 0.7-0.8 | None |
Confidence Calibration
- 0.9+: Directly stated fact (“I finished the newsletter”)
- 0.7-0.9: Strong inference (“Rohan always does QC after content — likely a handoff pattern”)
- 0.5-0.7: Weak inference (tone-based mood signals)
- Below 0.5: Not stored
6. Nightly Summarization
Summary Storage
summaryType = "profile"— one per entity, upserted nightly- Unique index on
(entity_type, entity_id, summary_type)— ensures one profile per entity - Embedding generated for the summary text itself (enables semantic search on summaries)
- Old summaries are overwritten, not versioned
7. Cleanup & Retention
| Table | Retention | Rationale |
|---|---|---|
channel_messages | 7 days (configurable via CONTEXT_RAW_RETENTION_DAYS) | Temporary buffer, facts already extracted |
context_observations | Indefinite (soft-delete via superseded_by) | Core knowledge graph |
context_summaries | Indefinite (overwritten nightly) | Entity profiles, always current |
8. Backfill Architecture
For new orgs or channels, historical messages can be backfilled from Slack:- Fetches last 1 year of history
- 2-second delay between Slack API calls (rate limit safe)
- Thread replies fetched for threaded messages
- Uses
backfill_statetable to track progress per channel
9. Auto Mood Detection
Context observations withcategory = "mood_signal" feed into automatic mood scoring:
10. API Endpoints
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
POST | /context/ingest | API Key | Ingest a channel message |
POST | /context/browse | API Key | Fetch + summarize a URL |
POST | /context/search | API Key | Web search + store results |
GET | /context/stats | JWT / API Key | Dashboard stats (counts, categories) |
GET | /context/observations | JWT / API Key | List observations (filterable) |
GET | /context/summaries | JWT / API Key | List entity summaries |
GET | /context/:entityType/:entityId | JWT / API Key | Get entity context (summary + observations) |
GET | /context/entity/:entityType/:entityId/timeline | JWT / API Key | Full entity timeline |
POST | /context/observations | JWT / API Key | Manually create observation |
DELETE | /context/observations/:id | JWT / API Key | Delete observation |
POST | /context/observations/:id/supersede | JWT / API Key | Soft-delete (supersede) |
POST | /context/backfill | JWT / API Key | Trigger historical backfill |
GET | /context/backfill/status | JWT / API Key | Check backfill progress |
11. Environment Variables
| Variable | Required | Default | Purpose |
|---|---|---|---|
ANTHROPIC_API_KEY | Yes | — | Claude Haiku for extraction & summarization |
OPENAI_API_KEY | Yes | — | text-embedding-3-small for 1536-dim vectors |
JINA_API_KEY | No | — | URL content fetching via Jina Reader API |
TAVILY_API_KEY | No | — | Web search via Tavily |
CONTEXT_BATCH_SIZE | No | 20 | Messages per extraction batch |
CONTEXT_RAW_RETENTION_DAYS | No | 7 | Days to keep raw channel_messages |
12. Key Files
| File | Purpose |
|---|---|
packages/db/src/schema/channel-messages.ts | Raw message buffer schema |
packages/db/src/schema/context-observations.ts | Extracted facts + embeddings schema |
packages/db/src/schema/context-summaries.ts | Entity profile summaries schema |
apps/api/src/modules/context/context.service.ts | Core service: ingest, query, summarize, cleanup |
apps/api/src/modules/context/context-processor.service.ts | BullMQ worker: batch extraction, URL processing, backfill |
apps/api/src/modules/context/context-embeddings.service.ts | OpenAI embedding generation + pgvector similarity search |
apps/api/src/modules/context/context-web.service.ts | Jina URL fetch + Tavily web search |
apps/api/src/modules/context/context-actions.service.ts | Proactive action evaluation |
apps/api/src/modules/context/context-backfill.service.ts | Backfill status tracking |
apps/api/src/modules/context/context.controller.ts | REST API endpoints |
packages/rules/src/context-actions.ts | Rule engine: observation -> proactive action mapping |
apps/api/src/modules/jobs/dynamic-cron.service.ts | Cron registration for daily summary + cleanup |
13. Database Indexes
pgvector/pgvector:pg16 Docker image and CREATE EXTENSION vector migration.