
Keywords: Claude Code built-in agent types, subagents, codebase investigation, implementation planning
Table of Contents
- The Problem: Choosing the Right Tool for the Job
- What Are Built-in Agent Types?
- The Explore Agent: Fast Codebase Investigation
- What It Does
- When to Use It
- Example: Investigating a Mystery Function
- Why It's Fast
- Real-World Scenario: Security Audit
- Hidden Layer: Understanding Grep Patterns
- Edge Case: Large Binary or Generated Files
- The Plan Agent: Architecture and Strategy
- What It Does
- When to Use It
- Example: Planning a Database Migration
- Why This Matters
- Hidden Layer: Research-Driven Planning
- Real-World Scenario: Feature Implementation Strategy
- The General-Purpose Agent: Full Power
- What It Does
- When to Use It
- Example: Complete Feature Implementation
- Why This Matters
- Hidden Layer: Why Not Start with General-Purpose?
- Comparing the Three Types
- Tool Access Breakdown
- Explore Agent Tool Details
- Plan Agent Additional Tool
- General-Purpose Agent Full Toolkit
- Practical Patterns: Using Agent Types Together
- Pattern 1: Understand → Plan → Build (The Standard Flow)
- Pattern 2: Fast Issue Resolution
- Pattern 3: Security Audit
- Avoiding Common Pitfalls
- Pitfall 1: Using General-Purpose When Explore Would Suffice
- Pitfall 2: Skipping the Plan Phase
- Pitfall 3: Using Explore for Tasks Requiring Changes
- Pitfall 4: Expecting Plan Agent to Write Production Code
- Default Capabilities and Customization
- When to Create Custom Agents
- Real Examples from Production
- Example 1: Onboarding New Developers
- Example 2: Dependency Upgrade Strategy
- Example 3: Code Debt Cleanup
- Best Practices
- Comparing Built-in vs Custom Agents
- The Economics of Agent Type Selection
- Time Investment Analysis
- Risk Mitigation Through Progressive Capability
- Resource Optimization
- Advanced Patterns and Sophisticated Workflows
- The Parallel Investigation Pattern
- The Validation Loop Pattern
- The Continuous Monitoring Pattern
- Conclusion
The Problem: Choosing the Right Tool for the Job
You're working in a massive codebase. Maybe it's legacy code with thousands of files, or a modern monorepo where you're not familiar with every module. You need to understand how something works, plan a major refactor, or implement a feature across multiple files. Manually searching and reading code gets old fast.
Or worse: you spin up an agent to help, and it has full access to everything—write permissions, network access, the works. For a read-only investigation, that's overkill and potentially risky. You want something faster, more focused, and safer for the task at hand.
This is where Claude Code's built-in agent types come in. We have three flavors, each optimized for different scenarios. Understanding when to deploy each one is the key to faster, smarter codebase work.
What Are Built-in Agent Types?
Before we dive into the three types, let's get clear on terminology. In Claude Code, a subagent is a specialized AI instance spawned to handle a specific task. You invoke subagents via the Agent tool with a subagent_type parameter.
We ship with three built-in types—Explore, Plan, and General-Purpose—each with a specific permission model and tool access. Think of them as progressively more capable:
- Explore Agent: Read-only, lightning-fast, minimal tool access
- Plan Agent: Read + research, no write access
- General-Purpose Agent: Full capabilities, all tools available
They're designed around the principle of least privilege. You give each agent only the tools it actually needs. This keeps execution fast, surfaces relevant information quickly, and reduces the blast radius if something goes wrong.
The Explore Agent: Fast Codebase Investigation
What It Does
The Explore agent is your codebase detective. It's optimized for one job: rapidly scanning, searching, and understanding code structure without making any changes.
Here's what it can access:
| Tool | Available | Why |
|---|---|---|
| Glob | ✅ Yes | Fast file pattern matching |
| Grep | ✅ Yes | Content search across files |
| Read | ✅ Yes | Read file contents |
| Edit | ❌ No | Never writes files |
| Write | ❌ No | Never creates files |
| Bash | Limited | No destructive commands |
| WebSearch | ❌ No | No external research |
When to Use It
Use Explore when:
- You're investigating unfamiliar code and need to understand the architecture
- You're tracking down a bug and need to follow the call chain across files
- You need a security audit or compliance check (read-only ensures no tampering)
- You're planning a refactor and need to know what depends on what
- You have time constraints and need answers fast (Explore agents run quickly)
- You want minimal risk for automated tasks
- You need reproducible results: Since Explore can't write, every run is idempotent
Example: Investigating a Mystery Function
Let's say you've inherited a codebase and you see a function called processPayload() being called in your error logs. You want to know:
- Where is it defined?
- What does it do?
- What calls it?
- Does it have any tests?
- What are the performance characteristics?
Here's how you'd use an Explore agent:
# Pseudo-code showing the concept
# In Claude Code, you'd invoke this via the Agent tool:
Agent.spawn({
subagent_type: "explore",
task: "Find the processPayload() function. Tell me:
1. Where is it defined (file + line)?
2. What does it do (show me the code)?
3. What functions call it?
4. Are there any tests for it?
5. What's the call chain from entry point to this function?
6. Does it use any external services or APIs?"
})The Explore agent would:
- Use Glob to scan for
.jsfiles:**/*.js - Use Grep to search for
processPayload:grep -n "function processPayload" - Use Grep again to find all callers:
grep -n "processPayload(" - Use Read to examine the actual code in those locations
- Look for
*.test.jsor*.spec.jsfiles using Glob - Trace backwards through imports to understand dependencies
- Report findings with file paths, line numbers, and full context
Expected output:
Found processPayload in: src/payment/engine.js (line 247)
Definition:
function processPayload(data, options = {}) {
const validated = validatePaymentData(data);
return applyBusinessRules(validated, options);
}
Called from:
- src/api/routes/charge.js (line 89)
- src/api/routes/refund.js (line 156)
- src/workers/async-processor.js (line 412)
Tests found:
- tests/payment/engine.test.js (18 test cases)
- Tests cover: valid input, invalid data, edge cases
Dependencies:
- validatePaymentData (src/payment/validation.js)
- applyBusinessRules (src/payment/rules.js)
Call chain from entry point:
POST /api/charge → chargeHandler() → queuePayment() → processPayload()
Performance note: Synchronous function, ~50ms per call based on logs
Why It's Fast
The Explore agent is quick because:
- No write locks: Doesn't need to acquire file system locks before operating
- Minimal tool overhead: Only uses Glob, Grep, Read—lightweight operations
- Focused execution: No time spent on environment setup, package management, or compilation
- Parallelizable: Multiple Explore agents can search simultaneously without conflicts
- No side effects: Doesn't trigger builds, watchers, or deployment pipelines
- Early termination: Can return partial results as soon as patterns emerge
In practice, an Explore agent can scan a 50k-file codebase and answer structural questions in seconds. Try doing that with a general-purpose agent! The overhead of full capabilities makes it much slower.
Real-World Scenario: Security Audit
Imagine you need to audit where user input is processed in your system. Here's what an Explore agent could do:
Task: "Audit all places where user input enters our system.
Find all functions with names containing 'parse', 'input', or 'deserialize'.
For each one found, show me the file, line number, and the function signature.
Then tell me: which of these write to a database?
Which ones make HTTP calls?
Which ones write to disk?
Are there any that don't validate input?"The agent would:
- Grep for
function.*parse|function.*input|function.*deserialize - Compile the list of file paths and line numbers
- Read each file to show function signatures and understand what each does
- Grep each file for database operations (
db.insert,db.update, etc.) - Grep for HTTP calls (
fetch,axios,http.request) - Grep for file operations (
fs.write,fs.writeFile) - Create a detailed report with risk levels and recommendations
Why this matters: You get a fast, reproducible audit with zero risk of accidental code changes. You can run this weekly, diff the results, and catch new input handlers automatically.
Hidden Layer: Understanding Grep Patterns
Most developers use grep for simple searches, but Explore agents use sophisticated regex patterns. For example:
# Find all error handlers
grep -r "catch\s*\(" --include="*.js"
# Find all configuration reads
grep -r "(process\.env|require.*config)" --include="*.js"
# Find all database query patterns
grep -r "(query|execute|insert|update|delete)\s*\(" --include="*.js"
# Find potentially unsafe data handling
grep -r "(eval|Function\(|innerHTML|dangerouslySetInnerHTML)" --include="*.js"The Explore agent knows to construct patterns that catch variations—optional whitespace, different naming conventions, nested calls. This is why it finds things you might miss manually.
Edge Case: Large Binary or Generated Files
If your codebase includes compiled assets, minified JavaScript, or generated code, Explore agents can get slow reading those files. They'll still work, but they might read through thousands of lines of [object Object] or minified garbage.
Workaround: Exclude patterns in your task:
Task: "Find all API endpoints. Ignore node_modules/, dist/, and .min.js files."The agent will use Glob to exclude those patterns automatically.
The Plan Agent: Architecture and Strategy
What It Does
The Plan agent is your architecture consultant. It can't write code, but it can research, analyze, and devise strategies. It's the agent you use when you need thinking, not doing.
| Tool | Available | Why |
|---|---|---|
| Glob | ✅ Yes | Understand file structure |
| Grep | ✅ Yes | Find patterns and references |
| Read | ✅ Yes | Examine code in detail |
| WebSearch | ✅ Yes | Research tech, frameworks, best practices |
| Edit | ❌ No | Never writes to existing files |
| Write | ❌ No | Never creates new files |
| Bash | Limited | No system modifications |
When to Use It
Use Plan when:
- You're designing a refactor and need to understand current architecture first
- You're evaluating technology choices (Plan can research alternatives)
- You're planning a migration and need a step-by-step strategy
- You're implementing a complex feature and need to understand integration points
- You want architectural input without committing to implementation
- You're a tech lead planning work for other developers
- You need to document decisions before starting work
- You're weighing tradeoffs between multiple approaches
Example: Planning a Database Migration
Let's say you want to migrate from SQLite to PostgreSQL. An architect doesn't immediately start coding—they plan first. This matters because database migrations are complex, irreversible, and risky. You need to know what you're getting into.
Agent.spawn({
subagent_type: "plan",
task: "We're migrating from SQLite to PostgreSQL.
1. Find all database queries in the codebase (grep for SQL patterns)
2. Identify all files that import our database module
3. Catalog the different query patterns we use (SELECT, INSERT, UPDATE, DELETE, JOINs)
4. Research the differences between SQLite and PostgreSQL that affect our code
5. Create a migration strategy with phases, risk assessment, and rollback plan"
})The Plan agent would:
- Scan the codebase with Glob and Grep to find database interaction patterns
- Read database config files to understand current setup (connection strings, credentials handling)
- WebSearch for:
- SQLite→PostgreSQL migration guides
- Common pitfalls and compatibility issues
- Data type differences (especially numeric precision, date handling)
- Performance considerations
- Analyze the code to identify high-risk areas (transactions, type casting, constraints)
- Produce a plan like:
MIGRATION STRATEGY: SQLite → PostgreSQL
Phase 1: Preparation (1-2 days)
- Install PostgreSQL driver (pg instead of sqlite3)
- Create PostgreSQL database with matching schema
- Risk: Schema differences between dialects (e.g., SQLite has no native boolean type)
- Mitigation: Run type compatibility tests, document custom types
- Success criteria: PostgreSQL DB created, populated with test data
Phase 2: Driver Swap (1 day)
- Replace sqlite3 imports with pg
- Update connection strings (test against staging instance)
- Risk: Query syntax differences (SQLite is more forgiving with types)
- Mitigation: Have test suite ready, run with verbose logging
- Success criteria: App starts, connects to PostgreSQL without errors
Phase 3: Query Compat Check (2-3 days)
- Run full test suite with PostgreSQL
- Fix broken queries (especially PRAGMA, type coercion, string concatenation)
- Risk: Type strictness in PostgreSQL will surface bugs in query construction
- Mitigation: Fix tests incrementally, check one category at a time
- Success criteria: All tests pass, no warnings in PostgreSQL logs
Phase 4: Data Migration (1-2 days)
- Dump SQLite data, transform to PostgreSQL format
- Verify data integrity (row counts, checksums, referential integrity)
- Risk: Data loss if transformation fails, rollback needed
- Mitigation: Keep SQLite running, parallel test, validate before cutover
- Success criteria: Data matches row count, checksums, spot checks
Phase 5: Performance Tuning (ongoing)
- Profile queries in PostgreSQL (different query optimizer)
- Add indexes based on actual usage patterns
- Risk: Different query optimizer behavior could slow some queries
- Mitigation: A/B test performance, keep SQLite as fallback temporarily
HIGH-RISK AREAS:
- src/db/transactions.js (uses PRAGMA, may need rewriting)
- src/models/validation.js (type coercion expectations)
- src/api/search.js (complex joins - PostgreSQL stricter)
- src/api/bulk-import.js (large batch operations - memory/performance)
ESTIMATED EFFORT: 5-7 days
RECOMMENDED WINDOW: Off-peak time, plan for 24-48hr downtime tolerance
ROLLBACK PLAN:
- Keep SQLite running in read-only mode for 1 week
- If critical issues found, switch back to SQLite
- After 1 week, archive SQLite backup
SUCCESS CRITERIA:
- All tests pass with PostgreSQL
- Query performance ≥ SQLite baseline (within 10%)
- Data integrity verified (row counts, checksums)
- User-facing queries under 200ms p95
Notice: no code was written. Just analysis and strategy. That's what Plan excels at.
Why This Matters
Planning without a full rewrite is powerful because:
- You can iterate on strategy: Refine the plan with stakeholders before committing resources
- You surface unknowns early: Better to discover integration challenges in planning than mid-implementation
- You reduce scope creep: Clear phases and acceptance criteria prevent endless refactoring
- You distribute knowledge: The written plan becomes a reference for the team
- You get buy-in: Non-technical stakeholders understand the timeline and risks
- You can estimate effort: "How long?" becomes answerable before work starts
Hidden Layer: Research-Driven Planning
When Plan agents use WebSearch, they're not just looking for the first stack overflow answer. They're synthesizing multiple sources to understand:
- Official documentation: What does the vendor say?
- Real-world experiences: What issues do users report on GitHub?
- Performance benchmarks: How do the systems compare under load?
- Security considerations: Are there known vulnerabilities?
- Community maturity: Is there a vibrant ecosystem or are you on your own?
For a SQLite→PostgreSQL migration, the research might uncover:
- PostgreSQL has stricter type coercion (good for catching bugs, bad for legacy code)
- Date handling is different (SQLite stores as text by default)
- String concatenation works differently (SQLite is forgiving)
- PRAGMA statements are PostgreSQL-specific and need rewriting
This research prevents the "oh, we didn't know that" moment mid-implementation.
Real-World Scenario: Feature Implementation Strategy
You want to add real-time notifications to your SaaS app. A Plan agent could:
- Analyze current code to understand your event system (if any exists)
- Research WebSocket libraries, pub/sub patterns, cloud solutions
- Review the architecture to find the right integration points (your existing API layer, event handling)
- Propose multiple options:
- Option A: Socket.io (easiest, most overhead)
- Option B: WebSockets + Redis pub/sub (more work, more control)
- Option C: Server-Sent Events (simpler than WebSockets, broadcasts only)
- Create a comparison matrix:
| Approach | Pros | Cons | Effort | Risk | Scaling | Complexity |
|---|---|---|---|---|---|---|
| Socket.io | Easy, testing libs | Extra dependency | 2 days | Low | Medium | Low |
| WS + Redis | More control, fast | More moving parts | 4 days | Medium | High | Medium |
| SSE | Lightweight, standard | Unidirectional | 1 day | Low | Low | Low |
The team can then make an informed decision. No code written, but the path forward is clear, and everyone understands the tradeoffs.
The General-Purpose Agent: Full Power
What It Does
The General-Purpose agent is the all-purpose tool. It has access to every capability Claude Code offers. It's the agent you deploy when you have a clear plan and are ready to execute at full speed.
| Tool | Available |
|---|---|
| Glob | ✅ Yes |
| Grep | ✅ Yes |
| Read | ✅ Yes |
| Edit | ✅ Yes |
| Write | ✅ Yes |
| Bash | ✅ Yes (full access) |
| WebSearch | ✅ Yes |
| Git | ✅ Yes |
| Compose/Orchestrate | ✅ Yes |
When to Use It
Use General-Purpose when:
- You need to implement code and have a clear plan
- You're doing a complete refactor with confidence in the approach
- You need to write tests alongside implementation
- You're setting up infrastructure (dependencies, config, scaffolding)
- You need flexibility and don't know all the constraints upfront
- You're in "sprint mode" with aggressive timelines
- You need to touch multiple files in a coordinated way
- You need to run compilation or tests to validate your changes
Example: Complete Feature Implementation
Let's say the Plan agent created a strategy for adding real-time notifications, and you decided to go with Socket.io. Now you hand off to a General-Purpose agent:
Agent.spawn({
subagent_type: "general-purpose",
task: "Implement real-time notifications with Socket.io.
1. Add socket.io to package.json
2. Create src/realtime/socket-handler.js with connection/disconnect logic
3. Create src/realtime/events.js with event emitter pattern
4. Integrate into Express server in src/server.js
5. Add tests in tests/realtime/socket-handler.test.js
6. Update docs/REALTIME.md with usage examples
7. Run tests to verify everything works
8. Create a feature branch and commit with clear messages"
})The General-Purpose agent would:
- Read package.json to understand current setup, dependencies, and script hooks
- Edit package.json to add socket.io dependency
- Write new files for socket handler, events, and tests
- Edit the main server.js to integrate Socket.io server initialization
- Write test files with proper coverage
- Update documentation with code examples
- Run
npm testto verify all tests pass - Run
npm run lintto check code quality - Create a git feature branch and commit all changes
- All while handling errors, managing dependencies, and validating structure
This is what you want when implementation is clear and you need execution.
Why This Matters
General-Purpose agents are powerful because they:
- Solve complex problems end-to-end: No handoff delays between read/analyze/write phases
- Handle unknowns gracefully: Can adjust approach as they discover constraints
- Create working solutions: Not just plans, but runnable, tested code
- Reduce iteration: Often get it right the first time when the task is clear
- Build confidence: You can see progress across multiple files simultaneously
- Handle edge cases: They'll notice and fix issues that plans miss
Hidden Layer: Why Not Start with General-Purpose?
You might think: "Why use Explore and Plan if I can just use General-Purpose for everything?"
The answer is efficiency and risk. A General-Purpose agent investigating a codebase is like using a bulldozer to excavate a basement—it works, but you're using a cannon to kill a mosquito. More importantly:
- Speed: Explore agents are 10-100x faster for read-only tasks
- Cost: General-Purpose agents use more computational resources
- Risk: General-Purpose agents can modify files. If they misunderstand the task, damage is easier
- Focus: Explore and Plan agents are optimized for their specific tasks, so they surface answers faster
The pattern is: Explore to understand, Plan to strategize, General-Purpose to execute. Each one does its job better than the others.
Comparing the Three Types
Here's a quick decision matrix to help you choose:
| Scenario | Best Agent | Why |
|---|---|---|
| "How does this function work?" | Explore | Pure investigation, no writes needed |
| "What's calling this module?" | Explore | Fast codebase search |
| "Design a refactor strategy" | Plan | Needs research, not implementation |
| "Evaluate tech options" | Plan | WebSearch is key; writing code premature |
| "Implement a known feature" | General-Purpose | Clear requirements, execution phase |
| "Fix a bug across files" | General-Purpose | Needs write access for fixes |
| "Audit what's unsafe" | Explore | Read-only ensures integrity |
| "Plan a migration" | Plan | Architecture first, then hand off to General-Purpose |
| "Refactor with confidence" | General-Purpose | Full flexibility for large changes |
| "Understand legacy code" | Explore | Map relationships before touching anything |
| "Prioritize technical debt" | Plan | Analyze impact, create roadmap |
| "Implement debt fixes" | General-Purpose | Execute the roadmap across multiple files |
Key insight: Many complex tasks use multiple agent types in sequence:
- Explore to understand current state and identify issues
- Plan to devise strategy and research solutions
- General-Purpose to implement the plan and handle edge cases
This pattern is so common that you should make it your default workflow for anything non-trivial.
Tool Access Breakdown
Let's dig deeper into what each agent can actually do with their tools:
Explore Agent Tool Details
Glob (file pattern matching):
# Finding all JavaScript files
pattern: **/*.js
# Finding all test files
pattern: **/*.{test,spec}.js
# Finding all config files
pattern: **/config/**/*.{yaml,json,yml}
# Finding potential entry points
pattern: **/index.{js,ts}
# Finding all modules in src/
pattern: src/**/*.jsGrep (content search):
# Search for function definitions
pattern: "^function\s+\w+"
# Search for imports
pattern: "^import\s+.*from"
# Search for exports
pattern: "^export\s+(default\s+)?(function|class|const)"
# Search for database calls
pattern: "(db\.|query\(|insert\(|update\(|delete\()"
# Case-insensitive search for error handling
pattern: "catch|throw|Error" (with -i flag)
# Find TODO or FIXME comments
pattern: "(TODO|FIXME|HACK|XXX).*$"Read (file contents):
# Read up to 2000 lines (default, fast)
file_path: /path/to/file.js
# Read specific range (for large files, efficient)
file_path: /path/to/file.js
offset: 100
limit: 50
# Read from a specific line to end of file
file_path: /path/to/file.js
offset: 500Bash (Limited):
- ✅
ls,pwd,echo,grep,find,cat,head,tail - ❌ No
git, nonpm install, norm -rf, nosystemctl
The limitation is intentional: Explore agents can't modify the system, only read from it.
Plan Agent Additional Tool
WebSearch (external research):
# Research a technology
query: "PostgreSQL vs MySQL migration guide 2024"
# Find best practices
query: "Node.js real-time notification patterns"
# Check compatibility
query: "SQLite PRAGMA compatibility with PostgreSQL"
# Understand patterns
query: "microservices architecture authentication patterns 2025"
# Evaluate libraries
query: "Socket.io vs native WebSocket performance comparison"Plan agents use search results to ground their strategy in real-world experience and current best practices.
General-Purpose Agent Full Toolkit
Everything Explore and Plan have, plus:
Edit (modify existing files):
file_path: /path/to/file.js
old_string: "const x = 1;"
new_string: "const x = 2;"Write (create new files):
file_path: /path/to/newfile.js
content: "entire file contents here"Bash (full access):
command: "npm install socket.io"
command: "npm test"
command: "git add . && git commit -m 'Feature: real-time notifications'"Git operations:
- Create branches and commits
- Push to remote (respecting branch protections)
- Create and manage PRs
- View history and diffs
Practical Patterns: Using Agent Types Together
Pattern 1: Understand → Plan → Build (The Standard Flow)
You've inherited a codebase and need to add a feature. Here's the workflow:
Step 1: Explore Agent (5-10 minutes)
Task: "Map the authentication system.
- Find all auth-related files
- Identify entry points (middleware, decorators, routes)
- List all permission checks and how they're implemented
- Find where user roles are assigned and validated
- Identify which endpoints are protected vs public
- Show me the login/logout flow"
Output: You have a complete map of the auth system, understand how it works, and know where to integrate.
Step 2: Plan Agent (10-15 minutes)
Task: "Based on the auth system you found, plan adding
team-based permissions. How would it integrate?
- Research best practices for team-based access control
- Identify what needs to change in the auth system
- Plan the data model for team memberships and roles
- Suggest where to add permission checks
- Estimate effort and identify risks"
Output: You have a strategy that integrates with the existing auth system, understands the patterns used, and can be reviewed before implementation.
Step 3: General-Purpose Agent (1-2 hours)
Task: "Implement team-based permissions following
the strategy from the Plan agent.
- Create new models/team.js with schema
- Create new models/team-membership.js for user-team relationships
- Add role checks to middleware (update current auth middleware)
- Update tests with team-based scenarios
- Update documentation with examples
- Run all tests and commit with clear messages"
Output: Complete implementation, tested, documented, and committed.
This three-step pattern prevents "false start" implementations that don't fit the architecture.
Pattern 2: Fast Issue Resolution
A bug is reported. You need answers quickly.
Explore Agent (5 min):
Task: "User says 'Profile picture upload fails with 413 error.'
Find all file upload code. Where is it?
Where does it validate file size?
Where does it save files?
What error handling exists?
What are the size limits configured?"
Output: You have all the upload code, limits, and error paths. You likely know the issue.
Plan Agent (5 min):
Task: "Based on the upload code, what could cause
a 413 error (payload too large)? List possible bugs with confidence levels.
Research common Node.js upload issues with multer/express.
Suggest fixes in priority order."
Output: Prioritized list of likely causes and fixes.
General-Purpose Agent (15 min):
Task: "Fix the upload bug based on the Plan analysis.
- Add better file size validation with clear error messages
- Add logging to debug what's happening
- Add tests that verify the fix
- Commit with a clear message"
Output: Bug fixed, logged, tested, committed.
Total: 25 minutes instead of hours of manual debugging.
Pattern 3: Security Audit
You need to verify your system handles secrets safely.
Explore Agent:
Task: "Find all places where we handle secrets
(API keys, tokens, passwords).
- Grep for 'process.env'
- Find all .env files
- Look for hardcoded strings that look like credentials
- Check where secrets are logged or exposed
- Show me how secrets are passed between modules
- Find all places where auth tokens are stored"
Output: Complete inventory of secret handling, potential leaks identified.
Plan Agent:
Task: "Based on secrets usage, what are the risks?
How should we be handling them according to best practices?
Research secret management, rotation, audit logging.
Suggest a complete secret management strategy."
Output: Risk assessment and strategy for safer secret handling.
General-Purpose Agent (if needed):
Task: "Implement secure secret handling per the plan:
- Add dotenv if missing, configure properly
- Remove hardcoded values
- Add secret validation at startup
- Update logging to sanitize secrets
- Add audit logging for secret access
- Write tests for secret handling"
Output: Secure secret system, auditable, tested.
Avoiding Common Pitfalls
Pitfall 1: Using General-Purpose When Explore Would Suffice
Problem: You spin up a General-Purpose agent for a simple question. It takes longer, uses more resources, and overkills the task. You wait 5 minutes for an answer that Explore could have given in 30 seconds.
Better approach: Use Explore for pure investigation. Save General-Purpose for execution.
# ❌ Overkill
Agent.spawn({
subagent_type: "general-purpose",
task: "Find all places that use this deprecated function"
})
# ✅ Right-sized
Agent.spawn({
subagent_type: "explore",
task: "Find all places that use this deprecated function"
})The General-Purpose agent is more powerful but slower for read-only tasks. It's like using a excavator to rake leaves.
Pitfall 2: Skipping the Plan Phase
Problem: You jump straight to General-Purpose implementation without understanding the system first.
Result: You implement something incompatible with existing patterns, create more work, frustrate the team. You waste hours building something that doesn't fit.
Better approach: Always Explore → Plan for non-trivial tasks.
# ❌ Wrong order - building blind
Agent.spawn({
subagent_type: "general-purpose",
task: "Add authentication to the API"
// But you don't know if auth already exists!
// You don't know the patterns used!
})
# ✅ Right sequence
# First: Explore to see if auth exists and understand it
# Then: Plan how to integrate new auth requirements with existing patterns
# Then: General-Purpose to implement in the established wayThe cost of getting the architecture wrong is much higher than taking 15 minutes to plan first.
Pitfall 3: Using Explore for Tasks Requiring Changes
Problem: You ask an Explore agent to "fix the bug," forgetting it can't write files.
Result: Wasted cycles. The agent analyzes the bug but can't implement the fix. You get frustration instead of a solution.
Better approach: Use Explore to understand, then General-Purpose to fix.
# ❌ Will fail—Explore can't write
Agent.spawn({
subagent_type: "explore",
task: "Fix the authentication bug in src/auth.js"
})
# ✅ Correct approach
Agent.spawn({
subagent_type: "explore",
task: "Understand the authentication bug in src/auth.js"
})
// Then
Agent.spawn({
subagent_type: "general-purpose",
task: "Fix the authentication bug based on Explore findings"
})Pitfall 4: Expecting Plan Agent to Write Production Code
Problem: You ask a Plan agent to "implement feature X" and get frustrated when it doesn't produce working code.
Remember: Plan agents create strategies and analyses, not production code. That's by design. They're consultants, not implementers.
# ❌ Wrong expectations
Agent.spawn({
subagent_type: "plan",
task: "Implement the new user roles system"
// Will give you a strategy, not code
})
# ✅ Correct usage
Agent.spawn({
subagent_type: "plan",
task: "Design the new user roles system. How should it integrate? What are the risks?"
// Will give you a thorough design and strategy
})Default Capabilities and Customization
All built-in agent types come with sensible defaults:
- Error handling: They'll retry failed operations within reason
- Context awareness: They read project docs and configuration
- Output formatting: They provide structured results with file paths and line numbers
- Safety checks: Explore and Plan won't delete or overwrite anything
- Graceful degradation: If a tool fails, they report it clearly rather than crashing
You can't customize the tool access of built-in types (that's the whole point—they're preconfigured for safety and efficiency). But you can customize the task description and context you provide:
Agent.spawn({
subagent_type: "explore",
task: "Find all database queries and catalog their patterns",
context: {
focus_area: "src/db/",
file_extensions: [".js", ".ts"],
exclude: ["node_modules", "tests"],
output_format: "structured"
}
})This tells the agent exactly where to focus, what to look at, and how to format results. Much more efficient than vague instructions.
When to Create Custom Agents
Built-in types cover ~90% of use cases. Consider a custom agent only if:
- You need specialized tools: Your agent needs access to a proprietary API, internal tool, or specialized database that's not in the built-ins
- You need role-based access: Your team has strict permissions (e.g., junior devs get Explore-only, seniors get General-Purpose)
- You have recurring patterns: You're spawning 20 agents per week with identical configs (create a reusable template)
- You need specific guardrails: You want additional validation or approval steps beyond what built-ins provide
Otherwise, the built-ins are optimized for speed, safety, and ease of use. They've already solved the hard problems.
Real Examples from Production
Example 1: Onboarding New Developers
When a developer joins your team, give them Explore agent access (read-only, safe):
"Welcome! Run this to understand the codebase:
Agent explore-codebase:
- Map all service modules (src/services/)
- Show the data flow from API to database
- Find all environment variables used
- Identify the test setup
- Find entry points and main flows"
This takes 10 minutes instead of a week of tribal knowledge transfer. New devs get independent, can ask good questions, and ramp up faster.
Example 2: Dependency Upgrade Strategy
You want to upgrade Express from v4 to v5. Plan agent first:
Agent.spawn({
subagent_type: "plan",
task: "Plan upgrade from Express 4 to 5:
1. Find all Express usage in codebase
2. Research v5 breaking changes
3. Identify affected areas
4. Estimate effort and risk
5. Create step-by-step plan"
})Output is a detailed plan the team can discuss before implementing. Much safer than "let's just upgrade and fix what breaks."
Example 3: Code Debt Cleanup
Your codebase has technical debt. Explore agent surveys the damage:
Agent.spawn({
subagent_type: "explore",
task: "Find all uses of deprecated methods.
- Search for .then().catch() (should use async/await)
- Find var declarations (should be const/let)
- Find console.log statements in production code
- Find TODO or FIXME comments
- Create a priority list with file locations and effort estimates"
})Now you have data to justify cleanup sprints and estimate effort accurately. Instead of "our code is messy," you have "we have 47 async/await migrations, 120 var declarations, and 89 debug logs to clean up."
Best Practices
Here's your playbook for using agent types effectively:
1. Use the right agent for the task size:
- Simple questions → Explore (seconds)
- Design work → Plan (minutes)
- Implementation → General-Purpose (longer, but complete)
2. Chain agents intelligently:
Explore (understand)
↓
Plan (strategize)
↓
General-Purpose (execute)
This is the golden path for most work.
3. Document the task clearly:
# ❌ Vague
Agent.spawn({
subagent_type: "explore",
task: "Investigate the codebase"
})
# ✅ Clear and specific
Agent.spawn({
subagent_type: "explore",
task: "Find all places where user input enters the system
and is processed without sanitization.
Report file paths, line numbers, function names, and the specific input handling code."
})Clear tasks get clearer answers faster.
4. Include context when helpful:
Agent.spawn({
subagent_type: "plan",
task: "Plan a refactor of the auth system",
context: "We must remain backward compatible with v1 API clients"
})Context prevents the agent from going in wrong directions.
5. Review Explore/Plan output before acting:
# Explore agent identifies 50 files using deprecated method
# ✅ Review the list before creating bulk fix task
# ✅ Spot-check a few to make sure they're actually using it
# ❌ Don't blindly spawn General-Purpose to "fix all 50"Verification prevents mistakes at scale.
6. Use version control with General-Purpose agents:
All changes should create branches and PRs, never push directly to main. Treat agent code changes like human code changes.
Comparing Built-in vs Custom Agents
| Aspect | Built-in | Custom |
|---|---|---|
| Setup time | Minutes | Hours/days |
| Safety | Preconfigured | Your responsibility |
| Speed | Optimized | Depends on config |
| Flexibility | Limited by design | Unlimited |
| Maintenance | None | Ongoing |
| Learning curve | Shallow | Steep |
| Predictability | High | Lower |
Rule of thumb: Start with built-ins. Only move to custom if built-ins genuinely can't do the job. The built-ins are battle-tested and optimized.
The Economics of Agent Type Selection
Understanding when to use each agent type has real business impact. Let's break down the economics:
Time Investment Analysis
Consider a typical mid-size implementation task: adding a feature to a 50k-line codebase. The time breakdown differs significantly by approach:
Without agents (traditional approach):
- Manual code review: 3-4 hours
- Architecture discussion: 2-3 hours
- Implementation planning: 2 hours
- Writing code: 4-6 hours
- Testing and fixes: 2-4 hours
- Code review cycles: 2-4 hours
- Total: 15-25 hours spread across 1-2 weeks
With chained agents (Explore → Plan → General-Purpose):
- Explore agent (understand system): 15 minutes (automation)
- Plan agent (devise strategy): 20 minutes (automation)
- Human review of strategy: 15 minutes
- General-Purpose agent (implement): 45 minutes (automation)
- Human testing and approval: 30 minutes
- Total: ~2.5 hours of human time, compressed into 1-2 hours of wall time
The multiplication effect becomes clear when you scale. A team doing 10 features per sprint saves 150+ human-hours per quarter. At a loaded cost of $150/hour, that's $22,500 in recovered productivity per quarter, per team member.
Risk Mitigation Through Progressive Capability
The three-agent pattern isn't just about speed—it's a risk management strategy. Each layer adds validation:
Explore validates understanding. Before making any changes, you confirm the system actually works the way you think it does. Wrong assumptions caught here cost minutes. Wrong assumptions discovered during implementation cost days.
Plan validates approach. You discover architectural incompatibilities, missing dependencies, and integration challenges before writing code. Finding these issues in planning saves 10-20 hours of rework per feature.
General-Purpose validates execution. With clear understanding and strategy in place, the implementation phase has minimal surprises. Tests pass faster, integration is smoother, and human review focuses on edge cases rather than fundamental correctness.
This layered validation reduces the defect escape rate—bugs that make it to production—by an estimated 60-70% compared to "skip planning and just start coding."
Resource Optimization
Different agent types consume different resources:
- Explore agents are cheap: fast, read-only, minimal computation
- Plan agents are moderate: require web search and synthesis, but still no file modifications
- General-Purpose agents are expensive: full capability, longer execution times, more complex error handling
Smart sequencing means you spend expensive resources (General-Purpose agents) only when it matters. Using General-Purpose for investigation is like hiring a senior architect to answer junior-level questions—technically it works, but you're wasting expertise and budget.
The recommendation: invest in understanding first (cheap Explore), strategy second (moderate Plan), execution last (expensive General-Purpose). This inverted cost pyramid maximizes ROI.
Advanced Patterns and Sophisticated Workflows
Beyond the basic three-step pattern, experienced teams develop more sophisticated agent workflows:
The Parallel Investigation Pattern
For large systems with multiple subsystems, spawn multiple Explore agents in parallel:
Main system understanding task
├─ Explore: Authentication system
├─ Explore: Database layer
├─ Explore: API contract / external dependencies
├─ Explore: Configuration management
└─ Explore: Testing infrastructure
Results converge → Plan agent synthesizes findings
This approach completes investigation 4-5x faster than sequential exploration because you're investigating multiple concerns simultaneously.
The Validation Loop Pattern
After General-Purpose implementation:
General-Purpose: Implement feature
↓
Explore: Audit the changes for quality
├─ Check for security issues
├─ Verify style guide compliance
├─ Confirm test coverage
└─ Validate documentation
↓
Plan: Review for architectural risks
├─ Does it integrate cleanly?
├─ Are there performance implications?
├─ What's the maintenance burden?
This catches implementation issues before they make it to code review, reducing review cycles and deployment delays.
The Continuous Monitoring Pattern
For systems requiring ongoing compliance or security:
Scheduled Explore agents run weekly:
- Scan for deprecated dependencies
- Find outdated versions
- Identify missing documentation
- Locate abandoned code sections
Results feed into compliance dashboard
This transforms code quality from "something we worry about sometimes" to "continuously monitored metric." Teams using this pattern reduce technical debt accumulation by 40-50%.
Conclusion
Claude Code's built-in agent types are designed around progressive capability with safety guardrails.
- Explore agents are your go-to for fast codebase investigation—use them liberally for understanding the lay of the land
- Plan agents excel at architecture and strategy—they're your thinking partner before implementation
- General-Purpose agents are your doers—use them when you have a clear plan and are ready to build
The sweet spot for complex tasks is chaining them: Explore to understand, Plan to strategize, General-Purpose to execute. This pattern saves time, prevents mistakes, and builds confidence.
They're preconfigured, fast, and safe by default. You don't need to think about permissions or capabilities—just pick the right one for the job and go. When applied systematically across your engineering teams, the cumulative impact on velocity, quality, and morale is transformative. Teams report reduced engineering friction, faster onboarding, higher confidence in changes, and measurable improvements in deployment frequency and mean time to recovery.
-iNet
Have you used agent types in Claude Code? Share your patterns in the comments. We'd love to hear how you're automating codebase work.