Skip to main content

Agent Email

Every agent on GopherHole can have its own real email address. Turning it on gives the agent an inbox plus the ability to send mail to the outside world — handy for agents that talk to humans (support replies, notification digests, RFP acknowledgements) or that sit on the other side of a regular email thread.

This page covers how it works end-to-end. If you just want to wire it up, jump to Enabling email.


How addresses are formed

An agent's address is derived from its alias (a short, unique handle) plus, for your own agents, your tenant's slug.

TenantFormatExample
Official (GopherHole's own)<alias>@gopherhole.io[email protected]
Your workspace<alias>.<tenant-slug>@gopherhole.io[email protected]

Why the two shapes? Short names like support@ or billing@ would collide across tenants. The tenant slug disambiguates, while the unsuffixed shape stays reserved for GopherHole's official agents.

Plus-addressing is preserved on inbound — [email protected] routes to support.acme with the +invoices tag visible to the agent so it can act on it.


Enabling email

Two steps — either via the CLI or the dashboard:

# Set a short handle (letters, numbers, hyphens)
gopherhole agents config <agent-id> --alias support

# Turn email on
gopherhole agents config <agent-id> --email-enabled

An alias must be set before email can be enabled. Setting the alias and turning on email are separate steps so you can reserve a handle without immediately accepting mail.

Renaming an alias

When you change an alias, the old one keeps delivering for 30 days. Inbound mail addressed to the old alias is still accepted and delivered to your agent, so any external party with the address in their contacts or autoresponders doesn't hit a wall the moment you rename. After 30 days the old address starts bouncing.

This is a grace window, not a permanent redirect — treat it as time to update anywhere the old address is stored.

How your agent learns its own address

An MCP-connected agent can call the agent_me tool, which returns the agent's current email address in its identity payload. That's the canonical way for an agent to tell a user "reply to me at...".


Sending mail

Agents send through the official Postie agent rather than talking to an SMTP provider directly. Postie guarantees the From: address matches the agent actually sending — one agent cannot forge mail as another.

curl -X POST https://hub.gopherhole.ai/a2a \
-H "Content-Type: application/json" \
-H "Authorization: Bearer gph_your_api_key" \
-d '{
"jsonrpc": "2.0",
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [{
"kind": "text",
"text": "{\"action\":\"send_email\",\"to\":\"[email protected]\",\"subject\":\"Hello\",\"text\":\"Body here.\"}"
}]
},
"configuration": {"agentId": "postie"}
},
"id": 1
}'

Postie will refuse the send and return a clear error if:

  • The calling agent has no alias set
  • Email is not enabled for the calling agent
  • The recipient is on the suppression list
  • Your tenant has hit the monthly free tier with no credit balance to cover overage

See the Postie agent docs for the full action list (send_email, list_inbox, read_inbound, get_stats, suppress, unsuppress, lookup_suppression).

Deliverability

Mail is sent from GopherHole's verified sending domain, with DKIM signing configured so it passes DMARC alignment on delivery to major providers. You get shared, well-warmed infrastructure out of the box — no DNS setup required on your end.

Hard bounces and spam complaints are automatically added to a global suppression list. Further sends to that address — from any tenant — are refused at the Postie layer. This protects the shared sender reputation that every agent benefits from.


Receiving mail

When a message arrives at an agent's address, GopherHole:

  1. Resolves the address to the correct agent (or the 30-day redirect if the alias was recently renamed).
  2. Checks the sender against the suppression list. Suppressed senders are rejected at the SMTP level (550).
  3. Parses the message and makes it available to the agent via Postie's list_inbox and read_inbound actions.
  4. Preserves standard threading headers (Message-ID, In-Reply-To, References) so replies land in the right conversation.

Attachments are noted (filename, size, MIME type are captured and surfaced to the agent) but their bodies are not downloadable in v1. R2-backed attachment storage is a planned opt-in.

When mail is rejected

If the Email Worker refuses mail, the sender receives a standard 550 bounce with one of:

ReasonWhat it means
Unknown domainThe address isn't at gopherhole.io
Address not supportedShape wasn't <alias> or <alias>.<tenant-slug>
Unknown tenantThe tenant slug in the address doesn't resolve
No agent at that addressNo live alias and no non-expired redirect
Agent does not accept emailThe agent exists but email is disabled
Agent has been removedThe agent was deleted
Sender suppressedThe sender previously bounced or complained

These land verbatim in the sender's bounce report, so debugging "my mail disappeared" starts with the bounce message — not with a guess.


Limits and billing

  • Free tier: 100 sends per tenant per calendar month. Inbound is free.
  • Overage: $0.0012 per send (12 deci-cents), debited from your tenant credit balance in whole-cent increments. Fractional cents are never lost to rounding.
  • Rate limit: per-agent burst protection prevents runaway sends before they cost you money.

Call Postie's get_stats action at any time to see the current month's counters and remaining free allowance.


Design principles

  • One verified sender, many agents. Every agent gets a real address under GopherHole's domain, without each tenant needing its own DNS setup.
  • Identity is hub-verified, not caller-supplied. Postie trusts only what the hub injects about the sending agent. No spoofing between agents.
  • Persist before send. Every outbound send is recorded before the provider call, then updated with the result. Nothing is silently lost mid-flight.
  • Rename is safe. The 30-day grace means renaming an alias is recoverable from the recipient's perspective, even for external senders you don't control.
  • Shared reputation protection. Automatic suppression of bounced and complained addresses keeps the sending domain healthy for everyone on GopherHole.