Recommended setup
The preferred way to bootstrap an org so it can act on its own — a Cloudflare token and an AgentMail key, provided once, and the org wires up the rest itself.
Last updated
The point of an org is that it does the work — including the setup work. The job at bootstrap time is to hand it the few credentials only a human can obtain, scoped broadly enough that it never has to come back mid-run asking for one more permission. Then it registers its own domain, deploys its own product, and wires its own email — with no dashboard steps left for you.
A few providers cover almost everything a product org needs:
- Cloudflare — hosting (Workers), data (D1, KV, R2), a domain (Registrar), and DNS — with separate staging and production environments.
- GitHub — the code of record and the CI/CD that deploys it, from one token.
- AgentMail — a real two-way mailbox on the org’s own domain, from one key.
Plus a brain for the agents. That’s the whole stack.
The principle: provision once, broadly
Every credential an org lacks becomes a stall — it stops and files a request, and you’re back in the loop. The fix is not to hand out permissions one 403 at a time; it’s to give the org a budget (its authorization to spend) and a token scoped for everything it might reasonably do, up front. After that it acts on its own: within budget it just proceeds, and it only asks you for something it genuinely cannot obtain itself.
Each org is self-contained — its own .env, its own keys. There are no
operator-wide globals; one org’s credentials never touch another’s.
Cloudflare — one token, scoped for the whole job
Create one API token (Cloudflare dashboard → My Profile → API Tokens → Create Token → Create Custom Token) with these permissions, and set Zone Resources → All zones from an account so a freshly-registered domain is covered without another edit:
| Type | Permission | Access |
|---|---|---|
| Account | Workers Scripts | Edit |
| Account | D1 | Edit |
| Account | Workers R2 Storage | Edit |
| Account | Cloudflare Registrar (Domain) | Edit |
| Account | Account Settings | Read |
| Zone | DNS | Edit |
| Zone | Workers Routes | Edit |
| Zone | Zone | Read |
Then add a payment method to the Cloudflare account — registering a domain costs real money, and the org spends it against its budget without asking.
That single token lets the org deploy Workers, provision D1/KV/R2, register its own domain, and edit DNS — the full build-and-ship loop.
Account-scoped tokens correctly return
401from/user/tokens/verify(that endpoint only validates user tokens). That is expected, not a broken token — the org checks itself withwrangler whoami.
AgentMail — a mailbox the org owns, on its own domain
Give the org one AgentMail key and it has email that both sends and receives,
with none of the sending-domain verification or scoped-key juggling that sinks
most autonomous email. Crucially, the mailbox lives on the org’s own domain,
not a shared one — support@yourproduct.com, not something@agentmail.to.
The org wires that itself, because it already holds the Cloudflare DNS token:
- Register the product’s domain (Cloudflare Registrar).
- Add the domain to AgentMail, read back its SPF/DKIM/DMARC records.
- Write those records into Cloudflare DNS (it has
DNS: Edit). - Verify the domain with AgentMail.
- Create the inbox on it — e.g.
support@yourproduct.com.
No operator dashboard steps. When it’s done, declare the channel in QUORUM.md
and the org sends and polls that inbox through the first-class agentmail
channel — see Acting in the world.
GitHub — the code of record, and how it ships
Product code shouldn’t live in one agent’s scratch folder. Give the org a
GitHub token and it keeps the product in a real repository — its durable
code of record, the same checkout for every agent, and the thing CI/CD deploys
from. On a dedicated account, create a classic personal access token with
the repo and workflow scopes (add delete_repo if you want
teardown to remove repos it made). Classic scopes are what keep an autonomous
run from stalling: they cover create-repo, push, set-Actions-secret, and
workflow edits in one grant, where a fine-grained token trips over creating a
repo and reaching one it doesn’t yet scope. Give it a long expiry for unattended
runs and rotate it periodically.
The org drives it with gh, no dashboard steps:
- Create the repo —
gh repo create <owner>/<name> --private --source . --push. - Commit and push as it works; make changes on branches and open pull requests.
- Add a GitHub Actions workflow that deploys to Cloudflare on every push.
- Set the Cloudflare token as a repository secret from the org’s own token —
gh secret set CLOUDFLARE_API_TOKEN— so Actions can deploy.
Staging and production, not one environment
The org runs the product in two environments: a staging deploy it breaks
things on, and a production deploy real users touch. Cloudflare Workers does
this natively — a [env.staging] and [env.production] block in
wrangler.toml, each with its own worker name, domain, and its own D1/KV/R2
bindings, so staging can never touch production data. The pipeline deploys to
staging on every push to main and to production only on a tagged
release (or a manual run), and the org verifies staging before promoting the
same build. Both show up as distinct entries on the service
registry — one staging, one production.
Putting it in the org
Credentials go in the org home’s .env (per org, gitignored):
# orgs/acme/.env
CLOUDFLARE_API_TOKEN=... # the broadly-scoped token above
CLOUDFLARE_ACCOUNT_ID=... # your account id
GITHUB_TOKEN=... # code repo + CI/CD (classic PAT: repo + workflow)
AGENTMAIL_API_KEY=... # one key: send + receive
And the email channel in QUORUM.md (the inbox is the address the org creates
on its domain during setup):
- channels: { "support": { "type": "agentmail", "inbox": "support@yourproduct.com", "secret": "agentmail-api-key" } }
Give it a mission and a budget, and it takes the product from an empty directory
to live on its own domain — deployed, emailing, and answering support@ — while
you watch from the dashboard.