Skip to main content
Glama

agent-cold-email

launch_campaign

Destructive

Create and activate a campaign on a lead list. You supply name, offer, leads[], sequence[] (per step: subject, body, delayDays — subject is REQUIRED on step 1; a LATER step may omit it to keep step 1's subject line [recommended], which resolves at launch to "Re: " + step 1's subject (unchanged if that already starts with "Re: "), or set one explicitly to change only that step's subject line — every later step is still sent In-Reply-To step 1, though some mail clients display a changed subject as a separate conversation), and optionally timezone, sendWindow, stopOnReply, listSource (one sentence on where the list came from — REQUIRED on a crowdfunding account, where a missing or "unknown" source is refused 400) — the platform does not write copy. Each step's step number must be unique within the sequence; a duplicate step number is refused (400) naming it. Subjects and bodies may use {{firstName}} and {{company}} (filled from each lead); a launch is refused (400) if any subject or body uses any other {{token}}, a single-brace form of a known token such as {firstName} or {company} (a typo for the double-brace form — it would otherwise reach the recipient unsubstituted), or a run of 3 or more consecutive { or } anywhere (e.g. {{{firstName}}} or a lopsided run like {{{firstName}} — it would otherwise reach the recipient with stray braces attached). The send window is evaluated in timezone (IANA, e.g. America/New_York; default UTC) — set it to your recipients' zone. sendWindow is { startHour, endHour, days? }: integer hours 0-23, endHour INCLUSIVE (the last hour a send may start in), days 0=Sunday … 6=Saturday. Each omitted field (or all of them, by omitting sendWindow) gets the platform's RECOMMENDED default {"startHour":8,"endHour":16,"days":[1,2,3,4,5]} — Monday-Friday business hours — except on a sandbox account, where omitted fields are open every hour of every day until it upgrades and they take that default; the decision is yours, e.g. include 0 and 6 in days to send on weekends. Setting exactly ONE of startHour/endHour combines it with the recommended default for the OTHER (08/16, including on a sandbox account, since that value re-resolves to the same default on upgrade) — if that combination would wrap the window past midnight (start > end), the launch is refused; set both explicitly, including for a deliberate overnight window such as {startHour:22, endHour:6}. Step 1 goes out from the least-loaded mailbox; each later step goes out delayDays after the previous step ACTUALLY sent, from the SAME mailbox, with In-Reply-To/References set to step 1's Message-ID — it waits while that mailbox is at its daily cap, and the lead's remaining steps are cancelled (a 'failed' event says why) once that mailbox is paused or released, since neither ever lifts on its own, or when a paid account's thread went out from a connected BYO mailbox, which this build never sends from; a step whose previous step never went out is skipped. Suppressed leads are skipped. Returns { campaignId, sendWindow, timezone, nextSteps } — sendWindow and timezone are what actually applied. Campaigns send real mail, so a launch identical to one this account made in the last 60 seconds is REFUSED with 409 { code:'duplicate_campaign', existingCampaignId } rather than contacting the same prospects twice — check that campaign instead of relaunching. Resend the same idempotencyKey to retry a call whose response you lost: that replays the original result instead of being refused. Campaigns that differ in any field other than listSource (which is not part of that check), and deliberate relaunches after those 60 seconds, are never blocked.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYes
endByNoOptional fixed end date, as an ISO 8601 instant with a zone. From then on nothing more in this campaign sends: every step still waiting is skipped and recorded as a 'failed' event with reason campaign_ended. Paid accounts only: a trial account that sends one is refused 400. Must be later than now and later than every step's notBefore. Omit to let the sequence run to its end.
leadsYes
offerYes
sequenceYes
timezoneNoIANA time zone the send window is evaluated in — set it to your recipients' zone. Default UTC.UTC
listSourceNoWhere this lead list came from, in a sentence (e.g. "our own past-donor CRM export"). REQUIRED on a crowdfunding account: a launch with no source, or "unknown", is refused (400) — cold lists are allowed only with a stated source. Optional elsewhere. Max 500 characters.
sendWindowNoInteger hours 0-23 (endHour inclusive: the last hour a send may start in) and weekdays, evaluated in `timezone`. Each field you omit (or all of them, by omitting sendWindow) gets the recommended {"startHour":8,"endHour":16,"days":[1,2,3,4,5]} — except on a sandbox account, where omitted fields are open every hour of every day until it upgrades and they take the recommended default. If you set exactly ONE of startHour/endHour, the other still defaults to the recommended value (08/16) — if that combination would wrap past midnight (start > end), the launch is refused; set both explicitly, including for a deliberate overnight window.
stopOnReplyNo
idempotencyKeyNoOptional idempotency key: resend the SAME key when retrying this call so a dropped-response retry is not applied twice (no duplicate campaign/provision/send).

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed3 schema fields changed
    • addedInput schema / properties / endBy
      Added value: +{
      +  "description": "Optional fixed end date, as an ISO 8601 instant with a zone. From then on nothing more in this campaign sends: every step still waiting is skipped and recorded as a 'failed' event with reason campaign_ended. Paid accounts only: a trial account that sends one is refused 400. Must be later than now and later than every step's notBefore. Omit to let the sequence run to its end.",
      +  "format": "date-time",
      +  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      +  "type": "string"
      +}
    • addedInput schema / properties / listSource
      Added value: +{
      +  "description": "Where this lead list came from, in a sentence (e.g. \"our own past-donor CRM export\"). REQUIRED on a crowdfunding account: a launch with no source, or \"unknown\", is refused (400) — cold lists are allowed only with a stated source. Optional elsewhere. Max 500 characters.",
      +  "maxLength": 500,
      +  "type": "string"
      +}
    • addedInput schema / properties / sequence / items / properties / notBefore
      Added value: +{
      +  "description": "Optional fixed date this step is held until, as an ISO 8601 instant with a zone (e.g. \"2026-11-03T09:00:00-05:00\" or \"...Z\"). The step goes out at the later of notBefore and delayDays after the previous step actually sent, still inside sendWindow. Paid accounts only: a trial account that sends one is refused 400, so use delayDays while on trial. Omit to send on delayDays alone.",
      +  "format": "date-time",
      +  "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      +  "type": "string"
      +}
  2. Changed7 schema fields changed
    • removedInput schema / properties / sendWindow / default
      Removed value: -{
      -  "endHour": 23,
      -  "startHour": 0
      -}
    • addedInput schema / properties / sendWindow / description
      Added value: +"Integer hours 0-23 (endHour inclusive: the last hour a send may start in) and weekdays, evaluated in `timezone`. Each field you omit (or all of them, by omitting sendWindow) gets the recommended {\"startHour\":8,\"endHour\":16,\"days\":[1,2,3,4,5]} — except on a sandbox account, where omitted fields are open every hour of every day until it upgrades and they take the recommended default. If you set exactly ONE of startHour/endHour, the other still defaults to the recommended value (08/16) — if that combination would wrap past midnight (start > end), the launch is refused; set both explicitly, including for a deliberate overnight window."
    • addedInput schema / properties / sendWindow / properties / days
      Added value: +{
      +  "description": "Weekdays sends may go out on, in `timezone`: 0 = Sunday … 6 = Saturday. Omit for [1,2,3,4,5] (every day while the account is a sandbox); include 0 and 6 to send on weekends.",
      +  "items": {
      +    "maximum": 6,
      +    "minimum": 0,
      +    "type": "integer"
      +  },
      +  "maxItems": 7,
      +  "minItems": 1,
      +  "type": "array"
      +}
    • removedInput schema / properties / sendWindow / required
      Removed value: -[
      -  "startHour",
      -  "endHour"
      -]
    • addedInput schema / properties / sequence / items / properties / subject / description
      Added value: +"Required on step 1. A LATER step (step > 1) may omit it to keep step 1's subject line (recommended) — it resolves at launch to \"Re: \" + step 1's subject (unchanged if that already starts with \"Re: \"). Set one explicitly on a later step to change only its subject line: every later step is still sent In-Reply-To step 1, though some mail clients display a changed subject as a separate conversation."
    • changedInput schema / properties / sequence / items / required
      Previous value: -[
      -  "step",
      -  "subject",
      -  "body",
      -  "delayDays"
      -]New value: +[
      +  "step",
      +  "body",
      +  "delayDays"
      +]
    • addedInput schema / properties / timezone / description
      Added value: +"IANA time zone the send window is evaluated in — set it to your recipients' zone. Default UTC."
  3. First observed

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With only destructiveHint=true available as annotation, the description carries the full behavioral burden and does so richly: real mail is sent, 409 duplicate semantics with the 60s window, idempotency replay behavior, mailbox rotation and cap/pause effects on later steps, suppression skipping, and explicit 400 refusal reasons. This is far beyond what the annotation covers.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core purpose is front-loaded, but the body is a single sprawling block that runs to roughly 2,000 characters and repeats material already in the schema (the step-1 subject rule appears in both the description and the schema property). Much of the content is valuable but oversized and hard to parse for an agent deciding whether to call it.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-param, deeply nested mutation tool with no output schema, the description covers the mutation semantics, default resolution, failure modes, and even the return shape ({ campaignId, sendWindow, timezone, nextSteps }). Nothing an agent needs to invoke this correctly appears to be missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50% across 10 params, and the description compensates with rules the schema omits entirely: unique step numbers, token whitelist ({{firstName}}/{{company}}), single-brace and 3+ brace refusal, and the startHour/endHour combination default. Some blocks (subject, timezone, sendWindow, listSource) largely restate the schema descriptions rather than extend them, preventing a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Starts with a specific verb+resource ("Create and activate a campaign on a lead list") and enumerates the required inputs, so the agent knows exactly what this does. It does not explicitly name or distinguish itself from the adjacent siblings plan_campaign or list_campaigns, keeping it at 4 rather than 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete when-not conditions (identical launch within 60s is refused, sandbox vs paid differences, trial accounts refused for endBy/notBefore) and tells the agent to check the existing campaign instead of relaunching, which implies the listing/results siblings. It stops short of explicitly naming the alternative tool for planning or inspecting campaigns.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources