Get started

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.

  1. 1Install

    git clone https://github.com/Agent-Emailing/agent-emailing-server.git
    cd agent-emailing-server
    npm install
    npm run build
  2. 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 email endpoint on its name card, so other agents can find it (section 5.1).

  3. 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 a deliver function, as the server's README shows.

  4. 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 carrier block 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.

  5. 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 price

    Try 17-forged.eml with --now 2026-10-29T17:15:00Z to see a failure. Add --as <agent id> to see the agent's verdict too: deliver, hold or refuse, with the reason. Without --now the 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.

  1. Download cases.json, cards.json and the seventeen fixtures.
  2. Give each fixture to your receiver as the case says, judged at the case's now, and compare its verdict with the case's expect. A case with after first replays the case it names.
  3. 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.