- A Courier tool gives you tight control. You write one function that sends one published template, and the agent fills in only the fields your schema allows.
- The Courier MCP server gives the agent the full API: 170+ tools for sending, users, templates, and logs. You choose which of them run without a prompt.
Prerequisites
- An Anthropic API key
- Node.js 20 or later, or Python 3.10 or later
Set up the project
In a new folder, install the Agent SDK and the Courier SDK:.env file on its own:
Give the agent a Courier tool
1
Write the agent
The tool sends one template and takes three inputs. The schema rejects any status other than The SDK runs custom tools in an in-process MCP server, so the tool’s full name is
in_progress or resolved, so the agent can’t invent one. Save the file as agent.ts or agent.py.mcp__notifications__send_ticket_update. Listing it in allowedTools lets it run without a permission prompt. tools: [] removes Claude Code’s built-in tools, such as Bash and file edits, so this agent can only call your Courier tool.The Courier SDK retries failed requests, and the Idempotency-Key makes those retries safe: a retried request returns the first response instead of sending twice. Use a fresh key for each send. A key built from the ticket and status would replay a failed first attempt, and silence a second notice with the same status, for 25 hours.2
Run it
send_ticket_update and replies with the requestId. The template holds the content, so the agent picks the recipient and the moment without writing the message.Connect the Courier MCP server
1
Point the agent at the server
Pass the hosted server as an The system prompt names the template, and the agent sends it with
http MCP server, with your key in the api_key header. Save the file as agent.ts or agent.py.send_message_template. Only the tools in allowedTools run without a permission prompt, so add Courier tools there, such as mcp__courier__trace_message, as the agent needs them.The MCP send tools take a user_id or a list_id, not an email address, so the customer needs a saved profile.2
Run it
send_message_template and replies with the requestId.Ask a person for approval
Send a template with an action button to Slack, Microsoft Teams, or the Inbox, and point the button at a URL in your app. The click reaches your app, not Courier, so record the decision there and resume the agent. The , , , and pages cover each channel.Verify
1
Find the request in Logs
Copy the
requestId from the agent’s reply, open , and find that request. Logs are per environment, so a Test send appears only in Test logs.2
Confirm it delivered
Expand the message timeline and confirm the provider accepted it. A channel with no configured provider shows as
UNROUTABLE, so start with the inbox channel, which needs no setup.Next steps
- to test sends from Claude Code, Cursor, or Codex
- for every tool the server exposes
- for every field a send accepts
- , so a template mapped to a subscription topic respects each customer’s opt-outs