Custom Agents
Creating specialized subagents with curated tool sets.
Overview
ClaudeBox enables a powerful pattern: the main Claude Code agent can spawn specialized subagents, each with their own curated set of MCP tools. This allows for:
- Separation of Concerns - Each agent focuses on what it does best
- Tool Curation - Give agents only the tools they need
- Parallel Work - Multiple specialized agents working together
- Expertise Abstraction - "Ask Venus for design help" vs knowing which tools to use
Why ClaudeBox, Not Claude Code's Task Tool?
Claude Code has a built-in Task tool for spawning subagents. So why do we need ClaudeBox?
The Limitation
Claude Code's Task tool has predefined subagent types with fixed configurations:
| Subagent Type | What It Does | Customizable? |
|---|---|---|
Explore | Search codebase | No |
Plan | Design implementation | No |
general-purpose | General tasks | No |
claude-code-guide | Documentation lookup | No |
These are hardcoded into Claude Code. You cannot:
- Add custom MCP servers (like magic-mcp or context7)
- Restrict which tools the subagent can use
- Define a custom system prompt
- Choose a different model
The Solution: Claude Agent SDK
The Claude Agent SDK is the underlying library that powers Claude Code itself. It provides full programmatic control over agent configuration:
from claude_code_sdk import query, ClaudeAgentOptions
options = ClaudeAgentOptions(
mcp_servers={"magic": {...}, "context7": {...}}, # Any MCP servers
allowed_tools=["Read", "mcp__magic__*"], # Tool restrictions
system_prompt="You are Venus...", # Custom personality
model="claude-sonnet-4-20250514" # Model choice
)
async for message in query("Find a button component", options):
print(message)
ClaudeBox = Agent SDK Over HTTP
ClaudeBox wraps the Agent SDK and exposes it via HTTP with SSE streaming. This lets Claude Code (or any HTTP client) spawn fully customized subagents:
┌────────────────────────────────────────────────────────────────┐
│ Claude Code │
│ │
│ Built-in Task Tool ClaudeBox HTTP Call │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ subagent_type= │ │ POST /chat │ │
│ │ "Explore" │ │ {mcp_servers, │ │
│ │ │ │ allowed_tools, │ │
│ │ Fixed config │ │ system_prompt} │ │
│ │ No customization│ │ │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Predefined │ │ ClaudeBox │ │
│ │ Subagent │ │ (Agent SDK) │ │
│ │ │ │ │ │
│ │ Tools: fixed │ │ Tools: custom │ │
│ │ MCP: none │ │ MCP: any │ │
│ └─────────────────┘ └─────────────────┘ │
└────────────────────────────────────────────────────────────────┘
Comparison
| Capability | Task Tool | ClaudeBox |
|---|---|---|
| Spawn subagents | Yes | Yes |
| Custom MCP servers | No | Yes |
| Tool restrictions | No | Yes |
| Custom system prompt | No | Yes |
| Model selection | Limited | Full |
| Works from Claude Code | Yes | Yes (via HTTP) |
When to Use Each
Use Task Tool when:
- You need basic exploration (
Explore) - You want implementation planning (
Plan) - The predefined types fit your needs
Use ClaudeBox when:
- You need custom MCP tools (magic-mcp, context7, etc.)
- You want to restrict what tools the agent can use
- You need a specialized personality (Venus, Athena, etc.)
- You're building reusable agent patterns
The Subagent Pattern
┌─────────────────────────────────────────────────────────────┐
│ Main Claude Code Agent │
│ │
│ "I need a React component for user settings" │
│ │
└──────────────────────────┬──────────────────────────────────┘
│ HTTP call to ClaudeBox API
▼
┌─────────────────────────────────────────────────────────────┐
│ Venus (Design Agent) │
│ │
│ Brain: Claude Sonnet │
│ Tools: │
│ - magic-mcp (21st.dev component library) │
│ - context7 (documentation lookup) │
│ │
│ "Here's a polished settings component with these files..." │
│ │
└──────────────────────────┬──────────────────────────────────┘
│ Returns design + code
▼
┌─────────────────────────────────────────────────────────────┐
│ Main Claude Code Agent │
│ │
│ Implements the design Venus provided │
│ (Write, Edit, Bash tools) │
│ │
└─────────────────────────────────────────────────────────────┘
Example: Venus (Design Agent)
Venus is a design-specialized subagent that finds and adapts UI components.
Configuration
venus_request = {
"prompt": "Find a user settings component with dark mode toggle",
"system_prompt": """You are Venus, a UI/UX design specialist.
Your job is to:
1. Search for relevant component designs using magic-mcp
2. Look up framework documentation with context7
3. Return complete, ready-to-use component code
Always consider:
- Accessibility (ARIA labels, keyboard nav)
- Responsive design
- Dark mode support
- Consistent styling with existing components
Return the component code and explain any dependencies needed.""",
"model": "claude-sonnet-4-20250514",
"mcp_servers": {
"magic": {
"command": "npx",
"args": ["-y", "@anthropic/magic-mcp"]
},
"context7": {
"command": "npx",
"args": ["-y", "@anthropic/context7-mcp"]
}
},
# Only design-related tools, no file writing
"allowed_tools": [
"mcp__magic__21st_magic_component_builder",
"mcp__magic__21st_magic_component_inspiration",
"mcp__magic__21st_magic_component_refiner",
"mcp__magic__logo_search",
"mcp__context7__resolve-library-id",
"mcp__context7__query-docs"
]
}
Invoking Venus
From Claude Code (main agent), call the ClaudeBox HTTP API:
import httpx
import json
async def ask_venus(prompt: str) -> str:
"""Call Venus subagent for design help."""
venus_request["prompt"] = prompt
async with httpx.AsyncClient() as client:
async with client.stream(
"POST",
"http://localhost:8765/chat",
json=venus_request,
timeout=300.0
) as response:
result = ""
async for line in response.aiter_lines():
if line.startswith("data: "):
event = json.loads(line[6:])
if event["type"] == "text":
result += event["data"]["text"]
elif event["type"] == "done":
return result
return result
# Usage
design = await ask_venus("Find a settings panel component with user preferences")
The main agent receives the design and implements it using its own Write/Edit tools.
What Venus Returns
Venus provides ready-to-implement designs:
## Settings Panel Component
Based on 21st.dev's settings-panel pattern, here's a component
that matches your app's style:
### Dependencies
- @radix-ui/react-switch
- lucide-react
### Component Code
```tsx
// SettingsPanel.tsx
export function SettingsPanel() {
// ... complete implementation
}
Usage
<SettingsPanel
user={currentUser}
onSave={handleSave}
/>
The main agent then implements this using its Write/Edit tools.
Creating Your Own Agents
Step 1: Define the Specialty
What does this agent do better than a general-purpose agent?
| Agent | Specialty | Key Tools |
|---|---|---|
| Venus | UI/UX design | magic-mcp, context7 |
| Athena | Research | web search, context7 |
| Hephaestus | Testing | test runners, coverage |
| Hermes | API integration | HTTP tools, schema validators |
Step 2: Select MCP Tools
Choose tools that match the specialty:
# Research agent
research_tools = {
"context7": {"command": "npx", "args": ["-y", "@anthropic/context7-mcp"]},
"web": {"command": "web-search-mcp"}
}
# Testing agent
testing_tools = {
"coverage": {"command": "coverage-mcp"},
"playwright": {"command": "playwright-mcp"}
}
Step 3: Craft the System Prompt
Define the agent's personality and constraints:
research_system_prompt = """You are Athena, a research specialist.
Your role:
1. Search documentation thoroughly before answering
2. Cite sources for all claims
3. Distinguish between facts and opinions
4. Acknowledge when information is uncertain
You do NOT:
- Write or modify code
- Make implementation decisions
- Execute commands
Return research findings in structured format with citations."""
Step 4: Set Tool Restrictions
Limit tools to prevent scope creep:
# Research agent can only read and search
allowed_tools = [
"Read",
"Glob",
"Grep",
"mcp__context7__query-docs",
"mcp__web__search"
]
# Note: No Write, Edit, or Bash
Step 5: Create a Helper Function
Wrap the HTTP call for easy reuse:
# agents.py - reusable agent helpers
VENUS_CONFIG = { ... } # Full config from above
ATHENA_CONFIG = { ... }
async def ask_venus(prompt: str) -> str:
"""Get design help from Venus."""
return await call_claudebox_agent(VENUS_CONFIG, prompt)
async def ask_athena(prompt: str) -> str:
"""Get research from Athena."""
return await call_claudebox_agent(ATHENA_CONFIG, prompt)
async def call_claudebox_agent(config: dict, prompt: str) -> str:
"""Generic ClaudeBox agent caller."""
config["prompt"] = prompt
async with httpx.AsyncClient() as client:
async with client.stream("POST", "http://localhost:8765/chat",
json=config, timeout=300.0) as response:
result = ""
async for line in response.aiter_lines():
if line.startswith("data: "):
event = json.loads(line[6:])
if event["type"] == "text":
result += event["data"]["text"]
elif event["type"] == "done":
return result
return result
Best Practices
1. Single Responsibility
Each agent should do one thing well:
- Venus: Find and adapt designs
- Athena: Research and cite
- Hephaestus: Test and validate
Don't create a "do everything" agent.
2. Clear Handoffs
Define what the subagent returns:
# Good: Clear deliverable
"Return the component code, required dependencies, and usage example"
# Bad: Vague
"Help with the UI"
3. Tool Minimization
Fewer tools = more focused agent:
# Good: Just what's needed
allowed_tools = ["Read", "mcp__context7__query-docs"]
# Bad: Everything
allowed_tools = None # All tools available
4. Stateless Design
Subagents should be stateless between calls:
# Good: Self-contained request
{"prompt": "Find a button component matching this style: {...}"}
# Bad: Assumes prior context
{"prompt": "Now make it blue"} # What is "it"?
Agent Composition
Combine multiple agents for complex tasks:
Main Agent: "Build a user dashboard"
│
├─► Venus: "Design the layout"
│ Returns: Component structure
│
├─► Athena: "Research dashboard best practices"
│ Returns: UX guidelines, accessibility requirements
│
└─► Main Agent: Implements using both inputs
Uses: Write, Edit, Bash
Future: Agent Registry
Planned features:
- Agent Catalog - Browse available specialized agents
- Agent Metrics - Track performance and usage
- Agent Composition - Define pipelines of agents
- Agent Versioning - Pin to specific agent configurations
See Also
- Agent HTTP API - How to invoke agents
- Janus - Infrastructure orchestration with second opinion pattern