Guides/How to Build Notifications with AI Agents/Skill, MCP, CLI, or SDK: When to Use Which

Chapter 3

Skill, MCP, CLI, or SDK: When to Use Which

You now have four ways to get Courier work done. They're not alternatives to each other, and picking by habit is how people end up running a model inside a deploy pipeline.

how to build product notifications with AI

Last updated: September 2026

You now have four ways to get Courier work done. They're not alternatives to each other, and picking by habit is how people end up running a model inside a deploy pipeline.

The four surfaces, and why "agent" isn't one of them

A common way to frame this is "skills vs. CLI vs. API vs. agents." That's wrong in a way that makes the whole choice muddy. The agent is the actor, not a surface. It's the thing doing the work. These four are what it works through.

They split into two layers:

Knowledge. The skill teaches your agent how Courier works and which rules it can't break. The docs MCP server lets it look things up mid-task. Neither one changes anything in your workspace.

Action. The API MCP server acts on your workspace conversationally. The CLI runs deterministic commands. The SDK is what your application actually ships with.

Most setups want one from each layer. The skill plus MCP covers exploration. The skill plus the SDK covers production.

Which surface should I use for this task?

TaskReach forWhy
Explore a workspace you don't knowAPI MCPConversational. Nothing to look up
Prototype a template or journeyAPI MCPYou don't know what you want yet
Look up how something worksDocs MCP and the skillStops the agent guessing
Write app code that sendsSDKIt's production code. It belongs in your repo
Smoke test after a deployCLIDeterministic. No model in the pipeline
Scheduled or recurring operationCLISame reason
Debug a failed deliveryCLIThe messages listhistorycontent ladder
Bulk edit across many templatesCLI or SDKRepeatable and reviewable
Promote a template to productionDashboardThe documented path. See Chapter 8

When you don't want a model in the loop

MCP is probabilistic. You ask for something, the agent decides which tools to call and with what arguments, and it's usually right. "Usually right" is fine when you're exploring and a human is reading every response. It is not fine in a pipeline that sends real messages to real people.

The CLI is deterministic. The same command produces the same request every time. Nothing interprets your intent.

So the rule is about blast radius, not preference. If a mistake would reach users before a human sees it, take the model out of the loop:

# CI smoke test after deploy. Same request every run.
export COURIER_API_KEY="$COURIER_TEST_KEY"
courier send message \
--message '{"to":{"user_id":"smoke-test-user"},"template":"welcome"}' \
--format json

Use your agent to write that command. Don't use it to be that command.

MCP or the CLI?

There's a real argument that agents are better with CLIs than with MCP servers, because they already know how terminals work and a CLI gives them --help, pipes, and exit behavior they've seen ten thousand times. We've made that argument ourselves in why CLIs beat MCP servers, and it holds up.

The practical answer is that they're good at different moments:

MCP wins early. You don't know your workspace, you don't know what you want, and typing "what providers do I have connected?" beats reading a command reference. The feedback loop is the product.

The CLI wins once you know. You've figured out the shape of the thing, and now you want it to happen the same way twice, in a script, in CI, at 3am without you.

The transition point is the useful signal: the moment you find yourself asking your agent for the same thing twice, move it to the CLI.

Where the skill fits

The skill isn't a surface. It's a routing layer that makes the other three more reliable.

Your agent reads SKILL.md first. Inside is a table mapping tasks to the one or two reference files that answer them:

Working onRead
Transactional: password reset, OTP, orders, receiptstransactional.md
Multi-step sequences: delays, branches, batching, digestsjourneys.md
Template CRUD, publishing, versioning, rollbacktemplates.md
Templates as code: managing from a repo, CI/CDtemplates-as-code.md

Ask about an OTP flow and it loads the transactional and SMS guides. Nothing else loads. That's the difference between an agent with context and an agent with a context window full of things it doesn't need.

It's also a pattern worth stealing. If you have internal conventions your agent keeps getting wrong, a routing file plus short reference docs beats one enormous instructions file.

When to drop to the raw API

Two cases. Something the SDK doesn't wrap yet, and anything where you want the request to be completely explicit because you're debugging it.

Otherwise use the SDK. It's typed, it handles headers correctly, and it won't drift when an endpoint changes shape.

Frequently asked questions

Do I need the MCP server if I have the CLI?

No, but you'll probably want it while you're learning. The CLI is better at everything repeatable, and MCP is better at the part where you're still figuring out what to build. Once a task is settled, moving it to the CLI is usually the right call.

Can an agent use the CLI instead of MCP?

Yes, and many do it well. The CLI supports --format json on every command specifically so an agent can parse the output. Some people prefer this because the agent's actions become shell commands you can read, log, and re-run.

Is the skill required?

No. Your agent can work against Courier's API without it. The skill mainly stops two failure modes: inventing endpoints that don't exist, and getting the details wrong on things like idempotency and channel wrapping. It costs one command to install.

What should run in CI?

CLI commands, with a Test environment key stored as a CI secret. Smoke tests after a deploy, template validation, drift checks. Keep the model out of it. Use your agent to write the pipeline, then let the pipeline run without one.