The engineering companion to "We Were Drowning in Slack. So We Built an AI Team to Run Our Studio." Everything below is the shipped system, not a design doc.
This is the map. It walks the whole runtime once, end to end, and links out to the post that goes deep on each piece. If you want one of those pieces rather than the tour, skip ahead: webhook alert dedup, exactly-once cron, the decision log, containing prompt injection, cost metering, or what we used instead of a framework.
The shape: one Worker, three files
The entire system is a single Cloudflare Worker. One entry point exports fetch (Slack events, GitHub webhooks, Google OAuth callback, /health) and scheduled (cron). The agent runtime itself is three files:
Component | Job | Size |
|---|---|---|
| Slack commands/mentions/DMs, cron ticks, and GitHub webhooks → one | 74 lines |
| decide which agent handles the event | 62 lines |
| build the tool set, run the LLM loop, return a result | 158 lines |
That is under 300 lines of runtime. The rest of the codebase is agents, tools, and the memory layer. Why it is deliberately that small, the full dependency ledger, and the honest version of "we didn't use a framework" are their own post.

Everything is channel-agnostic by design: Slack is v1, but agents never see Slack. They see a NormalizedEvent. Teams or email later means writing an adapter, not touching an agent.
Routing and the LLM loop
Slash commands and cron ticks carry an explicit agent hint and never touch an LLM to route. Only free text gets classified, by Haiku, the small cheap model. The loop that runs afterwards is bounded — 5 tool-use steps interactive, 30 for cron, hard-capped at 25 seconds against the Worker's ~30s ceiling — and a timeout cancels the in-flight call rather than orphaning it.
The principle is to pay for reasoning only when there is a decision to make. The routing and execution core takes both apart line by line.
The shared brain
All three agents read and write one Postgres database (Neon, through Cloudflare Hyperdrive). On top of it sits a knowledge layer: provenance on every row, 768-dimension embeddings in pgvector, a unified facts view across decisions, action items and meetings, and deterministic-first entity resolution that asks rather than guesses when two people share a name.
How a transcript becomes a row you can search months later is its own post. One security-relevant detail belongs here though: recalled memories are injected as user-role turns, never system-role, so a poisoned memory cannot impersonate the system prompt — the stored prompt-injection mitigation, covered in full in untrusted by default.
The ledger every run writes to
Every LLM invocation, router calls included, writes one row to an agent_runs table: trigger, timing, model, tokens, tools used, errors, and cost in integer microdollars. Two rules make it worth having. The run log is the last thing allowed to fail, so every path produces exactly one row including timeouts — a dashboard that only logs successes is a dashboard that lies. And the daily spend report is pure SQL with zero LLM calls, so observability pays for itself.
The unit, the pricing table and the arithmetic are in metering LLM cost in integer microdollars.
Safety guardrails
Raw tool errors never enter model context; a failed tool returns an opaque "Tool execution failed" and the real error goes to the run log. GitHub access is a read-only App scoped to our own org. OAuth refresh tokens are AES-256-GCM encrypted at rest. Cron jobs are idempotent, so "the cron fired twice" is a non-event rather than a duplicate message. Each of those is a property of the runtime rather than of any one agent, and how the runtime contains untrusted input is where they are argued properly.
Deployment
Two environments, prod and dev, each its own Worker and its own Slack app, so we can break dev in front of nobody. Deploys are wrangler deploy; secrets live in Cloudflare, never in the repo.
Building something like this, or wondering whether the pattern fits your stack? Get in touch
Back to the non-technical story: Read Part 0
.webp)
