Macrae
Updated 2026-10-08 20:15 · status: modules built, integration running
A voice agent for the Jungwirth group (IOCB Prague): it knows the group's papers, answers with citations, and when you click a task it does real work on cloud hardware, so you can watch exactly which papers it read and which calculations it ran.
1 · The pieces
The browser only talks to one Cloudflare address. The Worker serves the page, hands the browser a
short-lived ElevenLabs voice session, and forwards /api calls to the backend with a secret header
the browser never sees. The backend answers paper questions from its own index and starts tasks as
agent-runner flows; Harbor runs each agent step in a sandbox on Modal and keeps the full trace.
2 · What happens when you…
- Page asks the Worker for a signed URL; the voice session starts in the browser.
- The ElevenLabs agent calls
search_papers, a webhook that goes straight to the backend. - RAG returns the best passages, numbered
[1] [2], with title, authors, page, DOI. - The agent answers only from those passages and says the source ("Košťál 2026, page 3").
- It calls the page's
show_citations; the cards appear beside the transcript.
POST /api/tasks/{id}/startstarts the task's flow in the background →run_id.- Script steps pull paper passages from RAG; agent steps run in Modal sandboxes.
- The page polls
/api/runs/{id}/events: each tool call becomes a timeline row (📄 read, 🧮 calc, ✍️ write…). - A
check:verifies the output (e.g.result.jsonhas numbers) → reward. - The agent narrates progress from
run_status; the full trace is kept (container disk, copied to R2).
3 · Code map
| folder | what's in it | status |
|---|---|---|
data/, scripts/ | 479 group publications (titles, authors, DOIs) from the IOCB site | done |
web/ | landing (task cards, "Talk to the agent", try-asking chips, typed questions that search the papers even without voice), run view (live timeline 📄🔎🧮✍️✅, counters, cited papers, steps), offline state, light/dark | built |
cloudflare/ | Worker macrae: serves the page, proxies /api, ElevenLabs signed URL, rate limits; local dev server + mock backend | built |
server/ | FastAPI: tasks, runs, trace events (tool calls → read / calc / write…), search, ElevenLabs tools; 51 tests | built |
rag/ | PDF → clean pages (headers, hyphenation, reference lists removed) → chunks; BM25 + bge-small embeddings, fused ranking; [n] citations with page | built |
tasks/ | 2 placeholder tasks (methods card, small calculation on Modal) + Modal support in agent-runner | built your tasks: pending |
voice/ | ElevenLabs agent "macrae" (Claude Sonnet 5.5 via ElevenLabs, cites every claim), three server tools, setup script checked against the live API | built |
deploy/ | backend Dockerfile (Harbor uses Modal, no Docker needed inside), scripts, Makefile | built → Cloudflare Container |
| whole system | integrator agent fixes the seams between modules and tests end to end | running |
4 · Where it runs: all on Cloudflare
The page, the Worker and the backend live on one Cloudflare account and one address, deployed with
wrangler deploy. The backend is a Cloudflare Container (the same Docker image) that stays awake
about two hours after use so running tasks aren't cut off. Its disk is temporary, so the paper index is baked into
the image and run traces are copied to R2. The heavy work (agents, calculations) runs in Modal sandboxes.
AWS was the first plan and is no longer needed.
5 · How it was built
With agent-runner itself. A written contract (CONTRACT.md) fixed every interface, then six
Claude Opus 5.5 agents (high effort) built their modules at the same time across three Claude accounts, each in
its own container. All six passed their checks on the first attempt.
| module | time | cost (API-equivalent) |
|---|---|---|
| web + Worker | 18.5 min | $5.24 |
| server | 14.4 min | $3.86 |
| rag | 15.6 min | $3.41 |
| tasks + Modal | 16.5 min | $4.95 |
| voice | 10.2 min | $2.99 |
| deploy | 15.7 min | $3.44 |
| total | ~19 min wall clock | $23.90, on Claude subscriptions |
Next in the same flow: an integrator agent fixes mismatches and tests the whole system, then the site deploys. A second flow then moves the backend into a Cloudflare Container with R2.
6 · What the owner provides
| item | status |
|---|---|
| ElevenLabs API key | provided verified |
| Claude login for the agents | provided verified (to be replaced with a fresh key) |
| Modal token (dedicated, for the container) | pending |
| Paper PDFs | pending indexed on the server, never published |
| The 2–3 clickable tasks | pending two placeholders until then |
| Hosting | decided Cloudflare |
Glossary
| RAG | Retrieval-augmented generation: find the relevant passages first, answer only from them, cite them. |
| Harbor | Open-source harness that runs an agent in a sandbox and saves its trajectory, reward and files. |
| Modal | Cloud that starts sandboxes/containers on demand, CPU or GPU, billed per second. |
| Trace / trajectory | Every message, tool call and result of one agent run. |
| Worker | Small program on Cloudflare's edge that serves the site and forwards API calls. |
| Signed URL | A short-lived link that lets the browser open a voice session without seeing the API key. |