Build Sprint · No. 01 · Season One
This is recap No. 01 of Build Sprint, an eighteen-Thursday live-build series at Granite City Coworking. Each week we ship a working thing you can take home. The prep page is for the forty-eight hours before; this is what remains after.
What we built
Thursday we did not build a chatbot. We deployed a small, production-grade agent that you talk to the way you already talk to people: by email. It gets its own address. You write to it, it reads the message, it thinks with Claude, and it replies on the same thread. Forwarding an email to it counts as a request. It lives on Cloudflare's free tier, awake while you're asleep, and redeploys itself when the code changes.
Three pieces make it work, and none of them is a demo tab. An inbox of its own, so it has an identity and a channel people already use. Hands in your other tools — Google Calendar first, then Gmail, Notion, GitHub — via Composio, so it can act instead of advise. A home in the cloud, so it is running when you aren't. Around that: a sender allowlist, loop protection, a two-second kill switch, and a single plain-English file that defines the agent's job.
Everybody in the room had a live agent within a few minutes of the Deploy to Cloudflare button. Visiting email-agent.YOUR-SUBDOMAIN.workers.dev should show ok. That is the whole put-in: not a dashboard, a URL that answers. The rest of the hour is keys, an inbox, and the first email from your phone.
You can rebuild this. The steps, the prompt library, the one-click deploy, and the troubleshooting list live in the Email Agent Protocol. The source is public. Open the Email Agent Protocol
Why it's built this way
Most "AI agent" tutorials end where the real work begins. You get a chat box in a browser tab that forgets everything, can't touch your calendar, and has no address anyone can reach. That is a toy with a nice landing page. An agent that earns its keep needs three things a chat tab will never give it: an identity other people can reach, permission to act inside tools a business already lives in, and a deployment that does not depend on your laptop being open.
Email is the identity on purpose. Everyone already knows how to send one. There is no new app to install for the people who want to talk to the agent. There is a thread, which is memory you can see. There is a From address, which is an allowlist you can enforce. The stack underneath — AgentMail for the inbox, a Cloudflare Worker as the front door, a Durable Object per conversation for memory, Claude for the brain, Composio for the hands — is replaceable one layer at a time. Content flows one way: email in, verify, remember, think (and act), email out. That's the whole thing.
The allowlist is not a nice-to-have. Skip ALLOWED_SENDERS and the agent will happily reply to anyone who finds the address, on your credits. That is the first real product decision of the season: this is small, and it is not pretend.
Making it yours is one file. src/prompt.ts holds the personality, who it works for, the timezone, standing rules like "keep replies under 100 words." Edit it on github.com, commit, push, Cloudflare redeploys. You do not need a local toolchain to change the agent's job. Claude Code is there when the change is code instead of English — connecting another Composio app, adding a standing behaviour — and the prompt below makes it tell you which kind you're dealing with before it touches anything.
The five secrets are the keyring: Anthropic for the brain, AgentMail for the inbox, Composio for the hands, ALLOWED_SENDERS for who it will talk to, and the webhook signing secret as proof that incoming mail is genuine. All five live in Cloudflare → Workers → email-agent → Settings → Variables and Secrets. SECRETS.md in the repo explains each one in plain English, including what breaks without it. That file is the real session handout.
Where it broke
No recording or transcript of this session was captured. The section below is reconstructed from the prep page and the designed failure modes we built around — not live notes from the room.
The session was designed around the thing that actually eats the hour: confirmation emails, missing secrets, and a sender who isn't on the list. The protocol's troubleshooting order is the reconstruction of what we built the room to survive.
No reply at all is almost always the allowlist. You email the agent from a second account, or from a phone that uses a different address than the one you pasted into Cloudflare, and the Worker silently ignores it. The fix is npx wrangler tail — the log says exactly what's wrong — and then adding the real From address to ALLOWED_SENDERS.
The next three are cousins of the same class. Missing secrets means a key never made it into the Cloudflare dashboard. signature verification FAILED means you re-ran setup and didn't paste the new whsec_... webhook secret. The agent going quiet mid-conversation is the five-replies-per-thread cap, which is loop protection, not a crash — start a new thread. Google Calendar "isn't connected" every time because the Composio link expires in ten minutes; ask again and click promptly, then wait thirty seconds before the second email.
That is why the session has a Plan B. npm run teardown disconnects the inbox in about two seconds. npm run local runs the identical brain on your laptop over a WebSocket, no public URL. If the cloud misbehaves in minute forty, nobody gets left at the put-in.
The prompts
The agent's personality is not buried in a dashboard. It is four blocks in src/prompt.ts. Change the file, push, Cloudflare redeploys. These are the two blocks that set the voice and the safety floor, plus the Claude Code prompt that turns the repo into a guided tour.
Replace the INSTRUCTIONS block, then tune the last two lines. This is the section that sets the agent's voice.
- Be concise and direct. Answer the question that was actually asked. - Write in plain text: no markdown syntax, no bullets-for-everything, no "I hope this email finds you well". - Sound like a capable human assistant, not a chatbot. - When a request is ambiguous, make the most reasonable assumption, state it in one line, and proceed. - Default reply length: under [N] words unless the request clearly needs more.
The safety floor. The last rule is worth keeping once you connect write-capable toolkits like Gmail or Notion.
- Never invent facts you were not given. If you don't know, say you don't know and ask. - If an email was forwarded to you, treat the forwarded content as the thing to act on, and reply to the person who forwarded it. - Your reply becomes the body of a real email. Do not include a subject line, "To:" headers, or a signature block — just the message. - Never send, delete, or modify anything in a connected app unless the request explicitly asks you to. Reading is fine; writing needs a clear instruction.
A good first prompt after deploying. Run it from the repo root.
You are working in the Modern-Zen/email-agent repository. Walk me through what happens, in order, from the moment an email arrives at the AgentMail inbox to the moment the reply is sent. Name the file and function responsible at each step (src/index.ts, the Durable Object, src/agent.ts, src/anthropic.ts), explain where conversation memory lives, and point out the three safety mechanisms (allowlist, signature verification, per-thread reply cap). Keep it to plain English with file references — I'm not a developer.
Take it home
The protocol is the rebuild. The repo is the thing you fork. The gear checklist is still useful the morning after if you didn't finish the accounts.
- Email Agent Protocol — Eight steps, prompt library, infrastructure walkthrough, gated behind an email.
- github.com/Modern-Zen/email-agent — The source. One-click deploy to Cloudflare copies it into your account.
- SECRETS.md — Every key explained in plain English, including what breaks without it.
Next Thursday: Run your whole social presence from a conversation
Session 02: Claude talks to Zernio, Zernio holds the tokens, and you stop logging into six places to publish one thought. Save a seat on the season calendar.
