Agents, Subagents and the Claude Agent SDK
- Understand what subagents are and when spawning one makes sense vs. working in the main session
- Create a custom agent definition with specific tools and instructions
- Use the Claude Agent SDK to run Claude Code programmatically in CI/CD pipelines
What Are Agents?
An agent is simply a Claude instance with a specific purpose, a specific set of tools, and a specific scope. When a task is complex enough that different parts require different expertise — or can genuinely happen in parallel — Claude Code can spawn subagents to handle each part simultaneously.
Think of it as delegation. Just as you might ask a junior developer to investigate while you plan, a security engineer to review while you test, and a technical writer to document while you deploy — Claude Code can assign work to specialised instances that run in parallel and report back.
The result is faster, more thorough work than any single agent could produce alone.
Built-in Agent Types
Claude Code ships with four built-in agent types:
| Agent | What it does | Typical use |
|---|---|---|
Explore |
Fast read-only search across the codebase. Cannot write files or run commands — only reads. Returns quickly with findings. | "Find all usages of this function", "Where is X defined?", "Which files import Y?" |
Plan |
Designs an implementation approach. Reads files extensively, asks clarifying questions, returns a step-by-step plan. Does not write code. | Before implementing a complex feature or a risky refactor |
code-reviewer |
Reviews code for correctness, security vulnerabilities, test coverage gaps, and style consistency. Returns a structured report. | After implementing a feature, before merging a PR |
general-purpose |
Full-capability agent with all tools available. Used for open-ended research, multi-step tasks, and anything the other agents do not fit. | Complex research tasks, tasks that span exploration and implementation |
A Real Parallel Agent Workflow
Here is how a refactoring task looks when you use multiple agents:
Main task: "Refactor the user authentication system to use JWT instead of sessions"
Immediately, spawn three agents in parallel:
→ Explore agent: "Find every file that imports or uses the session module"
[reads 40 files in 15 seconds, returns a complete list]
→ Plan agent: "Design the JWT migration: what changes, in what order, with what risks"
[reads auth module, reads callers, designs the migration plan]
→ code-reviewer: "Review src/auth.ts for security issues before we start changing it"
[identifies existing vulnerabilities to fix during the migration]
[All three complete in parallel — total time: about 30 seconds]
Main session: reads all three results, has complete picture before writing a line of code
→ Implements the migration based on the plan
→ Runs the tests
→ Spawns code-reviewer again on the new code
→ Ships clean
Without subagents, the same work would be sequential: explore → plan → review → implement. With subagents, the first three happen simultaneously. The result is faster, and the review before implementation often prevents mistakes that would be expensive to fix afterward.
Creating Custom Agents
Custom agents live in .claude/agents/ in your project directory. Each agent is a directory with an agent.md file that defines its purpose and constraints.
Example: a database query expert
Create .claude/agents/db-analyst/agent.md:
---
name: db-analyst
description: Analyses database queries for performance issues and proposes optimisations
tools: Read, Bash
---
You are a database performance expert. When given a query or a function that makes database calls:
1. Read the relevant code to understand the full query
2. Run EXPLAIN ANALYZE on any PostgreSQL queries (use: psql $DATABASE_URL -c "EXPLAIN ANALYZE ...")
3. Identify N+1 query patterns, missing indexes, and full table scans
4. Propose specific optimisations with expected performance impact
5. Show the optimised query alongside the original for comparison
Provide concrete numbers where possible. Do not optimise prematurely — only report genuine performance problems.
Delegate to it with: @db-analyst review the getRecentOrders() function for performance issues
Example: a security reviewer
Create .claude/agents/security-reviewer/agent.md:
---
name: security-reviewer
description: Reviews code for security vulnerabilities with severity ratings
tools: Read, Glob, Grep
---
You are a security expert specialising in web application security. Review the provided code for:
1. SQL injection — user input passed directly to queries without parameterisation
2. XSS — unsanitised user input rendered to HTML
3. Authentication bypass — ways to access protected resources without valid credentials
4. Insecure direct object references — accessing resources by guessable IDs without authorisation checks
5. Hardcoded credentials — API keys, passwords, tokens in source code
6. Unsafe deserialisation — parsing untrusted data without validation
7. Missing input validation — accepting any value where only specific values are valid
Report each finding with:
- Severity: Critical / High / Medium / Low
- File and line number
- Description of the vulnerability
- Specific code change to fix it
Delegate with: @security-reviewer review the payment API endpoint in src/routes/payments.ts
When to Spawn Subagents
Not every task benefits from subagents. Here is a clear decision framework:
- Spawn an agent when: the sub-task is truly independent (does not need main conversation context), requires specialised expertise, or can genuinely run in parallel with other work.
- Do not spawn an agent when: the task is simple, needs the full context of your current conversation, or spawning would add complexity without adding speed or quality.
The Explore agent is the most commonly useful. Any time you find yourself typing "search for all files that..." — that is an Explore agent job. It is faster and more thorough than doing it in the main session.
The Claude Agent SDK
The Agent SDK (available in Python and TypeScript) lets you run Claude Code programmatically — not interactively. Instead of you sitting at a terminal guiding Claude, your code directs it. This opens up an entirely different class of use cases.
When to use the SDK instead of the CLI
| Scenario | Use |
|---|---|
| Interactive development — you are at the keyboard | CLI |
| CI/CD pipeline — runs automatically on push | SDK |
| Scheduled job — runs at 2am without anyone present | SDK |
| Hosted API — your users trigger Claude tasks | SDK |
| Multi-step automation — many tasks chained together | SDK |
Python SDK: basic usage
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def fix_failing_tests(test_file: str):
"""Automatically fix a failing test file"""
async for message in query(
prompt=f"""
The test file {test_file} has failing tests.
1. Read the test file and the source file it tests
2. Run the tests to see the current failures: npm test -- {test_file}
3. Fix the implementation (not the tests) to make all tests pass
4. Run the tests again to confirm they pass
""",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Edit", "Bash"],
permission_mode="acceptEdits"
),
):
if hasattr(message, "result"):
print(message.result)
asyncio.run(fix_failing_tests("tests/api/users.test.ts"))
TypeScript SDK: CI/CD integration
import { query } from "@anthropic-ai/claude-agent-sdk";
async function reviewPRDiff(diffContent: string): Promise<string> {
const results: string[] = [];
for await (const message of query({
prompt: `Review this pull request diff for security issues, bugs, and code quality:
${diffContent}
Provide:
1. A PASS / NEEDS WORK / FAIL verdict
2. Any critical issues (must fix before merge)
3. Any suggestions (nice to have)`,
options: {
allowedTools: ["Read"],
permissionMode: "default"
}
})) {
if ("result" in message) {
results.push(message.result as string);
}
}
return results.join("
");
}
// Called from your CI pipeline
const review = await reviewPRDiff(process.env.PR_DIFF ?? "");
console.log(review);
Scheduled Agents with /schedule
Claude Code's /schedule command lets you create agents that run on a cron schedule in Anthropic's cloud — no local machine required, no process to keep running.
Example: a nightly dependency check
claude
> /schedule
You are then walked through creating a scheduled routine. A good starting routine:
- Task: "Check for outdated dependencies in package.json. If any have high-severity vulnerabilities according to npm audit, create a GitHub issue summarising the findings."
- Schedule: Daily at 9am MDT (converted to UTC for the cron)
- Model: claude-sonnet-4-6
- Tools needed: Bash (for npm commands), GitHub MCP server
The scheduled agent runs in a fresh cloud environment, clones your repo, runs the check, and creates the GitHub issue if needed — all without any action from you. View and manage your scheduled routines at claude.ai/code/routines.
Agent Security
Subagents inherit the permission configuration of their parent session. If your main session has Bash(rm -rf *) in the deny list, subagents cannot run that command either. The settings.json and deny rules you configured apply to the entire session, including all subagents it spawns.
For the SDK, explicitly set allowed_tools to the minimum set required for the task. Do not pass all tools to every SDK query — use the least privilege principle:
# Code review agent — only needs to read, not write
options=ClaudeAgentOptions(
allowed_tools=["Read", "Glob", "Grep"],
permission_mode="default"
)
# Bug fix agent — needs to read and edit
options=ClaudeAgentOptions(
allowed_tools=["Read", "Edit", "Bash"],
permission_mode="acceptEdits"
) - Subagents are isolated Claude instances — spawn them for parallel work, specialised expertise, or independent sub-tasks
- Built-in types: Explore (fast read-only search), Plan (architecture design), code-reviewer (quality and security), general-purpose
- Custom agents live in .claude/agents/ — define their tools and expertise in agent.md
- The Agent SDK (Python + TypeScript) enables CI/CD integration, scheduled jobs, and hosted applications
- Use /schedule to create cloud-hosted agents that run on a cron without keeping your local machine running