jane@acme-outreach.com, not a connected Gmail or Outlook account. Mailboxes live on a sending domain you register through Cargo. You send from them with the native sendEmail action, the same way a play calls allocate or a connector action.
There is no HTTP “send” route. Delivery is a native action so workflows reuse orchestration’s pacing, retries, and credit charge. Direct delivery would skip all three.
How the pieces fit
- Register a domain with
defineDomain(or buy one in the UI). - Declare mailboxes on that domain with
defineMailbox. Google, shared, or private inboxes. - Start warm-up so the daily send ceiling can climb from 5 to 40 over 45 days.
- Send from a play or tool with
sendEmail({ mailboxUuid: jane.uuid, … }). Orchestration spaces those sends across the day and refuses once the rolling 24-hour allowance is spent. - Watch the thread — opens, clicks, replies, and unsubscribes land as events on the conversation.
sendEmail() helper, and Using the UI for the same flow in the app.
Register a sending domain
A mailbox can only be created on a domain the workspace already owns and that is active.defineDomain is the CDK resource for that:
domains/outreach.ts
adopt to register a new domain through Cargo. Registration charges workspace credits and is not refundable — a + create domain:… line in cargo-ai cdk plan is the signal, and the deploy confirmation is where it’s approved.
pending while the registrar provisions it. The deploy waits until it is active before publishing DNS or creating mailboxes.
The domain is addressed by its name, the way a member is addressed by email. If the workspace already owns that name and the spec does not say adopt: true, deploy fails with the way out (cargo-ai cdk import or adopt: true) rather than buying it a second time.
Declare a mailbox
defineMailbox provisions an inbox on that domain. Pass the domain handle — the deploy waits until the domain is active, creates the mailbox, and waits until the provider has issued credentials so a play in the same graph can send.
mailboxes/jane.ts
jane@acme-outreach.com. The slug is the CDK identity (mailbox:jane); username defaults to the slug. When two inboxes share a local part on different domains, pick a unique slug and set username explicitly:
jane.uuid is a deferred token. Pass it to sendEmail the same way you pass a capacity handle to allocate:
The workspace must have credits on file. Creating a mailbox charges a monthly fee in credits for as long as it exists (Google 125, shared and private 100). A send then charges 0.1 credits per delivered email.
destroy deletes a mailbox the CDK created (and stops the fee); an adopted mailbox is released, never deleted.
Provisioning is asynchronous. A new mailbox starts pending and becomes active once the provider has issued credentials. The deploy waits for that, the same way it waits for a domain registration. Only an active mailbox can send. Auth failure or a spam flag from the provider moves it to inactive and sending stops immediately.
Domain, username, and type are create-only. Changing them is a destroy plus a new defineMailbox. If the workspace already owns that address and the spec does not say adopt: true, deploy fails with the way out rather than provisioning a second inbox.
A mailbox created in the UI (or by an earlier deploy whose state file was lost) is bound the same way as a domain:
Organize with folders
Mailbox folders are a separate namespace from model or agent folders. Declare one withdefineFolder and pass the handle:
folders/outreach.ts
What a mailbox is not
Cargo mailboxes are not a replacement for Resend, SendGrid, or Lemlist. Those remain connector actions against your ESP or sequencer. A Cargo mailbox is an inbox the workspace owns, warmed and paced so cold outreach from a new domain does not burn the domain’s reputation.From the CLI
PreferdefineMailbox for the inbox itself. Use the CLI for warm-up, allowance, threads, events, and suppressions — the same surface as the mailbox management API.

