AI Market Intelligence & Product Strategy Agent

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).

v1.2.0 — CI green, 148 tests + gated retrieval eval Python · FastAPI · FastEmbed · sqlite-vec · n8n · Docker Multi-user · self-learning queries

▶ Try the console — interactive preview (no install)

Two themes of the same 88-second walkthrough: dark (default) and light — the console supports both.

Architecture

Hacker News ──▶ fetch (retries transient failures) ──▶ clean → chunk → embed (bge-small, FastEmbed) ──▶ SQLite + sqlite-vec (83 posts / 115 chunks) ──▶ retrieval ──▶ agents: Research → Competitor → Customer/UX → Strategy → Critic ──▶ typed JSON report + citation audit ──▶ FastAPI /ask · /reports · /pipeline/refresh · /eval ──▶ n8n schedules: corpus refresh 06:00 · report 07:00 → Slack

RAG, not vibes

Every agent claim must cite a retrieved chunk; answers refuse to assert what the corpus doesn't support.

Typed agent outputs

Agents emit structured JSON (claims + citations + verdicts), so the critic and the report render from data, not free-text markdown.

Evaluated retrieval

A labeled question set scores the index on every push; below-threshold retrieval fails the build.

Eval metrics (CI run, gate on)

MetricValueGate thresholdStatus
Precision@50.400—
Recall@50.820≥ 0.700PASS
MRR1.000≥ 0.800PASS
nDCG@51.000—

Labeled eval set over the 83-post corpus · 115 chunks. Regression below the gate fails CI.

The citation audit catches hallucinated sources

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:

Reference [10] — unresolved: report cites 10 sources, 9 evidence posts retrieved. Verdicts: 1 supported · 3 partial · 10 unsupported.
Mechanical audit: every [n] must point at real evidence; health is aggregated per report section and surfaced in the rendered output and the Slack summary.

The scheduler ran for real

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).

ExecutionWorkflowResultReceipt
#2corpus refresh 06:00fetch 195 · kept 161 · inserted 0 (dedup working)Slack: "Corpus refreshed — 0 new posts (169 total)"
#6market report 07:0043 poll loops · report succeeded in 1375 s · 22 evidence postsSlack webhook answered ok
#7corpus refresh 06:00 (next day)ONNX out of memory under RAM starvation → job failed cleanlySlack: "⚠ Corpus refresh failed…" answered ok
#8corpus refresh 06:00 (manual fire)first run after the in-place workflow re-import · job tagged source: "n8n" end to endSlack: "Corpus refreshed — 0 new posts (169 total)"
#9market 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.

Reproduce

git clone https://github.com/Aabyyss/AI-Market-Intelligence-Product-Strategy-Agent pip install -r requirements.txt -r requirements-dev.txt python run_corpus.py seed # build DB + vector index from the tracked fixture python run_eval.py # retrieval metrics + gate python run_report.py "ai agents" # full multi-agent report uvicorn market_intel.api:app # the service (or: docker compose up)