.claude/agents/*.md) define a role: tools, model, system prompt, skills. SendMessage each other while both are alive.planner.md, implementer.md) and a /task slash command I use instead — and how I run them automatically inside a GitHub Action for a client project.
A custom subagent in Claude Code is a Markdown file under .claude/agents/ that defines a role: which tools the agent can call, which model it runs on, its system prompt, and which skills it has access to. Main Claude can spawn it as a child task, hand it work, and read its final output back into the parent context.
Subagents are personas. Each invocation gets a fresh context, scoped by the role you defined. They don't share state with each other and they don't talk to each other.
This is the bit I got wrong for months.
I'd been treating "agent teams" and "custom subagents" as two ways to do the same thing. They aren't. They're orthogonal primitives.
A team uses subagents as the role each member plays. Subagents work fine without ever being in a team.
The decision rule that finally clicked for me: reach for a team only when agents need to converse while both are alive. If your workflow is sequential — agent A produces output, you (or main Claude) approve it, then agent B starts — you don't need a team. Main Claude is already the orchestrator. It can spawn one subagent, read the output, then spawn the next.
Whenever a task felt like it needed more than one agent, I'd send Claude something like this:
Create an agent team for the following task:
Before creating an agent team ask me questions if anything is unclear.
Spawn two teammates:
1. Planner (name: "planner")
- Model: Opus
- Mode: Default
- Role: Analyze the codebase and produce a detailed implementation plan with file-level changes. Flag ambiguities or risks. Output the plan as a structured message.
2. Implementer (name: "implementer")
- Model: Sonnet
- Mode: Default
- Role: Implement the approved plan step by step. After 2 failed fix attempts on the same issue, report the blocker to the lead.
Coordination:
- Create tasks with dependencies: implementer is blocked until planner's
plan is approved.
- The planner's plan requires approval from both you (the lead) and me
before the implementer starts.
Figma:
...
This worked. It also did three things I didn't actually need:
The role definitions weren't version-controlled. The skill list wasn't tied to the agent. The whole thing lived in my prompt history.
Same workflow, expressed as two .claude/agents/*.md files and a /task slash command that orchestrates them. The role definitions live in the repo, get version-controlled, and carry their tool and skill lists with them.
---
name: planner
description: "Analyzes the codebase and produces a detailed file-level implementation plan for a given task. Flags ambiguities and risks."
model: opus
color: pink
tools: Read, Glob, Grep, Bash, WebFetch, WebSearch, Skill, TaskCreate, TaskGet, mcp__figma__*
skills: flutter-apply-architecture-best-practices, flutter-build-responsive-layout, flutter-fix-layout-issues, flutter-implement-json-serialization, flutter-use-http-package, flutter-add-widget-test, flutter-accessibility-audit
---
You are the Planner. Your job is to produce a detailed, file-level implementation plan for given task — nothing more.
## What you do
1. **If the task contains Figma links, fetch the design first — before anything else.** Extract every relevant design detail: layout, spacing, colors, typography, component structure, text content (labels, button text, headings, body copy), icons, images, and interactive states. Do not draft the plan or list open questions until the design has been fully read — many "questions" answer themselves once you see the file.
2. Read the relevant existing code so the plan is grounded in the real codebase, not assumptions.
3. Produce a structured plan covering:
- **Goal**: one-paragraph restatement of the task.
- **Files to change**: every file you expect to touch, listed at the function/class/method level with the specific change and the reason.
- **Files to add**: new files with their purpose and approximate shape (key classes, public API).
- **Test plan**: which tests to add or update.
- **Risks & ambiguities**: anything that could go wrong.
- **Open questions for the lead**: things that must be resolved before the implementer starts.
4. Be honest about uncertainty. If you are unsure, list it as an ambiguity with options — do not guess.
## What you do NOT do
- Do not modify files. You have no Edit/Write tools by design.
- Do not implement the work. Your output is the plan only.
- Do not pad the plan with restatements of project conventions the lead already knows. Focus on what is specific to this task.
## Output format
Return one structured message in this shape:
## Goal
## Files to change
- `path/to/file.dart`
- `ClassName.methodName`: <what changes and why>
## Files to add
- `path/to/new_file.dart`: <purpose, key classes/functions>
## Test plan
- ...
## Risks & ambiguities
- ...
## Open questions for the lead
- ...
End your message with the literal line **`Plan ready for approval.`** so the lead knows to gate the implementer on it.
A few things worth calling out about this file:
Edit or Write tool.skills:. color: pink.
---
name: implementer
description: Implements a plan step by step.
model: sonnet
tools: Read, Write, Edit, Glob, Grep, Bash, WebFetch, WebSearch, Skill, TaskCreate, TaskGet, TaskUpdate, TaskList, mcp__figma__*
skills: flutter-apply-architecture-best-practices, flutter-build-responsive-layout, flutter-fix-layout-issues, flutter-implement-json-serialization, flutter-use-http-package, flutter-add-widget-test, flutter-accessibility-audit
---
Your key responsibility is to implement the given plan.
## Inputs you expect
- Implementation plan
- Any modifications the lead and user agreed on during plan approval
## What you do
Work through the plan step by step. Treat each "Files to change" / "Files to add" entry as a discrete unit of work.
## Blocker rule
If the same issue fails twice after you tried to fix it, **stop and report**. Send a single message to the lead with:
- What you were trying to do.
- The two attempts you made and why each failed.
- Your best hypothesis for the root cause.
- What you would try next, or what input you need from the lead.
Do not loop on a third attempt. The lead decides whether to redirect, re-plan, or escalate to the user.
## Reporting back
When the plan is fully implemented:
- Summarize what changed (files + one-line per change).
- List the verification checks you ran and their outcomes.
- Note anything you intentionally deferred and why.
Two details that matter here:
For interactive use, you could just run main Claude and ask it to use the planner subagent first, then the implementer. That works, but it's repetitive. So I wrapped the orchestration in a slash command:
---
description: Run a workflow with planner and implementer subagents for a task
argument-hint: [--auto] <task description>
---
Run the workflow described below — using the `planner` and `implementer` subagents — for the following task:
$ARGUMENTS
## Mode
- **Interactive (default)**: analyze code related to the task ask clarifying questions if anything is unclear, and require my approval of the plan before implementation.
- **Automated**: if the message above contains `--auto`, skip clarifying questions and skip my approval gate. Strip the `--auto` token from the task before passing it to the planner.
## Workflow
1. **Clarify** — interactive mode only. If the task is unambiguous, skip to step 2. Otherwise ask me clarifying questions before spawning anything.
2. **Plan** — spawn the `planner` subagent with the task. Wait for the plan.
3. **Approve**
- Interactive mode: present the plan to me. Both you and I must approve before implementation. If either of us has changes, send them back to the planner.
- Automated mode: review the plan yourself. If it has critical issues (architectural conflicts, missing prerequisites, contradictions with `CLAUDE.md`), send it back to the planner with feedback. Otherwise approve and proceed.
4. **Implement** — spawn the `implementer` subagent with the approved plan. The implementer is blocked until approval.
5. **Blockers** — if the implementer reports a blocker after 2 failed fix attempts on the same issue:
- Interactive mode: surface it to me with the implementer's hypothesis and options. Do not loop on a third attempt without my input.
- Automated mode: halt the workflow and report the blocker with full context. Do not retry.
Two modes:
--auto)
The --auto mode is what makes the command usable inside CI.
For Aparkado (the team behind LKW.APP), I run this as part of an end-to-end automation:
@automation-claude comment on a Linear issue labeled App + Automation. develop, commits a task.md containing the refined task, and opens a PR./task --auto against the contents of The whole point of this pipeline is that the expensive part — refining the task to a state Claude can implement well — happens before the agents run. The DoR check enforces it. By the time /task --auto fires, the input is good enough that no clarifying questions are needed.
If I'd built this same pipeline with agent teams, every PR would have been spawning a runtime communication group, paying the coordination tax, and re-defining the planner and implementer roles from scratch in every CI run. With custom subagents, the roles are committed to the repo and the pipeline is just claude --slash-command "/task --auto $TASK".
Are subagents and agent teams interchangeable?
No. Subagents define a role; teams define a runtime communication group. A team uses subagents as the role of each member, but subagents work without a team.
When should I actually use an agent team?
When you need agents to converse while both are alive — a debate, a back-and-forth code review, a long-running pair-programming session. If your workflow is sequential, main Claude is already the orchestrator and you don't need a team.
Why does the planner have no Edit or Write tools?
Role separation is enforced by the tool list, not just by the prompt. Removing those tools makes it physically impossible for the planner to start implementing the task.
Do subagents inherit the project's skills automatically?
No. You have to list each skill explicitly in the agent's skills: frontmatter. Built-in agents (Explorer, Plan, Verify) can't access skills at all — only custom subagents in .claude/agents/ can.
Can I run /task in CI without a human in the loop?
Yes — /task --auto skips the clarifying interview and the approval gate. Only do this when the input task is well-refined; otherwise the planner has nothing solid to ground its plan on. A well-defined Definition of Ready, enforced before the action runs, is what makes this safe.
This post focused on subagents. The same Anthropic Skills course also reshaped how I think about skill descriptions, the SKILL.md structure, the priority order between enterprise / personal / project / plugin skills, and when to reach for a hook or slash command instead of a skill. I'll write those up next.
If this kind of orchestration is something you're building into a client project and you want a second pair of eyes on it, get in touch — it's the work I do.