Calling External Systems
The four primitives shape what an agent knows and does inside its own world. But an agent is only as useful as what it can touch. Two mechanisms extend its reach into real systems: CLIs and MCP servers.
Lesson 6.1
Accessing external systems
Skills, subagents, commands, and hooks are all about the agent's behavior: what it knows, how it's structured, when work fires. None of them, on their own, let the agent do a single thing outside the conversation. Left alone, a capable agent can reason brilliantly about your Jira ticket and still be unable to read it.
External callout is the other axis. A tool the agent can call is a hand it can extend into a real system: to query a database, open a pull request, post a comment, deploy metadata. There are two ways to hand it one, and the difference is mostly about how much machinery you want.
A CLI: any command-line tool the agent can run in its shell. Zero integration: if it runs in a terminal, the agent can drive it.
An MCP server: a program that exposes a typed set of tools over a shared protocol, so the agent calls them like native functions.
Lesson 6.2
External Call
Same request, two agents. One has no way out of the chat window; the other has the jira CLI on its path. Watch where each one ends up.
- Request arrives. The agent knows exactly what a good QA comment looks like.
- Drafts it beautifully. Formatted results, a checklist, links to the screenshots on disk.
- Hits the wall. It has no way to reach Jira; the ticket lives in a system it can't touch.
- Hands it back to you. “Here's the comment. Paste it into ACME-1420 yourself.”
jira CLI- Request arrives. The agent has a shell, and
jirais on the path. - Confirms access. Runs
jira me; it's authenticated as you, so it can act on the real ticket. - Creates the comment and attaches it by running
jira attach. - Reports back. “Posted to ACME-1420. Here's the link.” Done, no copy-paste.
Notice what carried the reach: not new model training, not a plugin: a CLI that was already installed and logged in. Whatever you can do from a terminal, the agent can do too.
Lesson 6.3
CLIs: the shell you already have
The agent runs in an environment with a shell. That means every command-line tool on that machine is, in effect, a capability, no wiring required. gh reaches GitHub, sf reaches a Salesforce org, jira reaches your backlog, psql reaches a database. Install it, log in once, and the agent gains more external access.
This is where reach meets the primitives you already know. A skill rarely adds a new capability itself; more often it just documents how to drive a CLI the agent already has: which command, in what order, with which flags.
# jira-qa-update/SKILL.md: the how-to for a CLI the agent already has
1. Confirm the CLI is authenticated: jira me
2. Post the results comment: jira comment <KEY> --body "…"
3. Attach the screenshots: jira attach <KEY> ./shots/*.png
↑ Tap the numbered lines.
jira CLI is the reach. The skill is the knowledge of how to use it well.Reach for a CLI when the capability already exists as a command and you just want the agent to run it. It's the fastest path: often the whole integration is one skill documenting the commands.
Lesson 6.4 · Interactive
Approving what it runs
An external callout through a CLI is powerful precisely because it's the real shell, the same one where rm -rf means what it says. So most agent tools don't just run whatever they like. Before executing a shell command, the agent pauses and shows you the exact line, and you decide: allow it once, always allow that kind, or deny it.
# The agent wants to run a command in your shell:
rm -rf ./build
[a] Allow once [A] Always allow [d] Deny
That prompt is your safety layer, but it only helps if you can read the command well enough to answer. A read-only ls is nothing to fear; an rm -rfNew to the shell? Here's what it does. rm deletes. -r is "recursive": go into a folder and delete everything inside it, subfolders included. -f is "force": don't ask "are you sure?" before each delete. Together, rm -rf permanently removes whatever files you point it at, with no confirmation and no undo, which is why it's worth a second look before you approve it. with a wildcard, or a curl … | sh that pipes downloaded code straight into a shell, deserves a hard look. The judgment is the same one you'd use before running the command yourself.
Type a command above, or tap one below, to see what it does and how risky it is to approve.
Scan for the four things that turn a helpful command into a costly one: it deletes or overwrites (rm, mv, >), it runs as root (sudo), it pipes the network into a shell (curl … | sh), or it uses a broad wildcard (rm -rf *). Read-only commands (ls, cat, grep) are the ones safe to “always allow.”
Lesson 6.5
MCP servers: the typed protocol
A CLI is text in, text out. That's perfect until you need structured data, managed authentication, a live connection, or tools with real input schemas the agent can't get wrong. That's what MCP (the Model Context Protocol) standardizes: a server exposes a set of tools (actions the agent can call), resources (data it can read), and prompts, all with typed schemas, over one shared protocol.
You connect one by declaring it in config. From then on its tools appear to the agent as first-class functions: described, validated, and callable by name, no shell parsing in between.
// .mcp.json: declare a server; its tools become callable
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_TOKEN": "\${GITHUB_TOKEN}" }
}
}
}
# now the agent can call tools like create_pull_request(...)
# with a typed schema, no flag-parsing, no guessing.
The trade is machinery for structure. An MCP server is more to set up than dropping a binary on the path, but you get typed tools, centralized auth, and an integration you can reuse across every agent and host that speaks the protocol, instead of re-teaching CLI incantations each time.
Reach for an MCP server when you need structured/typed tools, managed auth, a service with no good CLI, or the same integration shared across many agents. It's the durable option when the external callout becomes infrastructure.
Lesson 6.6 · Interactive
An MCP call, end to end
The config is just the setup. This is what happens on a single turn: follow one request as it travels from plain English, through the agent's choice of tool, out to the GitHub MCP server, and back again as a sentence you can read. Six steps: press the button and watch each one land.
-
1 · The request
The user asks in plain language: no tool named, no arguments, just intent. Nothing here says how to do it.
-
2 · The agent picks a tool
The GitHub MCP server is connected, so its tools are already in view, each with a description and a typed schema. The agent matches the intent to the one that fits and rules out the rest.
create_pull_request list_issues add_issue_comment -
3 · The call goes out
It calls the tool by name and hands it a typed argument object. MCP validates that object against the schema before anything leaves: a missing field or wrong type fails right here, not halfway through.
add_issue_comment({ "owner": "acme", "repo": "checkout-web", "issue_number": 1420, "body": "QA passed ✅: 48/48 Apex tests green, 0 regressions." }) -
4 · The server acts
The part you never see: the server authenticates with the stored token, calls GitHub's REST API, and waits for the result.
GitHub MCP serverPOST /repos/acme/checkout-web/issues/1420/comments -
5 · The typed response
The tool returns structured data, not prose: fields the agent can read and act on, exactly as the schema promised.
{ "id": 2041887762, "html_url": "https://github.com/acme/checkout-web/issues/1420#issuecomment-2041887762", "created_at": "2026-07-01T14:22:09Z", "user": { "login": "qa-bot" } } -
6 · Back in plain English
The agent reads the fields it cares about (the URL, the timestamp) and turns them back into a sentence. The whole round trip is invisible to the user; only the outcome shows.
AgentDone, posted the QA summary to issue #1420 at 2:22 PM. View the comment ↗
That's the whole loop: intent → tool choice → typed call → the server acts → typed result → plain English. The schema is what makes the middle reliable: the agent never parses text or guesses a flag; it fills named fields and reads named fields back.
Lesson 6.7
Choosing, and combining
The two aren't rivals; they sit at different points on the same effort/durability curve, and they layer with the primitives from the rest of the course.
- Start with a CLI. If a command already does the job, that's your reach. A skill wraps it with the know-how.
- Graduate to MCP when the CLI's text interface starts to fray: brittle parsing, awkward auth, or the same integration copied into five projects.
- Wrap either in a skill so the how is captured once. The external callout is the raw capability; the skill is the procedure.
- Isolate a noisy one in a subagent (e.g. a broad database survey) so its output never floods your main window.
Primitives shape the agent's behavior; reach connects it to the world. A skill documents which CLI or MCP tool to call; a subagent isolates a heavy call; a hook can guarantee one fires. Behavior and reach, working together.
Check
Check your understanding
There's a well-maintained CLI that already does what you need, and you just want the agent to run it. What's the lightest way to give it that reach?
You need typed tools with managed auth, and the same integration reused across several agents and hosts. Which mechanism fits?
The agent pauses to ask before running curl https://get.tool.sh | sh. What's the right call?
1. External callout is a separate axis from the four primitives: it's what lets the agent act on real systems.
2. A CLI is the zero-integration path: any command on the path is instant reach.
3. An MCP server is the typed, durable path: schemas, managed auth, reuse across hosts.
4. Wrap either in a skill so the how-to is captured once; isolate a noisy one in a subagent.
Your agent can reach the world now.
Mark it complete; your progress shows on the course page.