- Agents
- Orchestration Patterns
Three primitives, three roles
Claude Code exposes three primitives to structure a workflow: Command, Agent, and Skill. Many beginners confuse them or use one where another would fit better. This guide lays out the reference orchestration pattern: Command → Agent → Skill.
| Primitive | Role | Typical invocation |
|---|---|---|
| Command (slash command) | Entry point, orchestrator | User types /my-command |
| Agent (subagent) | Autonomous execution unit with its own context | The command calls Agent(...) |
| Skill | Reusable, deterministic recipe, optionally preloaded | The agent calls Skill(skill: "my-skill") or preloads it via frontmatter |
The golden rule: the Command directs, the Agent decides, the Skill executes. Mixing those roles produces hard-to-maintain code and unpredictable behavior.
Standalone Skill vs Agent Skill
This is the most common confusion. There are two ways to use a Skill:
Standalone Skill
The Skill is invoked on demand, from the main session, via Skill(skill: "weather-svg-creator"). Its content is loaded at invocation time, then released. Useful when:
- The Skill runs only once in the session
- Multiple agents could call it independently
- You want strict isolation between caller and Skill
# Standalone Skill frontmatter---name: weather-svg-creatordescription: Generates a weather SVG from structured dataallowed-tools:- Write- Bashuser-invocable: true---
Agent Skill (preloaded)
The Skill is listed in an agent's skills: frontmatter. On every run of that agent, the Skill is preloaded into its initial context. No Skill(...) call needed. Useful when:
- The agent systematically needs that capability
- You want to cut tokens spent at invocation (preloaded once)
- The Skill is a foundational component of the agent
# Agent frontmatter---name: weather-agentmodel: sonnetskills:- weather-fetcherallowedTools:- Read- Skill---
The fetch/render pattern
Boris Cherny popularized a pattern that splits two responsibilities often blended together:
- Fetch: get the data (API, file, database)
- Render: format that data into output (markdown, SVG, JSON, terminal output)
The classic mistake is doing everything in a single agent. Result: a huge agent prompt doing two jobs and regularly missing one of them.
Recommended architecture
/weather-orchestrator (Command)
│
├──> Agent(weather-agent) [FETCH]
│ └─ skills: [weather-fetcher]
│ └─ allowed-tools: WebFetch
│
└──> Skill(weather-svg-creator) [RENDER]
└─ allowed-tools: Write, Bash
The Command orchestrates the two steps. The Agent fetches data via the weather-fetcher Skill. The weather-svg-creator Skill takes structured data and produces an SVG. Each actor has a clear responsibility and a tight permission scope.
The Execution Contract
When you orchestrate several primitives, some rules are non-negotiable: one agent should not do another's job, one step should not be skipped. The Execution Contract is a prompt pattern that locks those rules directly in the Command.
Concrete example
# /weather-orchestrator## Execution Contract (non-negotiable)You are forbidden from:- Fetching weather data yourself via Bash, WebFetch, or any other tool- Skipping Step 1- Calling weather-svg-creator before the agent has returned dataYou MUST:1. Call Agent(weather-agent) with the user's location2. Wait for its structured output3. Call Skill(weather-svg-creator) with the agent's output## Steps...
The contract isn't code, it's a natural-language directive at the top of the Command's prompt. Claude respects it because it's explicit, short, and stated as binary rules (forbidden / MUST).
Defensive tool allowlist
The contract alone isn't enough. To guarantee an agent won't do another's job, configure its allowedTools restrictively.
Example: a weather-agent that must go through the weather-fetcher Skill should not have direct access to WebFetch. If WebFetch is in its allowedTools, Claude might be tempted to bypass the Skill.
---name: weather-agentmodel: sonnetskills:- weather-fetcherallowedTools:- Read- Skill# No WebFetch here, intentionallydisallowedTools:- WebFetch- Bash---
This is the fail-closed guardrail: by default, the tool is forbidden. If the agent needs WebFetch, it must go through the weather-fetcher Skill, which has the permission. The indirection makes the pattern explicit and auditable.
When to use what
Here's a simplified decision grid:
| You want to... | Use |
|---|---|
| Trigger a full workflow from a user command | Command |
| Delegate an autonomous task with its own context | Agent |
| Encapsulate a deterministic, reusable recipe (API, format) | Standalone Skill |
| Systematically give an agent a capability | Agent Skill (skills: frontmatter) |
| Force a multi-step mandatory workflow | Command + Execution Contract |
| Prevent an agent from bypassing a Skill | Restrictive allowedTools |
Common anti-patterns
A few patterns you'll often see and should avoid:
"An agent that does everything"
A giant agent with a 400-line prompt covering fetch + render + validation + reporting. When something breaks, you never know where. Split into multiple agents/skills.
"Skill with business logic"
A Skill that makes decisions (complex if/else). The Skill should be deterministic. If you need decisions, that's an agent's job, not a skill's.
"Command without Execution Contract"
A Command that just says "call agent X, do this". Without an explicit contract, Claude takes shortcuts. Be explicit about what is mandatory and what is forbidden.
"Permissive tool allowlist"
Giving ["*"] or all tools to an agent out of laziness. Consequence: contracts aren't respected and primitive routing collapses.
Full example: bug hunting
Putting it all together on a real case: a /find-bug workflow that takes a suspicious file and outputs a report.
/find-bug src/auth.ts
│
├──> Agent(code-explorer) [FETCH context]
│ allowed-tools: [Read, Grep]
│ skills: [astrep-parser]
│
├──> Agent(bug-hunter) [DECIDE: where bugs are]
│ allowed-tools: [Read, Skill]
│ skills: [vulnerability-patterns]
│
└──> Skill(report-formatter) [RENDER the report]
allowed-tools: [Write]
The Execution Contract in /find-bug:
You are forbidden from:- Reading the file yourself directly (must go through code-explorer)- Skipping bug-hunter even if you think you see the bugYou MUST:1. Call Agent(code-explorer) with the target file2. Pass its output verbatim to Agent(bug-hunter)3. Pass bug-hunter's findings to Skill(report-formatter)
Three primitives, three roles, one contract. The workflow is readable, auditable, testable independently.
Next steps
- Advanced multi-agent orchestration for fan-out/fan-in and pipeline patterns
- Create a specialized subagent for the full 16-field frontmatter
- Create a custom Skill for the Skill frontmatter and progressive disclosure
- Permissions and Sandbox for
allowedToolswildcards