Docs / AI agents

Available in v1.0

Connect your AI agent to Flowmails

Claude Code, Cursor, and Copilot do not need an inbox password — they need a contract they cannot misremember and a key scoped to one of your domains. Install the flowmails-sdk skill and the agent gets the constructor signature, five error classes, retry policy, and payload shapes in every session, then ships a working @flowmails/flowmails-sdk integration in one prompt. Nothing here needs a doc fetch.

What your agent can do today

  • Send mail from an address on your own domain through fm.send(SendOptions), with typed SendResult and typed errors.
  • Use a revocable, domain-bound key — the blast radius of a mistaken call is one mailbox, and you can revoke it in the dashboard without rotating anything upstream.
  • Read the result through the API. Inbound mail is queryable against the same scoped endpoint the send call uses, so "did my verification link arrive?" has an answer the agent can read.
  • Stay inside your zone. The from address must land on the key's bound domain, so the agent cannot send as someone else by guessing.
  • Wait for a specific mail with a durable wait_for_email (fm.waits.create) — it answers immediately and resolves when the message lands, without holding an HTTP request open. Poll it with fm.waits.get.
  • Read the inbound log with a cursor (fm.events.list), filtered by recipient, sender or subject. The event carries routing facts plus the subject and never a body; the body is an explicit fm.messages.get.
  • Poll a send's delivery state with fm.messages.status — sent / delivered / bounced / failed, plus the SMTP Message-ID.
  • Reply in thread by naming the parent (send({ replyToMessageId })); the SDK derives In-Reply-To and References so threads don't fork.
  • Create a mailbox from code — fm.addresses.create(domainId, "billing"). It is the one account-configuration write the agent surface has: idempotent, one local part, and it never changes a domain's routing mode. Everything else about account setup stays dashboard-only.
  • Call it over MCP — a hosted MCP server speaks MCP over streamable HTTP and exposes ten tools, each one checked against a per-tool scope before it runs. A scoped credential that may read inbound mail cannot also send.
  • Drive it from a shell — the flowmails CLI: login, test, addresses, watch and wait. watch and wait resume from their cursor after a disconnect, so a dropped connection never loses a message.
  • Look back and read the thread — fm.messages.search(domainId, { q }) for the mailbox history, and fm.threads.get(threadId) for the conversation a message belongs to.
  • Send exactly once on a retry — send({ idempotencyKey }) makes a retry replay the first answer instead of sending twice, and a send that exceeds the account’s quota is refused with a typed 429 rather than sent.
  • Scope the credential — issue a scoped credential in Settings → Agent Credentials with only the capabilities the agent needs. The raw key is shown once, only its hash is stored, and revoking it takes effect immediately.

Not shipped yet — roadmap, not vaporware

  • Delivery-status webhooks — roadmap, not shipped yet. The signed webhook itself fires for message.received and message.sent today; the delivered and bounced half needs the receive worker to report its status transitions — it has no bounce or DSN ingestion today, so a bounce is not observable at all.
  • Event-driven agent workflows — roadmap, not shipped, and deliberately so: the platform keeps the event log and the durable wait, and your agent's own code does the matching, extraction and action. Flowmails ships no rule engine, by decision rather than by omission.

The shipped MCP surface — the ten tools, their arguments and the scope each one needs — is documented on the API page. Delivery-status webhooks and event-driven workflows are the items still on the roadmap page.

Give it an AGENTS.md

The skill makes the agent correct inside a session; AGENTS.md keeps it correct across the ones where the skill is not installed yet. Drop this block at the repo root:

AGENTS.mdmd
# Email via Flowmails

- Outbound mail goes through @flowmails/flowmails-sdk only.
  Never hand-roll a fetch against the mail endpoint.
- Send with new Flowmails({ apiKey: process.env.FLOWMAILS_API_KEY })
  .send({ to, subject, text }) — the from-address is fixed by the key's
  bound domain; ask the user instead of inventing one.
- Flowmails does not approve sends; send only when the user's
  instruction calls for it. The key is bound to one domain and
  revocable in one click.
- Inbound mail: wait for it with fm.waits.create() and read it with
  fm.messages.get(messageId) — do not poll the inbox in a loop.
- Creating a mailbox is fm.addresses.create(domainId, "billing"); it is
  the only account-configuration write the SDK has. Everything else
  (domains, DNS, workers, API keys, routing mode) is dashboard-only.
- The platform ships no rule engine. The event log and the wait are
  state; deciding what a mail means is your code's job.

One-line install for AI agents

The flowmails-sdk skill is published to skills.sh. One command installs it into the agent’s skill library; after that, the SDK contract (Hard rules, the five error classes, retry policy, payload shapes, framework examples) is auto-injected into every session — the agent does not have to re-fetch any doc on every run.

terminalbash
npx skills add wms-why/flowmails-sdk-plugin@flowmails-sdk

The skill is the source of truth for the SDK’s call conventions. The HTML docs under /docs are the source of truth for the wire surface. Use both — the skill loads first, the doc is the fallback when something has just changed and the cached skill is one version behind.

New endpoints, error codes, or breaking changes to @flowmails/flowmails-sdk ship a matching skill update in the same release. The skill version tracks the SDK version (currently v1.0); npx skills update pulls the latest.

The five-line prompt

In any agent (Claude Code, Cursor, GitHub Copilot, Windsurf, Cody — or your own MCP client), paste this prompt. The agent will install the skill, internalize the SDK contract, and write the integration against @flowmails/flowmails-sdk.

prompt.mdmd
Make sure the `flowmails-sdk` skill is installed by running:

  npx skills add wms-why/flowmails-sdk-plugin@flowmails-sdk

Then add a Flowmails client to this project using an API key from
the FLOWMAILS_API_KEY environment variable, and wire it up so I
can call fm.send() from any server-side route / handler / API
endpoint with a typed SendOptions payload — and so a verification
flow can wait for the mail to arrive instead of polling:

  const wait = await fm.waits.create({ address, subject: "verify" });
  // poll fm.waits.get(wait.waitId), then
  // fm.messages.get(wait.resolvedMessageId) to read the code.

Do NOT bypass the SDK with raw fetch / axios / curl — always use
the SDK methods (send / events.list / messages.get / waits.* /
addresses.*). Branch errors with instanceof (AuthenticationError,
ValidationError, RateLimitError, UpstreamError, FlowmailsError).
The full class hierarchy and the HTTP → code matrix are baked
into the skill.

The agent will: (1) install the skill, (2) pick up the exact constructor signature and class names, (3) wire the integration in one shot. No website crawl, no hallucinated method signatures, no missing retry policy.

Tool-specific setup

Claude Code

Run the install line directly in the chat — Claude Code will pick up the skill from your project’s installed skill list automatically. You can also persist the five-line prompt above as a custom slash command:

terminalbash
mkdir -p .claude/commands
# Paste the five-line prompt into this file:
cat > .claude/commands/flowmails.md <<'PROMPT'
Make sure the `flowmails-sdk` skill is installed by running:
  npx skills add wms-why/flowmails-sdk-plugin@flowmails-sdk
…
PROMPT

Cursor

Run the install line in your terminal so the skill lands in your global skill library. Cursor picks up globally installed skills automatically — reference flowmails-sdk in chat (e.g. “use the flowmails-sdk skill to wire up an SDK client”) and the agent loads the contract before responding.

GitHub Copilot (workspace)

Run the install line so the skill lands in the workspace toolchain. For agents that don’t speak the skills protocol, save the five-line prompt to .github/copilot-instructions.md — Copilot indexes that file automatically and pulls it into its prompt context.

terminalbash
mkdir -p .github
# Either install the skill (preferred):
npx skills add wms-why/flowmails-sdk-plugin@flowmails-sdk
# Or, for agents without skill support, write the prompt directly:
cat > .github/copilot-instructions.md <<'PROMPT'
Make sure the `flowmails-sdk` skill is installed by running:
  npx skills add wms-why/flowmails-sdk-plugin@flowmails-sdk
…
PROMPT

Anything else (Continue.dev, Cody, Windsurf, Aider…)

If the tool supports the skills protocol, npx skills add wms-why/flowmails-sdk-plugin@flowmails-sdk is enough — the skill auto-injects on every session. For tools without skill support, fetch the raw SKILL.md from the upstream repo and inline it as system context.

What the agent gets right (because of the skill)

  • The exact class hierarchy. Five error classes extending FlowmailsError, each with the right HTTP status range and the right code strings. The agent will branch with instanceof, not by parsing the response body.
  • The constructor options. All five fields (apiKey, baseURL, fetch, maxRetries, requestId) with their defaults. The agent will not invent timeout or region options that don’t exist.
  • The exact method & type shapes. fm.send(SendOptions) returns SendResult; attachments are SendAttachment with Uint8Array auto-base64-encoded inside the SDK. The agent will pass typed fields to send, not hand-roll JSON literals or call the underlying REST surface.
  • The retry policy. 5xx / 408 / 429 + network only — never 4xx, never a 401. The agent will not wrap fm.send in its own retry loop.
  • The from-domain bound. from must land on the API key’s bound domain. The agent will not guess or invent a from address — it will ask the user.

What stays manual

The agent can’t mint an API key for you — the key is bound to one of your domains, and the SDK backend enforces that. Mint the key first, then point the agent at the skill.

  1. Go to Settings → API Keys in the Flowmails dashboard.
  2. Click Create key, name it, pick the domain the integration will send from.
  3. Copy the raw fm_… key (shown exactly once) into your environment as FLOWMAILS_API_KEY.
  4. Now run the agent prompt — it will install the skill, read the env var, wire up the client, and you’re done.

Versioning

The skill tracks @flowmails/flowmails-sdk v1.0. The SDK is published on npm — npm i @flowmails/flowmails-sdk. The wire surface and class hierarchy are stable within the v1.0.x line; breaking changes ship in the next minor line. The skill install line (npx skills add wms-why/flowmails-sdk-plugin@flowmails-sdk) is the user-facing surface — keep it in sync with the mirrorwms-why/flowmails-sdk-plugin repo slug.

The update contract is enforced: any change to the public SDK surface ships a matching skill update in the same release. Run npx skills update to pull the latest; the version in the badge above updates when you do.

Common questions

Ready to wire up the SDK