Skip to main content
In this tutorial, you’ll build a TypeScript function that lets an AI agent send notifications across multiple channels with a single API call. The agent decides what to communicate and how urgent it is. Courier handles channel selection, failover, and delivery.

Prerequisites

Before you start, make sure you have:

Which channels work out of the box?

Not every channel requires provider setup. Here’s what you can use right away and what needs configuration:
Channels without a configured provider show as Unroutable in the logs. Courier skips them automatically and tries the next channel in the list. Start with "low" urgency (inbox only) and add channels as you set up providers.

Project setup

1

Initialize the project

Create a new directory and install the Courier SDK:
2

Configure your API key

Create a .env file in your project root:
3

Create the project structure

Understanding the routing model

Every Courier send call accepts a routing object with two fields:
The channel array is your priority list. For single, Courier works through it top to bottom. For all, every channel fires at once.
For a full walkthrough of routing configuration (including the visual designer), see How to configure multi-channel routing.

Pattern 1: Urgency-based routing

The most common pattern for agent-driven notifications. Instead of hardcoding a channel, the agent expresses urgency and a helper function maps it to a routing strategy. Create src/send-notification.ts:
Here’s what each urgency level does:

Test it

Add a quick test script at the bottom of send-notification.ts (or in a separate file):
Start with low urgency to confirm your setup works. This sends to inbox only, which requires no provider configuration:
Check Courier Logs to confirm the notification was delivered to inbox. Then try higher urgency levels as you configure additional channels:
If a channel shows as Unroutable in the logs, that just means you haven’t configured a provider for it yet. With method: "single", Courier automatically skips to the next channel in the list, so your notification still gets delivered through whichever channels are set up.

Pattern 2: Channel failover

Some users don’t have push tokens configured. Some haven’t verified their phone number. With method: "single", Courier attempts each channel in order and stops at the first success:
If push fails (no device token), Courier tries email. If email fails (bad address), it tries SMS. If SMS fails, it falls back to inbox. The agent doesn’t need to check user profiles before sending.
The requestId returned by the send call lets you check delivery status later using the Messages API. This is useful for agents that need to confirm a notification landed before continuing.

Pattern 3: Provider failover

Channel failover handles “which channel.” Provider failover handles “which service within a channel.” If your primary email provider goes down, Courier can silently retry through a backup. Add a channels object to configure per-channel provider ordering:
This gives you two layers of failover:
  1. Channel level: email → push → inbox
  2. Provider level (within email): SendGrid → AWS SES
If SendGrid returns a 5xx, Courier retries through SES automatically.
You can configure provider failover for any channel, not just email. For example, set up Twilio as a primary SMS provider with Vonage as a backup.

Pattern 4: Template-based multi-channel

For notifications that need branded designs, channel-specific copy, or complex layouts, use a Courier template instead of inline content. Design the template once in the template designer, and Courier renders the appropriate version for each channel.
The data object passes dynamic values into your template variables. The email version can include a full HTML layout with error details, the push notification can be a short summary, and the inbox message can include action buttons.
To create the DEPLOYMENT_ALERT template, go to Templates, click New, and add channel blocks for each delivery channel. Use {service}, {environment}, and {exitCode} as template variables.

Exposing to your agent

The sendNotification function from Pattern 1 works as a tool in any agent framework. Here are three ways to connect it:

Option 1: Courier MCP server

If your agent runs in Cursor, Claude Code, or another MCP-compatible environment, the Courier MCP server exposes a send_message tool that already supports routing, channels, and template fields. No custom code needed. Add to your .cursor/mcp.json:

Option 2: Courier CLI

For agents that work through shell commands, use courier send message with the same JSON structure:
See the CLI reference for installation and full command documentation.

Option 3: Custom tool definition

Wrap sendNotification as a tool in your framework of choice. The function signature maps directly to a tool schema: userId, title, body, and urgency as parameters, with the urgency descriptions guiding the LLM’s selection. This works with OpenAI function calling, Vercel AI SDK, LangChain, or any framework that supports structured tool definitions.

Verify delivery

After sending, check delivery status in two ways:
  1. Courier Logs UI: Go to app.courier.com/logs to see the full delivery timeline for each notification, including which channels were attempted, which succeeded, and which providers were used.
  2. Messages API: Query delivery status programmatically:
In the logs, you’ll see one entry per channel attempted. Common statuses:

What’s next

Configure multi-channel routing

Set up routing rules in the Send API and the visual designer

Agent quickstart

Set up your AI agent with Courier’s MCP server, CLI, and Skills

CLI reference

Send and manage notifications from the command line

Send API reference

Full API documentation for the Send endpoint