Files
gh-basher83-lunar-claude-pl…/skills/claude-agent-sdk/references/agent-patterns.md
2025-11-29 18:00:18 +08:00

192 lines
5.5 KiB
Markdown

# Agent and Subagent Definition Patterns
This guide covers how to define agents and subagents programmatically using the Claude Agent SDK.
## Core Concepts
**AgentDefinition** - Defines a specialized agent with specific tools, prompts, and model configuration.
**Programmatic Definition** - SDK best practice is to define agents programmatically using the `agents` parameter in `ClaudeAgentOptions`, not filesystem auto-discovery.
## Basic Agent Definition
```python
from claude_agent_sdk import AgentDefinition, ClaudeAgentOptions
options = ClaudeAgentOptions(
agents={
"agent-name": AgentDefinition(
description="When to use this agent",
prompt="System prompt defining role and behavior",
tools=["Read", "Grep", "Glob"],
model="sonnet" # or "opus", "haiku", "inherit"
)
}
)
```
## AgentDefinition Fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `description` | `str` | Yes | Natural language description of when to use this agent |
| `prompt` | `str` | Yes | Agent's system prompt defining role and behavior |
| `tools` | `list[str]` | No | Array of allowed tool names. If omitted, inherits all tools |
| `model` | `str` | No | Model override: "sonnet", "opus", "haiku", or "inherit" |
## Common Patterns
### Read-Only Analyzer Agent
For code review, architecture analysis, or documentation review:
```python
"code-reviewer": AgentDefinition(
description="Reviews code for best practices, security, and performance",
prompt="""You are a code reviewer. Analyze code for:
- Security vulnerabilities
- Performance issues
- Best practice adherence
- Potential bugs
Provide constructive, specific feedback.""",
tools=["Read", "Grep", "Glob"],
model="sonnet"
)
```
### Code Modification Agent
For implementing features or fixing bugs:
```python
"code-writer": AgentDefinition(
description="Implements features and fixes bugs",
prompt="""You are a code implementation specialist.
Write clean, tested, well-documented code.
Follow project conventions and best practices.""",
tools=["Read", "Write", "Edit", "Grep", "Glob"],
model="sonnet"
)
```
### Test Execution Agent
For running tests and analyzing results:
```python
"test-runner": AgentDefinition(
description="Runs tests and analyzes results",
prompt="""You are a testing specialist.
Execute tests, analyze failures, and provide clear diagnostics.
Focus on actionable feedback.""",
tools=["Bash", "Read", "Grep"],
model="sonnet"
)
```
### Multiple Agents Pattern
Orchestrator with specialized subagents:
```python
options = ClaudeAgentOptions(
system_prompt="claude_code", # Orchestrator needs Task tool knowledge
allowed_tools=["Bash", "Task", "Read", "Write"],
agents={
"analyzer": AgentDefinition(
description="Analyzes code structure and patterns",
prompt="You are a code analyzer. Examine structure, patterns, and architecture.",
tools=["Read", "Grep", "Glob"]
),
"fixer": AgentDefinition(
description="Fixes identified issues",
prompt="You are a code fixer. Apply fixes based on analysis results.",
tools=["Read", "Edit", "Bash"],
model="sonnet"
)
}
)
```
## Loading Agent Definitions from Files
While programmatic definition is recommended, you can still store agent prompts in markdown files:
```python
import yaml
def load_agent_definition(path: str) -> AgentDefinition:
"""Load agent definition from markdown file with YAML frontmatter."""
with open(path) as f:
content = f.read()
parts = content.split("---")
frontmatter = yaml.safe_load(parts[1])
system_prompt = parts[2].strip()
# Parse tools (can be comma-separated string or array)
tools_value = frontmatter.get("tools", [])
if isinstance(tools_value, str):
tools = [t.strip() for t in tools_value.split(",")]
else:
tools = tools_value
return AgentDefinition(
description=frontmatter["description"],
prompt=system_prompt,
tools=tools,
model=frontmatter.get("model", "inherit")
)
# Load and register programmatically
investigator = load_agent_definition(".claude/agents/investigator.md")
options = ClaudeAgentOptions(
agents={"investigator": investigator}
)
```
## Best Practices
1. **Use programmatic registration** - Define agents via `agents` parameter, not filesystem auto-discovery
2. **Set orchestrator system_prompt** - Main agent needs `system_prompt="claude_code"` to use Task tool
3. **Specific descriptions** - Agent descriptions determine when they're used
4. **Restrict tools** - Limit agent tools to minimum needed for safety and clarity
5. **Match agent names** - Ensure agent names in `agents={}` match what orchestrator references
## Anti-Patterns
**Relying on filesystem auto-discovery**
```python
# SDK will auto-discover .claude/agents/*.md but this is NOT recommended
options = ClaudeAgentOptions() # Missing explicit agents={}
```
**Programmatic registration**
```python
options = ClaudeAgentOptions(
agents={"agent-name": AgentDefinition(...)}
)
```
**Missing orchestrator system prompt**
```python
options = ClaudeAgentOptions(
agents={...}
# Missing system_prompt="claude_code"
)
```
**Proper orchestrator configuration**
```python
options = ClaudeAgentOptions(
system_prompt="claude_code", # Orchestrator knows how to use Task tool
agents={...}
)
```