A Python pipeline that watches Hacker News, builds a RAG knowledge base over what it finds, and runs a five-agent LLM team to produce an evidence-cited market report — scheduled and orchestrated by n8n, verified by CI on every push (pytest + eval gate, and a smoke render of the demo reel in both themes).
▶ Try the console — interactive preview (no install)
Two themes of the same 88-second walkthrough: dark (default) and light — the console supports both.
Every agent claim must cite a retrieved chunk; answers refuse to assert what the corpus doesn't support.
Agents emit structured JSON (claims + citations + verdicts), so the critic and the report render from data, not free-text markdown.
A labeled question set scores the index on every push; below-threshold retrieval fails the build.
| Metric | Value | Gate threshold | Status |
|---|---|---|---|
| Precision@5 | 0.400 | — | |
| Recall@5 | 0.820 | ≥ 0.700 | PASS |
| MRR | 1.000 | ≥ 0.800 | PASS |
| nDCG@5 | 1.000 | — |
Labeled eval set over the 83-post corpus · 115 chunks. Regression below the gate fails CI.
The report's citation health is checked mechanically by code, not by an LLM. On a live run the model cited a source that didn't exist — and the audit caught it:
n8n is not a diagram here — both workflows executed end-to-end against the live API through their schedule triggers, and Slack received the notifications (free incoming webhook).
| Execution | Workflow | Result | Receipt |
|---|---|---|---|
| #2 | corpus refresh 06:00 | fetch 195 · kept 161 · inserted 0 (dedup working) | Slack: "Corpus refreshed — 0 new posts (169 total)" |
| #6 | market report 07:00 | 43 poll loops · report succeeded in 1375 s · 22 evidence posts | Slack webhook answered ok |
| #7 | corpus refresh 06:00 (next day) | ONNX out of memory under RAM starvation → job failed cleanly | Slack: "⚠ Corpus refresh failed…" answered ok |
| #8 | corpus refresh 06:00 (manual fire) | first run after the in-place workflow re-import · job tagged source: "n8n" end to end | Slack: "Corpus refreshed — 0 new posts (169 total)" |
| #9 | market report 07:00 (manual fire) | 39 poll loops · succeeded in 1233 s · 21 evidence posts · verdicts 5 ✓ / 2 ~ / 15 ✗ | Slack webhook answered ok |
Every n8n-started job is tagged source: "n8n" end to end — job record, API responses, console badge — so scheduled runs are distinguishable from manual ones.
A deliberately-injected poll-loop bug (Route dropping poll_seconds) was caught by the first run and fixed — the demo found a real bug. Full log: n8n/LIVE_RUN_2026-09-27.md.