Chronicle
Enables personal data analysis and insights using AI agents across Spotify, GitHub, finances, fitness, and journal entries.
README
Chronicle — Personal AI Analyst
Chronicle connects to your real data — Spotify, GitHub, finances, fitness records, journal entries — and tells you what it says about you that you haven't admitted yet. Five specialised AI agents, each with a locked inference tier, deployment configuration, and OOM safety check, run as a compiled LangGraph swarm behind a validated FastAPI gateway.
This is a multi-session build. Each session extends the previous one without removing anything.
Quick Start
You need one thing before anything else: a Gemini API key.
Get one free at aistudio.google.com → "Get API key" → Create. It's free with generous limits.
Then open .env in this directory and replace the placeholder:
GEMINI_API_KEY=your_actual_key_here
That's the only external step. Everything else is handled below.
Option A — Local Setup (Python)
Requirements: Python 3.11 or later. Check with python3 --version.
Step 1 — Create a virtual environment
python3 -m venv .venv
Step 2 — Activate it
# macOS / Linux
source .venv/bin/activate
# Windows
.venv\Scripts\activate
Your prompt will now show (.venv).
Step 3 — Install dependencies
pip install -r requirements.txt
This installs: FastAPI, uvicorn, aiohttp, pydantic, google-generativeai, python-dotenv, certifi.
Step 4 — Add your API key
Open .env and set your key:
GEMINI_API_KEY=your_actual_key_here
Step 5 — Run the verification
python agent.py
Expected output:
╔══════════════════════════════════════════════════════╗
║ Chronicle — Session 12.1 Verification ║
╚══════════════════════════════════════════════════════╝
Verification: 5/5 checks passed in ~14500ms
✓ build_chronicle_graph() compiles without error
✓ Graph has all 5 Chronicle agent nodes
✓ MCPClientPool instantiates correctly
✓ Empty question rejected by AnalysisRequest (min_length=1)
✓ graph.ainvoke() returns non-empty final_brief
✓ Session 12.1 COMPLETE. Start the API: python api.py
If all 5 checks pass, proceed. (This check makes real Gemini API calls through the LangGraph swarm, so it takes ~10-15 seconds — that's expected, not a hang.)
Step 6 — Start the server
python api.py
Step 7 — Open the UI
Go to: http://localhost:8000
The dashboard, agent cards, and chat interface will load. Type a question and click Analyse.
Option B — Docker Setup
Requirements: Docker Desktop installed and running. Check with docker --version.
Step 1 — Add your API key
Open .env and set your key:
GEMINI_API_KEY=your_actual_key_here
Step 2 — Build and start
docker compose up --build
Docker will pull the Python base image, install all dependencies, and start the server. First build takes ~60 seconds. Subsequent starts take ~3 seconds.
Step 3 — Open the UI
Go to: http://localhost:8000
To stop:
docker compose down
To rebuild after code changes:
docker compose up --build
Verifying Everything Works
Once the server is running, you can check each endpoint directly:
| URL | What it returns |
|---|---|
http://localhost:8000 |
The Chronicle UI |
http://localhost:8000/health |
Session version, OOM status, MCP connector status, all agent configs |
http://localhost:8000/health/ready |
200 once the LangGraph graph is compiled and the MCP pool is connected, else 503 |
http://localhost:8000/docs |
Swagger UI — interactive docs for all endpoints |
http://localhost:8000/vram-budget/tiered |
Per-agent VRAM breakdown across S11.1/11.2/11.3 |
http://localhost:8000/oom-check |
OOM prevention pass/fail per agent |
http://localhost:8000/deployment-config |
Full vllm serve launch command per agent |
http://localhost:8000/cost-model |
4 GPU cost scenarios with annual savings |
http://localhost:8000/concurrency-table |
How context window size affects concurrent capacity |
http://localhost:8000/survivability |
Which tasks survive INT4 quantization |
http://localhost:8000/calibration-stats |
30-sample calibration dataset summary across 5 sources |
What Was Built — Session by Session
Session 11.1 — Inference Foundation
Goal: Get all 5 Chronicle agents firing concurrently against a real AI API and measure the performance baseline.
What was built:
-
CHRONICLE_AGENTS— the 5 permanent agents defined with their roles and tiers:ingestion— parses and normalises raw data from all sourcespattern— finds cross-source correlationstimeline— sequences life events chronologicallybrutality— delivers honest analysis without softeningsynthesis— produces the final structured analyst brief
-
calculate_chronicle_vram_budget()— calculates total VRAM needed for all 5 agents at a given precision (FP16, INT4, etc.). Establishes the S11.1 baseline: 90 GB at uniform FP16. -
chronicle_infer()— fires a single async inference request against the Gemini REST API and measures Time to First Token (TTFT) and Time Per Output Token (TPOT). -
run_concurrent_analysis()— dispatches all 5 agents simultaneously usingasyncio+aiohttp. All agents fire at the same moment. Wall clock time reflects true concurrent load. -
BenchmarkResult/AnalysisRequest— Pydantic schemas that remain permanent through all sessions. -
API endpoints added:
GET /health,POST /analyze,GET /vram-budget -
Dashboard: Split layout with agent status card, inference metrics card, and VRAM budget card with precision selector.
Key result: 5 agents fire concurrently in a single wall-clock window. TTFT measured across all agents.
Session 11.2 — Model Quantization
Goal: Assign the right precision to each agent based on whether its task survives quantization. Not every agent needs full FP16.
What was built:
-
CHRONICLE_AGENTSextended with per-agent fields:precision—int4for utility agents,fp16for frontier agentsmodel_size_b— 7B for utility, 13B for frontiergpu_tier—L4for utility,A100-40for frontiermonthly_gpu_cost_usd— $450 (L4), $1,500 (A100-40)survivability_note— why this precision is safe for this task
-
TASK_SURVIVABILITY_MATRIX— 11 task types tested at INT4. Results:- Survives INT4 (≥90% retention): intent classification, NER, sentiment, summarisation, data parsing, temporal sequencing, cross-source correlation
- Requires FP16 (<90% retention): structured generation, long-context coherence, multi-constraint reasoning, code generation
-
calculate_tiered_vram_budget()— replaces the uniform budget with per-agent precision. Reduced from 90 GB to ~84 GB. -
calculate_monthly_gpu_cost()— 3 GPU deployment scenarios:- Scenario A: All A100-80, no tiering → $9,375/mo
- Scenario B: 3× L4 (utility) + 2× A100-40 (frontier) → $4,350/mo, saves $60,300/yr
- Scenario C: 3× A10G + 2× A100-40 → $4,650/mo
-
task_survivability_matrix()— queryable by task type. -
chronicle_infer()updated with tier-aware prompts: utility agents get structured 2-sentence prompts, frontier agents get full analytical prompts. -
API endpoints added:
GET /vram-budget/tiered,GET /cost-model,GET /survivability,GET /calibration-stats -
Dashboard: Precision badges on agent cards (INT4 green, FP16 purple), tiered VRAM card, cost model card with 3 scenarios.
Key result: VRAM dropped from 90 GB to ~84 GB. Monthly GPU cost halved vs naive all-A100 setup.
Session 11.3 — GPU Resource Allocation (Current)
Goal: Lock the exact deployment configuration that prevents Chronicle from crashing at 2 AM. Every number calculated here goes into the actual vllm serve command.
What was built:
-
CHRONICLE_AGENTSextended with:max_model_len— 4,096 for utility agents, 8,192 for frontier agents. Without this lock, Llama-3 defaults to 128K context, consuming 64 GB KV cache per agent.gpu_memory_utilization— 0.28 for utility (co-located on shared L4), 0.85 for frontier (dedicated A100-40 with 15% safety buffer)
-
GPU_VRAM_GB— reference dict for all 6 GPU tiers (T4→H100-80). -
calculate_max_safe_concurrent()— the OOM prevention formula:Max Safe Concurrent = (Effective VRAM - Weights - Overhead - Buffer) / KV_per_requestResults: utility agents handle 1 concurrent request each on their L4 partition. Frontier agents handle 5 concurrent requests each on their A100-40.
-
oom_prevention_check()— runs the formula for all 5 agents at startup. If any agent returns 0 concurrent slots, Chronicle refuses to start. The crash is caught at deploy time, not at 2 AM. -
vllm_config_per_agent()— generates the exactvllm servecommand for each agent, including--max-model-len,--gpu-memory-utilization,--max-num-seqs,--tensor-parallel-size, and port assignments (8100–8104). -
colocation_partitioner()— validates the 3 utility agents fit on one shared L4:- 3 × 0.28 = 0.84 model fraction + 0.08 system overhead = 0.92 total (safe, ≤ 1.0)
- Remaining 1.9 GB headroom
-
kv_cache_growth_simulator()— simulates KV cache VRAM growth under a given requests-per-minute rate. Shows the exact minute OOM would occur without the concurrent request guard. -
calculate_tiered_vram_budget()updated — KV cache now calibrated to per-agentmax_model_len. Utility agents locked at 4K (2.0 GB KV each) instead of the conservative 8K estimate from S11.2, saving 6 GB total. -
calculate_monthly_gpu_cost()updated — Scenario D added (co-location):- 1× L4 shared by 3 utility agents + 2× A100-40 for frontier → $3,450/mo
- Saves $10,800/yr vs S11.2's separate-GPU approach
- Saves $71,100/yr vs naive all-A100 setup
-
chronicle_infer()updated — input length guard added. Requests longer than the agent'smax_model_lenare rejected before dispatch with a clear error message. -
API endpoints added:
GET /deployment-config,GET /oom-check,GET /concurrency-table -
Dashboard: Deployment config card (per-agent mml / util / concurrent slots), OOM safety card (✓ ALL AGENTS SAFE),
mml:badge on agent cards.
Session 11.3 verification — 5/5 checks:
- All 5 agents have
max_model_lenandgpu_memory_utilizationset - OOM prevention passes: all agents have
max_safe_concurrent > 0 - S11.3 calibrated VRAM (78.2 GB) < S11.2 conservative estimate (84.2 GB) — saves 6 GB
- Co-location partition valid: grand total 0.92 ≤ 1.0
- Scenario D ($3,450/mo) < Scenario B ($4,350/mo) — co-location wins
VRAM journey across Week 11:
S11.1 uniform FP16 (no tiering): 90.0 GB
S11.2 tiered precision (8K budget): 84.2 GB saved 5.8 GB
S11.3 calibrated max_model_len: 78.2 GB saved 11.8 GB total
Session 12.1 — FastAPI Gateway + MCP Ingestion (Current)
Goal: Put a real HTTP front door in front of Chronicle. Replace the direct Gemini REST calls with a compiled LangGraph swarm, validate every request before the graph boots, and pull data through an MCP client pool instead of hardcoded prompts.
What was built:
-
MCP_SOURCE_CONFIG— maps each of the 5 Chronicle data sources to an MCP server URL (localhost:3001–3005) and tool name. -
MCPClientPool— manages oneaiohttpsession per data source.fetch_source()calls the MCP server and falls back toCHRONICLE_CALIBRATION_DATASET(restored to its full 30 samples in this session — S11.3 had shipped it as an empty stub) when the server is unreachable. Every fetch reports aliveflag so downstream code always knows whether it got real or fallback data. No MCP servers actually exist yet in this exercise — every source currently resolves via the calibration fallback, which is expected. -
ChronicleState— a LangGraphTypedDictshared across all 5 agent nodes, threadingraw_data,sources_live,correlations,timeline_events,honest_analysis,final_brief,confidence, and a debugagent_trace. -
Five LangGraph node functions (
ingestion_node,pattern_node,timeline_node,brutality_node,synthesis_node) — utility-tier nodes use a cheap/fastChatGoogleGenerativeAIinstance, frontier-tier nodes use a slower/higher-quality one, mirroring the S11.2 precision tiers. -
build_chronicle_graph()— compiles a linearStateGraph:ingestion → pattern → timeline → brutality → synthesis → END. Compiled once at FastAPI startup vialifespan, not per-request. -
AnalysisRequestreplaced with aField-validated Pydantic model:question(1–2000 chars),data_sourcesrestricted to aLiteralof the 5 known sources,depthrestricted toquick/standard/deep. Invalid requests get a 422 in under a millisecond, before any Gemini call or graph work happens. -
AnalysisResponse— the new output contract:correlations,honest_analysis,final_brief,confidence(bounded 0–1),sources_used,sources_live,processing_ms, optionalagent_trace. -
The 3-level async chain is now real and verified end-to-end:
POST /analyze→await graph.ainvoke()→await llm.ainvoke()inside each node. -
API endpoints added:
GET /analyze/stream(501 stub — real SSE lands in S12.2),GET /health/live,GET /health/ready./healthnow reports live MCP connector status per source./calibration-statsrestored. -
Dashboard: MCP Data Connectors card (live/fallback badge per source), Gateway Status card (session, version, uptime, graph-compiled indicator).
Session 12.1 verification — 5/5 checks (makes real Gemini calls, ~10-15s):
build_chronicle_graph()compiles without error- Graph has all 5 Chronicle agent nodes
MCPClientPoolinstantiates correctly- Empty question correctly rejected by
AnalysisRequest(min_length=1) graph.ainvoke()returns a non-emptyfinal_briefend-to-end
What's Coming — Upcoming Sessions
Session 12.2 — SSE Streaming
Chronicle stops waiting for all 5 agents to finish before showing anything.
/analyzereplaced with a Server-Sent Events streaming endpoint- Tokens stream from each agent as they arrive — no more waiting for the slowest agent
- Per-agent streaming indicators in the dashboard
- Real TTFT measurement (first token, not first response)
Session 12.3 — Async Job Queue
Deep analyses that take longer than 30 seconds get queued properly.
POST /analyzereturns202 Acceptedwith a job ID immediatelyGET /jobs/{id}polls for result- Background worker processes the queue
- No more HTTP timeouts on long analyses
Session 13.1 — OpenTelemetry Tracing
Every agent request becomes a traceable span.
- OTel instrumentation on all 5 agents
- Distributed trace per analysis: one root span, 5 child spans (one per agent)
- Trace viewer card in the dashboard showing per-agent latency breakdown
- Export to any OTel-compatible backend (Jaeger, Grafana Tempo, etc.)
Session 14.1 — Semantic Caching
Reduce inference cost by catching semantically similar questions.
- Embedding-based cache: if a new question is >90% similar to a cached one, return the cached result
- Cache hit rate tracked per agent
- Reduces effective GPU-hours by 30–60% in practice
Session 14.2 — Per-Agent Spend Ledger
Know exactly what each agent costs per question, per day, per month.
- Token counting per agent per request
- Cost attribution: $X per question broken down by agent
- Monthly spend projection card in the dashboard
- Alert threshold: flag when spend exceeds a per-agent daily budget
Project Structure
chronicle/
├── agent.py # Inference core: LangGraph swarm, MCP pool, VRAM, OOM, vLLM config, cost model
├── api.py # FastAPI server: lifespan + all HTTP endpoints
├── index.html # Dashboard UI: chat + live metrics cards
├── requirements.txt # Python dependencies
├── .env # API key (never commit this)
├── Dockerfile # Container build
└── docker-compose.yml # Multi-service orchestration
agent.py is the source of truth. Every number in api.py and index.html comes from functions defined there. Sessions extend these files — nothing is ever removed.
Endpoints Reference
| Method | Path | Session | Description |
|---|---|---|---|
GET |
/ |
11.1 | Chronicle UI |
GET |
/health |
11.1, updated 12.1 | Version, OOM status, MCP connector status, agent configs |
GET |
/health/live |
12.1 | Liveness probe — process is running |
GET |
/health/ready |
12.1 | Readiness probe — 200 once graph + MCP pool are ready, else 503 |
POST |
/analyze |
11.1, replaced 12.1 | Runs the compiled LangGraph swarm via graph.ainvoke() |
GET |
/analyze/stream |
12.1 | 501 stub — real SSE streaming lands in Session 12.2 |
GET |
/vram-budget |
11.1 | Uniform VRAM at a given precision |
GET |
/vram-budget/tiered |
11.2 | Per-agent tiered VRAM breakdown |
GET |
/cost-model |
11.2 | 4 GPU deployment cost scenarios |
GET |
/survivability |
11.2 | INT4 task survivability matrix |
GET |
/calibration-stats |
11.2, restored 12.1 | 30-sample calibration dataset summary |
GET |
/deployment-config |
11.3 | vLLM launch commands per agent |
GET |
/oom-check |
11.3 | OOM prevention check per agent |
GET |
/concurrency-table |
11.3 | Context window vs concurrent capacity |
Troubleshooting
GEMINI_API_KEY environment variable is not set
Open .env and make sure the key is set with no quotes and no spaces around =:
GEMINI_API_KEY=AIza...your_key_here
address already in use on port 8000
Something is already running on port 8000. Kill it:
# macOS / Linux
lsof -ti :8000 | xargs kill -9
# Windows
netstat -ano | findstr :8000
taskkill /PID <pid> /F
Then restart with python api.py.
SSL certificate error on macOS
This is handled automatically via certifi. If it still appears, run:
/Applications/Python\ 3.x/Install\ Certificates.command
Replace 3.x with your Python version.
Dashboard cards show "API offline"
The UI is running but can't reach the API. Make sure python api.py (or docker compose up) is running, then refresh the page.
MCP Connectors card shows "fallback" for every source
This is expected in Session 12.1 — no MCP servers actually exist yet at localhost:3001–3005. MCPClientPool.fetch_source() tries each connection, fails, and falls back to CHRONICLE_CALIBRATION_DATASET. The client pool, live/fallback flag, and graceful degradation are all real and working; only the servers on the other end are stubs. Standing up real MCP servers for these 5 sources is out of scope for this session.
Docker: Cannot connect to the Docker daemon
Docker Desktop is not running. Open Docker Desktop from your Applications folder and wait for it to start (the whale icon in the menu bar stops animating when ready), then re-run docker compose up --build.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。