How to Create Agents and Subagents in Claude Code

#claudecode #ai #tutorial #blog #blogpost #development #agents #automation #sdk

How to Create Agents and Subagents in Claude Code — A Technical Tutorial

Claude Code is not a single assistant — it is an orchestrator that can spawn specialised agents, delegate tasks in parallel, and coordinate multi-agent workflows. Understanding how agents work is the difference between using Claude Code as a chatbot and using it as an engineering team.

This tutorial covers three levels of agent architecture: subagents within Claude Code, agent teams for parallel work, and the Claude Agent SDK for building custom agents programmatically.


What Are Agents and Subagents?

Claude Code itself is an agent. It operates in an agentic loop: gather context → take action → verify results → repeat. You stay in control and can interrupt at any point.

Subagents are specialised assistants that Claude spawns to handle specific tasks. Each runs in its own isolated context window — completely separate from your main session. They do their work, summarise the results, and return them to the main conversation.

Why does this matter? Because context windows have limits. If you ask Claude to search 50 files, read 20 web pages, and analyse the results — all that content floods your main context, pushing out earlier conversation. Subagents absorb that load. They do the heavy lifting in their own space and return only the summary.

Agent teams take this further — multiple Claude instances working in parallel, communicating with each other, and coordinating through a shared task list.


Level 1 — Subagents in Claude Code

Built-In Subagent Types

Claude Code has several built-in subagent types, each with different tool access:

Subagent Type Tools Available Best For
general-purpose All tools (Read, Write, Edit, Bash, Glob, Grep, WebSearch, WebFetch, Agent) Complex multi-step tasks that need full access
Explore Read-only (Read, Glob, Grep, WebSearch, WebFetch) Research, codebase exploration, investigation — no file modifications
Plan Read-only (Read, Glob, Grep, WebSearch, WebFetch) Architecture planning, implementation strategy — read and think, don’t write

How Claude Spawns Subagents

When you ask Claude to do something, it decides whether to handle it directly or delegate to a subagent. The decision is based on:

  • Task complexity — multi-step research benefits from a subagent
  • Context cost — tasks that generate lots of output (search results, file contents) are better in a subagent
  • Specialisation — some tasks match a specific subagent type

You can also explicitly request a subagent:

Use an Explore agent to research how FHIR Subscriptions work 
across different server implementations.

Claude spawns an Explore subagent with read-only tools. The subagent searches, reads documentation, analyses code — all in its own context. When done, it returns a concise summary to your main session.

Launching Multiple Subagents in Parallel

The real power of subagents is parallelism. You can ask Claude to launch multiple agents simultaneously:

I need to understand three things in parallel:
1. How does our authentication middleware work?
2. What FHIR resources are we currently using?
3. What are the latest Hasura features for healthcare?

Research all three simultaneously.

Claude launches three subagents — one for each question — all running at the same time. Each returns its findings independently. This is dramatically faster than sequential research.

Foreground vs Background Agents

Foreground (default) — Claude waits for the agent to finish before continuing. Use this when you need the results before proceeding:

Research how to implement FHIR Subscriptions, then use those 
findings to implement it in our codebase.

Background — Claude continues working while the agent runs. Use this when you have genuinely independent work:

In the background, research the latest NICE guidelines on 
antenatal care. Meanwhile, I want to work on the appointment 
booking API.

Agent Isolation with Worktrees

For tasks that modify files, agents can run in isolated git worktrees — a temporary copy of the repository:

In an isolated worktree, refactor the patient search module 
to use Elasticsearch instead of PostgreSQL full-text search.

The agent works on its own branch without affecting your current work. If the changes are good, they can be merged. If not, the worktree is discarded.


Level 2 — Agent Teams (Parallel Collaboration)

Agent teams are multiple Claude Code instances working together. One acts as the team lead coordinating work, while teammates work independently and communicate directly.

Enabling Agent Teams

Add to your settings:

{
  "env": {
    "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
  }
}

Creating a Team

Create an agent team to review PR #142:

- Teammate 1: Security reviewer — check for auth issues, 
  injection vulnerabilities, data exposure
- Teammate 2: Performance reviewer — check for N 1 queries, 
  memory leaks, algorithmic efficiency  
- Teammate 3: Test reviewer — validate test coverage, 
  check edge cases, verify integration tests

Have them review independently, then discuss their findings 
and agree on a final assessment.

Claude creates the team with:

  • A team lead that coordinates and synthesises
  • Three teammates that each get their own context window
  • A shared task list for coordination
  • Direct messaging between teammates for discussion

How Teams Communicate

Teams use a mailbox system:

  • Teammates can send messages directly to each other
  • The team lead can broadcast to all teammates
  • Each teammate maintains its own conversation context
  • Findings are synthesised by the team lead

Display Modes

In-process — all teammates share your terminal output (default).

tmux split-panes — each teammate gets its own pane, and you can watch them work in parallel:

{
  "teammateMode": "tmux"
}

Real Example: Competing Hypothesis Investigation

Users report the app crashes after one message. Create a team 
of 5 investigators, each testing a different hypothesis:

1. WebSocket connection drops after first message
2. Message queue overflow causes crash
3. Database connection pool exhaustion
4. Memory leak triggered after ~1MB allocation
5. Deadlock in message processing pipeline

Each teammate should:
- Test their hypothesis with evidence from the codebase
- Try to disprove the other hypotheses
- Present their findings with file paths and line numbers

The theory that survives scrutiny is likely the root cause.

This pattern — parallel investigation with adversarial testing — is extraordinarily effective for debugging.


Level 3 — Claude Agent SDK (Programmatic Agents)

The Claude Agent SDK lets you build agents in Python or TypeScript that run in cloud containers, persist across sessions, and orchestrate multi-agent workflows.

This is the level you use when building agent-powered features into your own applications.

Core Concepts

Concept Description
Agent A configured Claude instance with a system prompt, model, tools, and skills
Environment A Docker container with pre-installed packages
Session A running conversation between a user and an agent
Thread A sub-conversation within a session (for multi-agent)
Event A message, tool call, or status change in the session stream

Example 1: Simple Agent (Python)

from anthropic import Anthropic

client = Anthropic(api_key="your-api-key")

# 1. Create an agent
agent = client.beta.agents.create(
    name="EHR Code Reviewer",
    model="claude-opus-4-6",
    system="""You are a healthcare software code reviewer.
    Focus on:
    - FHIR resource compliance
    - Clinical data safety
    - HIPAA/GDPR data handling
    - SQL injection and input validation
    Rate issues as Critical, High, Medium, or Low.""",
    tools=[
        {"type": "agent_toolset_20260401"}
    ]
)

# 2. Create an environment with dependencies
environment = client.beta.environments.create(
    docker_image="python:3.11",
    setup_commands=[
        "pip install fhir.resources requests"
    ]
)

# 3. Start a session
session = client.beta.sessions.create(
    agent=agent.id,
    environment_id=environment.id
)

# 4. Send a task
client.beta.sessions.events.send(
    session.id,
    events=[{
        "type": "user.message",
        "content": [{
            "type": "text",
            "text": "Review the FHIR Patient resource "
                   "implementation for compliance issues."
        }]
    }]
)

# 5. Stream the response
with client.beta.sessions.stream(session.id) as stream:
    for event in stream:
        if event.type == "agent.message":
            for block in event.content:
                if block.type == "text":
                    print(block.text)

Example 2: Simple Agent (TypeScript)

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

// 1. Create an agent
const agent = await client.beta.agents.create({
  name: "FHIR Validator",
  model: "claude-opus-4-6",
  system: `You validate FHIR resources against the R5 specification.
    Check for: missing required fields, invalid value sets,
    broken references, and non-compliant extensions.`,
  tools: [{ type: "agent_toolset_20260401" }],
});

// 2. Create an environment
const environment = await client.beta.environments.create({
  dockerImage: "node:20",
  setupCommands: ["npm install @types/fhir"],
});

// 3. Start a session
const session = await client.beta.sessions.create({
  agent: agent.id,
  environment_id: environment.id,
});

// 4. Send a task
await client.beta.sessions.events.send(session.id, {
  events: [
    {
      type: "user.message",
      content: [
        {
          type: "text",
          text: "Validate all FHIR resources in the /src/fhir/ directory",
        },
      ],
    },
  ],
});

// 5. Stream the response
for await (const event of client.beta.sessions.stream(session.id)) {
  if (event.type === "agent.message") {
    for (const block of event.content) {
      if (block.type === "text") {
        process.stdout.write(block.text);
      }
    }
  }
}

Example 3: Multi-Agent Orchestration

This is where it gets powerful. One coordinator agent delegates work to specialist agents, each running in their own thread:

from anthropic import Anthropic

client = Anthropic()

# Create specialist agents
security_agent = client.beta.agents.create(
    name="Security Auditor",
    model="claude-opus-4-6",
    system="""You are a security auditor. Review code for:
    - OWASP Top 10 vulnerabilities
    - Authentication and authorisation flaws
    - Cryptographic misuse
    - Data exposure risks
    Rate each finding: Critical / High / Medium / Low""",
    tools=[{"type": "agent_toolset_20260401"}]
)

test_agent = client.beta.agents.create(
    name="Test Engineer",
    model="claude-opus-4-6",
    system="""You are a test engineer. Your job:
    - Write comprehensive unit tests
    - Cover edge cases and error paths
    - Ensure integration tests exist for API endpoints
    - Verify test coverage meets 80% threshold""",
    tools=[{"type": "agent_toolset_20260401"}]
)

docs_agent = client.beta.agents.create(
    name="Documentation Writer",
    model="claude-opus-4-6",
    system="""You write technical documentation. Generate:
    - API endpoint documentation (OpenAPI format)
    - Code comments for complex functions
    - README updates for new features
    - Architecture decision records""",
    tools=[{"type": "agent_toolset_20260401"}]
)

# Create the coordinator that calls the specialists
coordinator = client.beta.agents.create(
    name="Engineering Lead",
    model="claude-opus-4-6",
    system="""You are an engineering lead. When given a task:
    1. Break it into subtasks
    2. Delegate security review to the Security Auditor
    3. Delegate testing to the Test Engineer
    4. Delegate documentation to the Documentation Writer
    5. Synthesise all findings into a final report""",
    tools=[{"type": "agent_toolset_20260401"}],
    callable_agents=[
        {
            "type": "agent",
            "id": security_agent.id,
            "version": security_agent.version
        },
        {
            "type": "agent",
            "id": test_agent.id,
            "version": test_agent.version
        },
        {
            "type": "agent",
            "id": docs_agent.id,
            "version": docs_agent.version
        },
    ]
)

# Create environment
env = client.beta.environments.create(
    docker_image="node:20",
    setup_commands=["npm install typescript @types/node"]
)

# Start session with the coordinator
session = client.beta.sessions.create(
    agent=coordinator.id,
    environment_id=env.id
)

# Send the task — the coordinator delegates automatically
client.beta.sessions.events.send(
    session.id,
    events=[{
        "type": "user.message",
        "content": [{
            "type": "text",
            "text": """Review the patient API module:
            - Security audit all endpoints
            - Write missing tests
            - Update API documentation
            
            Coordinate all three specialists and give me 
            a consolidated report."""
        }]
    }]
)

# Stream the coordinator's orchestration
with client.beta.sessions.stream(session.id) as stream:
    for event in stream:
        if event.type == "agent.message":
            for block in event.content:
                if block.type == "text":
                    print(block.text)

The coordinator automatically:

  1. Creates a thread for each specialist
  2. Sends them their specific tasks
  3. Waits for results
  4. Synthesises findings into a single report

Each specialist works in isolation with its own context window, tools, and conversation history.

Monitoring Multi-Agent Sessions

# List all threads in a session
for thread in client.beta.sessions.threads.list(session.id):
    print(f"[{thread.agent_name}] Status: {thread.status}")

# Stream a specific thread's work
with client.beta.sessions.threads.stream(
    thread.id, session_id=session.id
) as stream:
    for event in stream:
        if event.type == "agent.message":
            print(f"[{thread.agent_name}] {event.content}")

# Get thread event history
for event in client.beta.sessions.threads.events.list(
    thread.id, session_id=session.id
):
    print(f"[{event.type}] {event.processed_at}")

# Check session status (idle, running, terminated)
status = client.beta.sessions.retrieve(session.id)
print(f"Session status: {status.status}")

Creating Custom Agent Types in Claude Code

Beyond using the built-in types, you can define custom agent types that Claude Code recognises and spawns automatically.

Custom Agent via Skill (Simplest Approach)

Create a skill with context: fork to run as a subagent:

mkdir -p ~/.claude/skills/fhir-validator

Create ~/.claude/skills/fhir-validator/SKILL.md:

---
name: fhir-validator
description: Validate FHIR resources for R5 compliance. Use when 
  checking healthcare data models, API responses, or database 
  schemas against the FHIR specification.
argument-hint: [file-or-directory]
context: fork
agent: Explore
allowed-tools: Read Glob Grep WebFetch
effort: high
---

# FHIR Resource Validator

Validate the FHIR resources in $ARGUMENTS against the R5 spec.

## Validation checks

1. **Required fields** — Are all mandatory elements present?
2. **Cardinality** — Do arrays respect min/max constraints?
3. **Value sets** — Are coded values from the correct value set?
4. **References** — Do resource references point to valid types?
5. **Extensions** — Are custom extensions properly namespaced?
6. **Data types** — Are dates ISO 8601? Are identifiers structured?

## For each issue found, report:

- **Resource**: Which FHIR resource type
- **Field**: JSON path to the problem
- **Severity**: Error / Warning / Info
- **Rule**: Which FHIR rule is violated
- **Fix**: Specific correction needed

## Summary

End with a compliance score: X/Y checks passed.
List the top 3 most critical fixes.

Usage:

/fhir-validator src/fhir/resources/

Claude spawns an Explore subagent with read-only access, runs the validation in an isolated context, and returns the results to your main session.

Custom Agent via AGENT.md (Advanced)

For full control, create an agent definition:

mkdir -p .claude/agents/security-auditor

Create .claude/agents/security-auditor/AGENT.md:

---
name: security-auditor
description: Security code review specialist for healthcare applications
model: claude-opus-4-6
tools: Read Grep WebSearch
system: |
  You are a security auditor specialising in healthcare applications.
  
  When reviewing code:
  1. Identify OWASP Top 10 vulnerabilities
  2. Check authentication and authorisation patterns
  3. Look for PHI/PII exposure risks
  4. Verify input validation on all endpoints
  5. Check for SQL injection, XSS, and CSRF
  6. Review cryptographic implementations
  
  Rate every finding:
  - CRITICAL: Exploitable now, patient data at risk
  - HIGH: Exploitable with effort, significant impact
  - MEDIUM: Potential risk, needs remediation
  - LOW: Best practice improvement
  
  Always include file paths, line numbers, and specific fix recommendations.
---

How Agents, Subagents, and Skills Work Together

Component What It Is When To Use
Skills Prompt templates (SKILL.md) Teaching Claude HOW to do something
Subagents Isolated Claude instances spawned within a session Delegating work that would overflow your context
Agent Teams Multiple Claude instances working in parallel Parallel investigation, adversarial review, research
SDK Agents Programmatic agents running in cloud containers Building agent features into your own applications

They compose naturally:

  • A skill can specify context: fork to run as a subagent
  • A subagent can use skills loaded in its context
  • An SDK agent can have skills pre-loaded and call other agents
  • An agent team member can invoke skills during its work

Practical Patterns for Healthcare

Pattern 1: Parallel Research

Research these three topics simultaneously using separate agents:

1. Latest NICE guidelines on gestational diabetes management
2. FHIR R5 changes to the MedicationRequest resource
3. How Medplum implements clinical decision support

Return findings in a comparison table.

Pattern 2: Code Review Pipeline

Create a team to review the maternity module:

- Agent 1: Review clinical safety — are there edge cases that 
  could produce incorrect gestational age calculations?
- Agent 2: Review data integrity — are FHIR resources correctly 
  structured with all required fields?
- Agent 3: Review performance — will the appointment query scale 
  to 3,000 active pregnancies?

Each reviewer should challenge the others' findings.

Pattern 3: Document Generation (SDK)

# Agent with document creation skills
agent = client.beta.agents.create(
    name="Clinical Report Generator",
    model="claude-opus-4-6",
    system="Generate clinical audit reports from data.",
    tools=[{"type": "agent_toolset_20260401"}],
    skills=[
        {"type": "anthropic", "skill_id": "xlsx"},
        {"type": "anthropic", "skill_id": "docx"},
        {"type": "anthropic", "skill_id": "pptx"},
    ]
)

This agent can generate Excel spreadsheets with audit data, Word documents with clinical reports, and PowerPoint presentations for governance meetings — all programmatically.

Pattern 4: Long-Running Background Analysis

# Start analysis that runs for minutes/hours
session = client.beta.sessions.create(
    agent=analysis_agent.id,
    environment_id=env.id
)

client.beta.sessions.events.send(
    session.id,
    events=[{
        "type": "user.message",
        "content": [{
            "type": "text",
            "text": "Analyse 12 months of appointment data. "
                   "Identify patterns in DNA rates, peak booking "
                   "times, and seasonal variation. Generate a "
                   "report with visualisations."
        }]
    }]
)

# Check back later
status = client.beta.sessions.retrieve(session.id)
if status.status == "idle":
    print("Analysis complete — retrieving results")

Best Practices

1. Write Clear Agent Descriptions

The description determines when Claude spawns the agent. Be specific:

# Good — specific triggers
description: Security auditor for healthcare code. Use when reviewing 
  authentication, authorisation, data validation, PHI exposure, 
  or HIPAA compliance in healthcare applications.

# Bad — too vague
description: Reviews code

2. Choose the Right Level

Situation Use
Quick file search or web lookup Subagent (Explore)
Multi-file investigation Subagent (general-purpose)
Multiple independent questions Parallel subagents
Adversarial review or debate Agent team
Long-running analysis SDK managed agent
Building agent features into your app SDK

3. Keep Subagent Prompts Specific

Don’t dump your entire problem on a subagent. Give it one clear task:

# Good — focused task
Use an Explore agent to find all files that import the 
PatientResource class and list how each one uses it.

# Bad — too broad
Use an agent to understand the codebase.

4. Use Isolation for Safety

  • Explore agents for read-only investigation (can’t break anything)
  • Worktrees for experimental changes (isolated branch)
  • disable-model-invocation: true for dangerous skills (deploy, delete)

5. Compose Agents with Skills

Give agents domain knowledge through skills:

# The skill provides the expertise
---
name: fhir-guide
description: FHIR R5 specification reference
user-invocable: false  # Only agents use this
---

FHIR R5 key resources: Patient, Encounter, Observation...
# The agent uses the expertise
---
name: fhir-reviewer
description: Review FHIR implementations
context: fork
agent: Explore
---

Using your FHIR knowledge, review $ARGUMENTS for compliance.

Summary

Level What Where Best For
Subagents Spawned within Claude Code Your terminal Task delegation, context management
Agent Teams Parallel Claude instances Your terminal (split panes) Investigation, review, research
SDK Agents Programmatic cloud agents Your application Building AI features, long-running tasks
Multi-Agent SDK Coordinator specialists Your application Complex workflows, orchestration

Start with subagents. They are free, require no setup, and solve the most common problem: keeping your context clean while delegating research. Move to agent teams when you need parallel investigation. Move to the SDK when you are building agent-powered features into your own products.

The future of software development is not one AI assistant. It is a team of specialised agents, each with the right tools and the right constraints, coordinated by an intelligent lead. Claude Code gives you that team today.


  • How to Create Skills in Claude Code
  • Claude Code AI Resources for EHR Development
  • Blog Post Index
  • 16 Core Components of Modern Apps
  • How to Automate Your Life
  • Workflow Automation Platforms
  • 27 Healthcare App Ideas
  • Build VS Buy

References

[1] Anthropic. (2026). ‘Claude Code Documentation — Agents and Subagents’. Anthropic Docs. Available at: https://docs.anthropic.com/en/docs/claude-code (Accessed: 23 April 2026).

[2] Anthropic. (2026). ‘Claude Agent SDK — Python and TypeScript’. Anthropic Docs. Available at: https://docs.anthropic.com/en/docs/agents/agent-sdk (Accessed: 23 April 2026).

[3] Anthropic. (2026). ‘Multi-Agent Sessions — Orchestrating Specialist Agents’. Anthropic Docs. Available at: https://docs.anthropic.com/en/docs/agents/multi-agent (Accessed: 23 April 2026).

[4] Anthropic. (2026). ‘Claude Code Agent Teams’. Anthropic Docs. Available at: https://docs.anthropic.com/en/docs/claude-code/agent-teams (Accessed: 23 April 2026).

[5] Anthropic. (2026). ‘Claude Code Skills Documentation’. Anthropic Docs. Available at: https://docs.anthropic.com/en/docs/claude-code/skills (Accessed: 23 April 2026).

Leave a comment