Give an agent an email address
The Agent Emailing Server is the reference implementation of this standard. It holds one agent's key, watches its mailbox, checks every email, hands verified requests to the agent, and sends the agent's signed answers back in the same thread.
You need Node.js 22 or later, and a mailbox for the agent: its IMAP and SMTP settings, or an account with one of the email providers below. The server is free and open source under the Apache License 2.0, and needs nothing else installed to run.
-
1Install
git clone https://github.com/Agent-Emailing/agent-emailing-server.git cd agent-emailing-server npm install npm run build
-
2Make the agent's key
mkdir -p state node dist/server/cli.js keygen --out state/agent.seed
It prints the agent's id, its public key. Keep the seed file secret: it signs everything the agent sends. Publish the agent's mailbox as the
emailendpoint on its name card, so other agents can find it (section 5.1). -
3Connect a local agent
The agent is code you write. The server POSTs each verified email to it and sends whatever it answers. This small example answers every request with what it was asked:
AGENT_TOKEN=change-me node examples/echo-agent.mjs &
It listens on
http://127.0.0.1:8080/deliver, the address the example configuration points at. The agent is only ever handed envelopes that passed every check, with the sender's text framed for a model. The agent interface describes what it receives and how it answers. To run the server inside your own program instead, pass adeliverfunction, as the server's README shows. -
4Run the server
Against a mailbox, over IMAP and SMTP
Copy the example configuration and fill in the agent's address and its mail server.
cp examples/config.imap-smtp.json config.json MAILBOX_PASSWORD=... AGENT_TOKEN=change-me SERVER_TOKEN=change-me-too \ node dist/server/cli.js serve --config config.json
Against an email provider
Change the
carrierblock of the configuration. Secrets are never in the file: each is named by the environment variable that holds it. For Resend there is an example configuration,examples/config.resend.json. For AgentMail and Primitive the block is:"carrier": { "type": "agentmail", "apiKeyEnv": "AGENTMAIL_API_KEY", "inboxId": "<your inbox>" } "carrier": { "type": "primitive", "apiKeyEnv": "PRIMITIVE_API_KEY", "address": "<the agent's address>" }Cloudflare Email Service runs through a Worker, which the server's
examples/cloudflare-worker/folder holds. The provider interface lists every carrier's settings, and Email providers says which have been proven on real mail. -
5Check one email
The command line checks an email the way a mail program would, and says what an agent would do with it. Try it on the first conformance fixture, with the test name cards and the time the case is judged at:
curl -O https://agentemailing.ai/conformance/fixtures/01-request.eml curl -O https://agentemailing.ai/conformance/cards.json node dist/server/cli.js check 01-request.eml --cards cards.json --now 2026-10-29T16:25:00Z
For a person: the text matches the signed message ok signature (the envelope's signature verifies) ok text digest ok subject ok states the sender ok states what was asked ok states the message word for word ok names the file agenda.txt ok states the priceTry
17-forged.emlwith--now 2026-10-29T17:15:00Zto see a failure. Add--as <agent id>to see the agent's verdict too: deliver, hold or refuse, with the reason. Without--nowthe check uses the time it is run at, and the test name cards, which were valid for one hour, no longer verify.
Your own implementation
Run the conformance cases
The cases are the same for every implementation. Each one names an email fixture, the role that receives it, the agent it is received as, the time to judge it at, and the outcome it must produce. Every envelope in them is really signed with published test keys, which control nothing.
- Download cases.json, cards.json and the seventeen fixtures.
- Give each fixture to your receiver as the case says, judged at the case's
now, and compare its verdict with the case'sexpect. A case withafterfirst replays the case it names. - Where a case has a
person_view, run your mail-program check too, and compare that.
To see how it is done, check-fixtures.mjs is a
small reference receiver that runs every case. The Agent Emailing Server runs every case twice,
against its library and against a running server, with npm run conformance.
node conformance/check-fixtures.mjs # pass e01 01-request.eml # ... # all 19 cases pass
An implementation that passes every case can be listed under Implementations. Open an issue in the Common Agent Standards repository with a link to the implementation and its results.