Through Sprint 13 · How the pieces fit together

Where The Pieces Live

Three diagrams. The first answers the question underneath your other questions: what's actually different between this conversation and the tool it's building — still true no matter how many sprints get added. The second is the tool itself, updated through Sprint 13 (a real database, a background job with live status). The third is every outside account this project touches, all of it live now.

1. This conversation, vs. the tool it's building

Everything in this chat happens in one place because it's one continuous agent — me — working across many steps. The code we've built is a completely different, much simpler thing once it runs.

You, right now, in this chat prompts results writes this code — can run it to test You directing this session FULL AGENT Claude Code has tools (edit files, run bash, push to git...) remembers this whole chat loops until the task's done pipeline/analyze.py — a plain python module one-shot claude api call Producer call reads the raw text, drafts findings no tools · no memory of anything else one-shot claude api call Verifier call separate request — checks the drafts never sees how the producer "thought" the code passes the output along — the two calls never talk directly
Claude Code (this chat) is a full agent — it has tools and loops through steps on its own, holding our entire conversation as context. The two Claude calls inside pipeline/analyze.py are a much simpler thing: each is a single request that gets a single response, with no tools and no memory — closer to "ask a question, get an answer" than to an agent. Plain Python code, not an AI deciding anything, is what chains them together — true in Sprint 4 and still true now that a database and a background job sit around it.

2. The pipeline, as built through Sprint 13

Read left to right, top row first. The dashboard submits audience + site + tag; everything from validation onward now runs in a background thread while the browser polls for status, and both the raw material and the findings land in Postgres instead of flat files.

next runs in a background thread — the browser polls a status endpoint meanwhile 01 Dashboard input audience + site + tag combobox /api/sites, /api/tags 02 Validate plain code, no AI checks site + tag are real 03 Recency guard plain code, checks the database warns on a near-duplicate rerun 04 Collector plain code, no AI Stack Exchange API + dates 05 · stage: analyzing Producer call one-shot Claude API call drafts the findings 06 Grounding check plain code, no AI quote must be a real, verbatim match 07 · stage: verifying Verifier call separate one-shot Claude API call checks each claim vs. source 08 · stage: done Save to database pipeline/db.py — one transaction a run row + its finding rows 09 Postgres runs + findings tables survives redeploys — Sprint 12 10 Web app dashboard, profile view polls status while 05-08 run 11 Exports plain code, no AI export_csv.py / export_xlsx.py 05 and 07 are two separate Claude calls — the second never sees how the first "thought," only what it produced.
Only two steps in this whole pipeline touch an AI model at all (05 and 07), and each is a narrow, one-shot request — not an agent, not a loop, no tools. Everything else — validation, the recency guard, collection, storage, the code-level grounding check, export — is plain, deterministic Python with no AI involved. What changed since Sprint 4: steps 02-08 now run in a background thread (the click that starts a run returns immediately), and 03/09 didn't exist at all — there was no recency check and no database, just flat files that reset on every Railway redeploy.
Full agent (tools, loop, memory)
One-shot Claude API call
Plain code, no AI
Data at rest

What's an "agent," really?

A program built on an LLM that loops: decide what to do, take an action (often using a tool), look at the result, decide the next thing — repeating until it's done. Claude Code, right here, is one. Typing into this chat is using an agent — there's no separate, hidden "agent" elsewhere; I'm it.

What's a "one-shot call"?

No loop, no tools, no memory beyond a single exchange: send a prompt, get an answer, done. The producer and verifier calls inside pipeline/analyze.py are this — much simpler than what I do in this conversation, and they don't know this chat exists at all.

Where's the "live status" coming from?

Not a second AI deciding to report in. The background thread just writes its current step ("collecting", "analyzing", ...) into a shared in-memory slot as it goes; the browser's own JavaScript asks a small endpoint "what's the status now?" every second or two and displays whatever it finds. Polling, not pushing — plain code on both ends.

3. Accounts & services — how they fit together

Every outside account this project (and its sibling, the twilightmesa.com marketing site) touches, and what each one is actually for. Everything below is live — no more "planned for a later sprint." No Google account is involved anywhere here — if that's what "Google console" meant, Anthropic Console is the one you're thinking of.

Claude Code this session network access: Full Anthropic Console console.anthropic.com API key + billing Stack Apps stackapps.com API key, raises quota audience- research-tool this project research.twilightmesa.com GitHub hosts both repos Railway hosts n8n and this app — one project, two services + a dedicated Postgres, not n8n's Cloudflare DNS twilightmesa.com + research subdomain Vercel hosts twilightmesa.com n8n on Railway runs contact form twilightmesa.com marketing site — separate project
Left of center: accounts dedicated to this tool. Right of center: the marketing site's own accounts. Middle column: shared infrastructure — GitHub hosts both repos, and Railway runs both n8n and this app as separate services in the same project. The dedicated Postgres service (Sprint 12) sits next to n8n's own, deliberately separate — sharing a database between two unrelated tools risks table-name collisions and mixes their data lifecycles for no real benefit.
A project
Anthropic / Claude account
Other account or host
Data at rest