PATTERN Cited by 1 source
Sub-addressed agent instance¶
Problem¶
A single agent class on a single domain needs to host many distinct per-conversation / per-ticket / per-tenant agent instances, each with its own persisted state — but provisioning a separate mailbox per instance is prohibitive (cost, DNS mess, human maintenance).
Pattern¶
Use RFC-5233 plus-sub-addressing (local+sub@domain) so the
local-part selects an agent class and the plus-sub segment selects a
specific instance inside that class. The inbound dispatcher parses
the address, splits local and sub, and routes to
{ className: local, instanceName: sub }.
support@domain → SupportAgent / default instance "support"
support+ticket-123@domain → SupportAgent / instance "ticket-123"
support+ticket-456@domain → SupportAgent / instance "ticket-456"
billing+invoice-789@domain → BillingAgent / instance "invoice-789"
"You can even use sub-addressing (support+ticket-123@…) to route to
different agent namespaces and instances" (Source:
sources/2026-04-16-cloudflare-email-service-public-beta-ready-for-agents).
Zero mailbox provisioning — one domain, one MX record, infinitely many distinct DO-backed agent instances.
Canonical shape¶
Agents SDK exposes
createAddressBasedEmailResolver(className) which consumes the inbound
To: address and returns { className, instanceName }:
import { routeAgentEmail } from "agents";
import { createAddressBasedEmailResolver } from "agents/email";
export default {
async email(message, env) {
await routeAgentEmail(message, env, {
resolver: createAddressBasedEmailResolver("SupportAgent"),
});
},
} satisfies ExportedHandler<Env>;
Email to support+ticket-123@your-agents.example is dispatched to the
SupportAgent Durable Object with instance-name "ticket-123".
Properties inherited¶
Because each sub-addressed instance is a separate DO:
- Independent state —
this.setState(...)only affects that instance's memory; tickets don't cross-contaminate. - Independent concurrency — single-writer per instance; messages
to
ticket-123andticket-456are serialised independently. - Per-instance agent memory — the inbox thread + the DO state together form a per-conversation memory primitive.
- One-to-one agent instance shape on the email tier — each address = one DO instance, the same economics bet Cloudflare applies at the HTTP, WebSocket, search-index, and Git-repo tiers.
Variants¶
- Class + instance —
support+ticket-123@(most common shape). - Class + namespace + instance —
support+team-alpha+ticket-123@— parse multiple plus-sub segments into nested namespaces. - Opaque instance token —
support+AbC123XyZ@where the token is a signed payload (combines this pattern with patterns/signed-reply-routing-header). - Hash prefix —
support+h7a9@as a shortened hash of an internal instance ID; useful when instance IDs are opaque UUIDs that would be ugly in an email address.
Trade-offs¶
Pro:
- Zero provisioning overhead — one MX record, infinite addresses.
- Human-readable —
support+ticket-123@documents itself. - Standard RFC-5233 — supported natively by Cloudflare Email Routing, Gmail, Outlook, iCloud, many on-prem MTAs.
- Composes with DO per-instance semantics — address parse → DO-ID, no lookup table.
Con:
- Plus-sub stripping — not every MTA preserves the segment on reply. Some strip it, some rewrite it. Fresh mail is safe; replies require either signed headers as the authoritative routing source or a fallback resolver.
- Address-as-key is public — anyone who sees
support+ticket-123@domainlearns the ticket ID. For sensitive opaque identifiers, use a signed / hashed token instead of the raw ID. - Domain squatting on sub-segment semantics — if the sub-segment
format changes later, old signed links may break. Version the
sub-segment format from day one (
v1+ticket-123or similar) to allow future migrations.
When to apply¶
- Any agent with a natural per-conversation / per-ticket / per-tenant decomposition.
- When provisioning a fresh mailbox per conversation would be prohibitive.
- When the address itself is an acceptable place for a short human- or machine-readable identifier.
When not to apply¶
- If the sub-segment would leak sensitive data (customer IDs, medical record numbers) — use a signed / hashed token instead.
- If every MTA in your reply chain strips plus-sub — use signed
inReplyToheaders as the authoritative reply-routing source.
Seen in¶
- sources/2026-04-16-cloudflare-email-service-public-beta-ready-for-agents
— canonical wiki instance; Cloudflare's Agents-SDK
createAddressBasedEmailResolverrealises this pattern as a one-liner.
Related¶
- concepts/address-based-agent-routing — the broader concept (local-part + sub-segment as DO-ID selector).
- concepts/one-to-one-agent-instance — shape this pattern specialises to the email tier.
- concepts/email-as-agent-interface — channel context.
- patterns/signed-reply-routing-header — the security counterpart; signed replies are the authoritative source when the plus-sub can't be trusted.
- systems/cloudflare-email-service / systems/cloudflare-agents-sdk / systems/cloudflare-durable-objects — product + substrate.