Cold email for AI agents

How an AI agent can run cold email safely: what it can do over MCP, REST tools and the CLI, what stays with a person, and how mail it reads is fenced.

An AI agent can run most of outbound: search contacts, build segments, draft campaigns, triage replies and draft answers. Putting mail on the wire stays behind explicit permissions. In AY Inbox dashboard actions are reachable with an API key behind a scope (the few that must stay with a signed-in person each have a recorded reason), and no tool on the MCP or REST tool surfaces sends a message itself.

An AI agent here means a language model that calls tools in a loop: it reads a result, decides the next call, and keeps going until the task is done. The question for cold email is not whether a model can write an email (it can) but which of its calls are allowed to reach a real person's inbox.

Three doors, one registry

AY Inbox exposes one tool registry through three surfaces. Each tool checks its own scope, and the member behind the credential must also hold the matching workspace permission, so a tool behaves the same whichever door it came through.

DoorAddressUse it when
MCP serverhttps://api.ayinbox.com/v1/mcpYour agent speaks the Model Context Protocol: Claude Code, Claude Desktop, Cursor
REST agent toolsGET /v1/ai/tools and POST /v1/ai/tools/{name}/callA function-calling agent over plain HTTP: OpenAI-compatible, Hermes, LangChain, a script
ayinbox CLIayinbox tool list, ayinbox tool call, plus typed commandsAn agent that works in a terminal, or CI

The list a credential sees is already filtered: tools/list on MCP and GET /ai/tools return only the tools that credential may call. A credential with read scopes sees read tools; add write scopes and the write tools appear. The dashboard assistant runs the same registry as the signed-in member, and rate limits apply per key (or per user for OAuth tokens) exactly as on the rest of the API.

What an agent can do

The catalog is large, so it is grouped into toolsets a client can narrow to with ?toolsets=: inbox, campaigns, contacts, leads, crm, mailboxes, workspace, automation, forms, developer, research and analytics. A small model does best started on inbox alone. The filter only shortens the list; every call is gated the same way.

FamilyExamplesScope it needs
Readsearch_contacts, list_campaigns, get_campaign_stats, list_threads, get_thread, list_mailboxes, list_placement_testsThe matching READ_* scope
Writecreate_campaign_draft, add_campaign_step, create_segment, update_contact_fields, add_suppressions, CRM deals and tasksThe matching WRITE_* scope
Draftgenerate_reply_draft (the AI writes a reply, charged to credits, never sent), draft_reply (checks text you wrote against the campaign brain, no model)READ_UNIBOX plus AI_DRAFT for the first, READ_UNIBOX for the second
Leadsfind_leads (a Looot lead job with a max_cost_usd of 0.05 to 50), verify_emailINTEGRATIONS and BULK_CONTACTS for the first, WRITE_CONTACTS for the second
Booking prepget_availability, offer_meeting_times (prepares a block of times, sends nothing)READ_CONTACTS (plus READ_UNIBOX with a thread) for the first, WRITE_UNIBOX for the second

The full table, with every tool and its scope, is on the MCP server page.

What stays with a person

Some actions are not tools at all, whatever scope the credential holds:

  • Sending. send_reply, compose_email, run_placement_test and run_placement_batch are never listed or callable on MCP or the REST tools.
  • Booking a meeting. The scheduling provider mails an invitation to a real person, so book_meeting exists only in the dashboard assistant, where it always asks. Code books through POST /booking/offers/:id/book with its own key.
  • Lifting a stop or opening a lasting way out. remove_suppression (it can undo an unsubscribe or a complaint), creating or updating a webhook, and rotating a webhook secret stay with the assistant, which asks a person each time.
  • What the AI reads as instructions. No tool changes the workspace's product description, ideal customer notes, voice or playbooks, because every AI writing surface reads them.
  • Consent and first emails. No tool records a contact's prior consent or approves a first email in a review queue.
  • Governance. Team, invitations, roles, workspace settings writes and billing are not tools.

Beyond the tools, some REST routes refuse API keys altogether and answer only a signed-in person. Each has a recorded reason, for example: a person has to consent in a browser, the route changes how someone signs in or who can get in, it moves money, it exports or destroys the whole workspace (owner only), or it is one person's own screen. Connecting a mailbox is one of them, because it needs OAuth consent or a credential form in a browser.

Starting mail needs SEND_CAMPAIGNS

SEND_CAMPAIGNS is separate from WRITE_CAMPAIGNS on purpose: editing a draft and starting something that transmits are different blast radii. On the tool surfaces it gates:

  • set_campaign_status, which starts or stops a campaign
  • add_segment_to_campaign and set_campaign_segments into a campaign that is already sending, and widening a segment that feeds one
  • set_automation_enabled with enabled: true, and enabling auto-reply for the workspace or a campaign
  • find_leads when it names a campaign that is sending

An MCP client that registered itself over OAuth is never granted SEND_CAMPAIGNS (nor API_KEYS or WRITE_WORKSPACE). So the usual pattern is: the agent builds a draft campaign and its audience, and a member starts it. One subtlety is worth knowing: once a segment is linked to a sending campaign, a contact that comes to match it through an ordinary contact write is enrolled and mailed. Linking the segment is the decision that needs SEND_CAMPAIGNS.

WRITE_UNIBOX is the other scope to watch. No tool sends with it, but over plain REST it can send through POST /unibox/reply. Give a model a key without it unless the model's code is meant to send.

Mail is untrusted input

Anyone who can email the workspace, fill in a form or appear in an imported list writes text your agent reads. Two defences work together.

  1. Fenced results. Every tool result starts with one line saying everything between the markers is data, then the result between <<<UNTRUSTED_CONTENT>>> and <<<END_UNTRUSTED_CONTENT>>>. Markers inside the data are removed, so it cannot close the fence early. The only unfenced result is load_skill, your workspace's own playbook.
  2. A key that cannot do harm. The Agent: read and draft preset (84574239) holds every read scope plus AI_DRAFT. A steered model on that key can read and draft, and it holds no scope that writes or sends.

The fence lowers the odds that injected text steers the model. The scopes limit what a steered model can do. Rely on both, not on either alone. See Permissions for every scope and preset.

Retries without double effects

Agents retry, and a retried write should not happen twice. Every write tool's schema carries an optional idempotency_key: a retry with the same key and arguments returns the first result for 24 hours instead of running again. The key is bound to the credential that used it. A key reused with different arguments answers idempotency_key_reused, and a retry while the first call is still running answers tool_call_in_progress.

generate_reply_draft requires its key, and a key pays for one draft, so a new draft takes a new key. find_leads takes the key in its own arguments too: a retry with the same key returns the job it already started instead of starting and paying for a second one, while a retry without one starts a second job.

Where to start

Frequently asked questions

Can an AI agent send cold email through AY Inbox?

No tool on the MCP server or the REST tool endpoints sends a message. An agent can start a campaign, which then sends, only with the SEND_CAMPAIGNS scope, and an MCP client that registered itself over OAuth is never granted it. Without that scope, a person or your own code starts the mail.

Does AY Inbox have an MCP server?

Yes. It is at https://api.ayinbox.com/v1/mcp over streamable HTTP, and a self-hosted instance serves the same path on its own API host. Clients connect with an OAuth sign-in in the browser or with a scoped API key.

Should an agent use MCP, the REST tools or the CLI?

Whichever it already speaks. All three expose the same AY Inbox tool registry with the same scope checks: MCP for Claude Code, Claude Desktop or Cursor, GET /v1/ai/tools for a function-calling agent over HTTP, and the ayinbox CLI for an agent working in a terminal or CI.

How does AY Inbox stop an email from giving instructions to my agent?

Every tool result is fenced: one line says the content is data, then the result sits between <<<UNTRUSTED_CONTENT>>> and <<<END_UNTRUSTED_CONTENT>>> markers, and markers inside the data are removed. The fence lowers the odds that steering works; the scope rules limit what a steered model could do.

What happens when an agent retries a tool call?

With the same idempotency_key and arguments, AY Inbox returns the first result for 24 hours instead of running the write again. A key reused with different arguments answers idempotency_key_reused, and a retry while the first call still runs answers tool_call_in_progress.

On this page