A contextual bandit for bookmark surfacing.
Kairos learns when to interrupt with a topic cluster, not just what matches a query. Silence is the default; feedback changes the policy.
Most bookmark tools become searchable graveyards. They can retrieve the right link when you ask, but they do not learn whether this is the right moment to interrupt.
Kairos treats surfacing as a policy problem:
- Ingest and cluster saved bookmarks.
- Read the current headspace: calendar gap, location, work mode, attention capacity.
- Rank clusters by topical fit.
- Thompson-sample learned engagement weights.
- Surface one digest or return
KAIROS_OK. - Update the bandit from snooze, dismiss, expand, and click feedback.
The core demo beat is simple: dismiss a surface and watch beta increase. No LLM fine-tuning, no hidden gradient steps.
cp .env.example .env # set MONGODB_URI and GEMINI_API_KEY
brew install just # or: cargo install just
just demo-serveOpen http://127.0.0.1:8420, click Surface now, dismiss the card, then switch to Admin view to watch the bandit update.
Useful one-liners:
just demo-surface # trigger another demo surface
uv run kairos bookmarks prep --sync # incremental X sync + enrich + research + embed + cluster
uv run kairos heartbeat # one direct policy cycle
uv run kairos optimize readiness # check GEPA sample readiness
uv run kairos optimize nightly # cron-safe prompt improvement pass
uv run kairos mcp # expose Kairos tools over MCPAfter the server is running, open http://127.0.0.1:8420/walkthrough for the animated prep -> heartbeat tour.
| Plane | What it does | Key files |
|---|---|---|
| Data plane | X sync, bookmark enrichment, link research, embeddings, HDBSCAN clusters | ingest/, bookmarks/, embeddings/ |
| Context plane | Calendar/Gmail/location/demo headspace, LLM moment narrative | core/context.py, core/headspace.py, google/ |
| Policy plane | Vector match, Thompson sampling, interrupt gates, digest generation | core/ranking.py, core/heartbeat.py, db/bandit.py |
| Learning plane | Feedback events, alpha/beta updates, treatment posteriors, GEPA prompt diffs | core/feedback.py, core/optimize.py, sim/ |
| Surface plane | FastAPI dashboard, SSE activity feed, MCP tools, optional OS delivery | web/, delivery/, mcp/, agent/ |
The two important loops:
| Loop | Learns | Trigger | Artifact |
|---|---|---|---|
| Online bandit | When/what to surface | Every feedback event | bandit_params, bandit_treatments |
| Offline GEPA-style reflection | How to phrase digests | kairos optimize run/nightly or /api/optimize |
optimization_runs |
Read the full map in docs/ARCHITECTURE.md.
| Start here | When you need |
|---|---|
| docs/demo-readiness/DEMO.md | Stage runbook, timing, recovery paths |
| docs/demo-readiness/FAQ.md | Judge Q&A: bandits vs RAG, GEPA, MCP, X API |
| docs/DEVELOPER_GUIDE.md | UI/API contract, hotspots, extension checklist |
| docs/ARCHITECTURE.md | System diagrams and data model |
| docs/TECH_DEBT.md | What shipped, what to build next |
| docs/MCP_SETUP.md | Claude Code / Cursor MCP setup |
| docs/GOOGLE_WORKSPACE_SETUP.md | Calendar/Gmail OAuth and headspace sync |
| docs/LOCAL_QUEUE.md | Optional Redis + Arq prep queue |
If you want to contribute, pick one of these lanes.
| Lane | Good first expansion | Why it matters |
|---|---|---|
| Make learning visible | Add a latest-learning trace panel from pipeline_events |
Judges and users should see context -> rank -> feedback -> beta update in one glance |
| Treatment lift | Visualize bandit_treatments by digest style or prompt version |
Connects GEPA wording changes to measured behavior |
| Better context sharing | Move from bucketed context_class to linear/contextual Thompson sampling |
A click in one similar context should help another |
| Sleep-time cache | Precompute candidate digests after Google sync or prep jobs | Keeps heartbeat latency low without weakening intelligence |
| More sources | Readwise, Pocket, browser export, RSS | Tests whether the policy is source-agnostic |
| Trace infrastructure | Add decision_id, prompt version, model input/output, latency, reward |
Turns the self-improvement stack into a research-quality dataset |
The strongest product rule: if it does not improve the interruption policy or make learning legible, defer it.
- PLAN.md - product thesis, theme framing, and roadmap.
- docs/ARCHITECTURE.md - how the heartbeat, ranking, and feedback loop fit together.
- Contextual bandits / LinUCB - the classic shape behind context-aware recommendation.
- Action-Centered Thompson Sampling - useful mental model for interventions and feedback.
- docs/TECH_DEBT.md - current "what next" list for making the stack stronger.
- GEPA paper - prompt/program evolution from feedback signals.
- DSPy GEPA overview - production-oriented optimizer API inspiration.
- docs/archive/hackathon/VISION.md - longer-range positioning around GEPA, traces, and self-improvement.
- docs/DEVELOPER_GUIDE.md - practical guide to API endpoints, SSE events, and fragile assumptions.
- docs/MCP_SETUP.md - MCP tool path for Claude Code and Cursor.
- docs/GOOGLE_WORKSPACE_SETUP.md - Google OAuth, Calendar/Gmail sync, and ADK path.
- OpenInference - useful reference point for future LLM trace export.
- MongoDB Atlas Vector Search - cluster and bookmark ranking backend.
- HDBSCAN documentation - density clustering for noisy bookmark corpora.
- Google Gemini API docs - Gemini generation and embeddings reference.
- X API bookmarks endpoint - primary ingest path.
These are deliberately scoped research threads that map back to code in this repo.
- Treatment-aware bandits. Kairos already writes
bandit_treatments. The next step is showing whether digest style or prompt version changes engagement. - Linear Thompson sampling. Replace sparse context buckets with feature vectors: gap length, meeting density, topic affinity, hour, surface fatigue.
- Delayed feedback. A user might click later or ignore silently. Explore decay windows, censored rewards, and off-policy evaluation.
- Sleep-time compute. Precompute cluster dossiers and digest drafts while idle, then keep heartbeat fast.
- Cohort priors. Cold-start new users from similar users without losing per-user personalization.
- Trace joins. Add a durable
decision_idthrough heartbeat -> LLM call -> notification -> feedback. This is the substrate for serious prompt optimization. - Multi-source memory. Add non-X sources and test whether the policy still works when content shape changes.
For a curated list of post-demo bets, see docs/TECH_DEBT.md and docs/archive/research/CURSOR.md.
# Data plane
uv run kairos x auth
uv run kairos bookmarks prep --sync
uv run kairos bookmarks clusters
# Policy plane
uv run kairos heartbeat
uv run kairos heartbeat --via-agent
uv run kairos feedback <notification-id> dismissed
# Self-improvement
uv run kairos sim run --days 14 --personas alex,maya,jordan
uv run kairos optimize readiness
uv run kairos optimize run --dry-run
uv run kairos optimize nightly
# Interfaces
uv run kairos serve
uv run kairos mcp
uv run kairos workerKairos is not trying to be a general second brain, a search box, or a notification firehose.
It is a small, inspectable system for one claim:
Saved knowledge becomes useful when the agent learns the right moment to bring it back.