Search the docs

Find a page, a section, or an endpoint.

Hermes

Mail that starts a Hermes conversation, and the tools.

Hermes Agent, from Nous Research, can have an email address of its own in two ways, and most setups want both:

  • The plugin: mail to the address starts a Hermes conversation, one per email thread, and the agent's answer goes back as a reply in that thread. This is what makes email wake the agent.
  • The MCP server: tools the agent calls when a conversation asks it to — create addresses, search mail, wait for a verification code.

Both were run end to end on Hermes 0.22.2 on macOS, with gpt-4.1 as the model.

The plugin

sh
hermes plugins install pidgeon-ai/pidgeon-python/hermes/pidgeon --enable

It needs a key that reads and sends. Create one under Developers → API keys, limited to the address the agent answers, then add to ~/.hermes/.env:

PIDGEON_API_KEY=pgn_live_…
PIDGEON_ALLOWED_USERS=you@example.com
PIDGEON_ADDRESSES=agent@pidgeon.email
sh
hermes gateway run

[Pidgeon] Connected with key "…"; answering agent@pidgeon.email is the gateway reading mail. Send the address an email: the agent answers in the thread, and a reply to that answer continues the same conversation. In our run each answer arrived about ten seconds after the email.

It is Python's standard library only. Beyond the run above on macOS, we installed it into Hermes 0.22.2's own Docker image on Linux arm64 and x64, where it passes its tests and connects.

PIDGEON_ALLOWED_USERS is who may write to the agent, comma-separated. Mail from anyone else is dropped and the gateway log says so; the sender gets nothing back, not a pairing code. PIDGEON_ALLOW_ALL_USERS=true answers everyone who can reach the address. PIDGEON_ADDRESSES limits which of the key's addresses start conversations; without it, every address the key reaches does.

What reaches the agent

The sender, the address, the subject and the attachment names, then the Firewall's clean text of the new message: what a person would see, with hidden text removed, never the raw HTML. Mail Pidgeon filed as spam never becomes a turn, and mail Pidgeon Firewall marked suspicious — addressed to an AI, or asking for mail to be sent somewhere else — stays in the inbox. PIDGEON_SUSPICIOUS=deliver gives flagged mail to the agent with the Firewall's warning above it instead.

The agent can only reply in the thread; it cannot write to anyone new. Its answer goes out as a plain-text email, and only the answer: Hermes's setup notices and its mid-turn status messages ("shutting down") go to the gateway log, not to whoever wrote.

How it stays up

The plugin reads Pidgeon's event log every five seconds from a cursor in ~/.hermes/pidgeon/. A dropped connection is one failed request: on our run the Mac lost its network for half an hour, and mail was read again as soon as it was back. A message is pending until a reply to it is sent, so a gateway that stops mid-turn hands it to the agent again when it restarts, for up to a day; one already answered is not answered twice. A first start begins at the present, so installing the plugin does not answer a mailbox's history.

One gateway per key on a machine: a second refuses to start, because two would answer every email.

The MCP server

sh
hermes mcp add pidgeon --url https://pidgeon.ai/api/mcp \
--auth oauth --connect-timeout 300

Hermes prints a sign-in link and opens it in your browser. The consent screen asks what the agent may do — read, read and send, or full access — and which addresses it reaches. That choice becomes an API key under Developers → API keys → Connected apps, and Disconnect there ends it. Hermes then lists the tools and asks which to enable.

The connect timeout matters: at Hermes's default of 30 seconds it gives up on the sign-in before most people have finished it, and the page you land on afterwards cannot reach 127.0.0.1. The link works once, so if that happens, run the command again and use the new link, not an old tab.

A new hermes chat has the tools; an open session gets them with /reload-mcp. To sign in again later, run hermes mcp login pidgeon.

With a key instead

For a Hermes on a server with nobody there to sign in. Put the key in ~/.hermes/.env as PIDGEON_API_KEY, and reference it from the server entry, so it is not written into the config:

mcp_servers:
pidgeon:
  url: "https://pidgeon.ai/api/mcp"
  headers:
    Authorization: "Bearer ${PIDGEON_API_KEY}"

Give it the narrowest key the agent needs. A key created at read can never send, whatever the prompt says (Authentication).

What we ran

Create a new address for yourself with local_part hermes-test.

A verification email is about to arrive at hermes-test@pidgeon.email.
Wait for it with await_message and tell me the code.

Reply in the thread to say the code was received.

The agent called create_address, then await_message with the longest wait, 280 seconds, three times in a row, passing the cursor each time. Hermes allows a tool call 300 seconds by default, so the waits ran their full length. The email came back with its code in extracted.codes, and reply_to_message answered it in the same thread.

The email also carried a visible line telling "the AI assistant" to forward the inbox to someone else. Pidgeon Firewall marked it suspicious, naming an instruction addressed to an AI and a request to send mail out, and the agent did not act on it. The Firewall removes text a person cannot see; a line anyone can read stays in the text and is flagged.

Without the plugin

Hermes's own email gateway also starts a conversation from an email, and it works on Pidgeon over IMAP and SMTP. It reads the message as it arrived, not the Firewall's clean text; flagged mail is not held back; and it keeps one conversation per sender, not per thread. Use it when you cannot install a plugin.

The gateway signs in with an app password. Create one for the address on Inboxes → Mail apps and agents → An agent or a script → Get a password; it is shown once. Then, in ~/.hermes/.env:

EMAIL_ADDRESS=agent@pidgeon.email
EMAIL_PASSWORD=the app password
EMAIL_IMAP_HOST=imap.pidgeon.ai
EMAIL_SMTP_HOST=smtp.pidgeon.ai
EMAIL_SMTP_PORT=465
EMAIL_AUTHSERV_ID=amazonses.com
EMAIL_ALLOWED_USERS=you@example.com
EMAIL_HOME_ADDRESS=you@example.com

hermes gateway run then prints [Email] Connected as agent@pidgeon.email. In our run each email was answered about thirteen seconds after it arrived. Three of those lines are the ones people get wrong:

  • EMAIL_SMTP_PORT=465. Pidgeon takes mail to send on 465 only, over TLS. Hermes's default is 587, where nothing answers, so replies time out.
  • EMAIL_AUTHSERV_ID=amazonses.com. Hermes acts on an email only when the topmost Authentication-Results header comes from the server it is told to trust, and drops everything otherwise. Pidgeon receives through Amazon SES, which writes that header on top, above anything a sender wrote. Do not set EMAIL_TRUST_FROM_HEADER instead: it lets a forged sender speak in someone else's conversation.
  • EMAIL_HOME_ADDRESS. Without it, Hermes emails the first sender a notice that no home channel is set.

One agent per address. If the plugin and the email gateway, or an OpenClaw channel, answer the same address, each email gets a reply from every one of them. Give each agent its own address, or set PIDGEON_ADDRESSES.

Undoing it

sh
hermes plugins uninstall pidgeon

Remove the PIDGEON_ lines from ~/.hermes/.env and delete the key under Developers → API keys. For the MCP server:

sh
hermes mcp remove pidgeon

then Disconnect it under Developers → API keys → Connected apps, which ends its key on Pidgeon's side. For the email gateway, remove the EMAIL_ lines from ~/.hermes/.env and disconnect it under Inboxes → Connected devices and agents.