11 KiB
Claude Agent SDK Validation Checklist
This checklist helps validate SDK applications against official patterns and best practices from the claude-agent-sdk skill documentation.
Quick Validation
Use this checklist when:
- Creating new SDK applications
- Reviewing SDK code
- Debugging SDK issues
- Ensuring alignment with best practices
1. Imports & Dependencies
Required Checks
-
Async runtime import
- Uses
import anyio(official SDK examples use anyio) - Comment reflects official preference:
# Official SDK examples use anyio - Reference: Official examples consistently use anyio
- Uses
-
Claude SDK imports are accurate
ClaudeAgentOptionsfor configurationClaudeSDKClientfor continuous conversations ORqueryfor one-shot tasksAgentDefinitionif using programmatic agents- Message types:
AssistantMessage,ResultMessage,TextBlock - Permission types if using callbacks:
PermissionResultAllow,PermissionResultDeny - Reference:
references/api-reference.md
-
UV script headers (if applicable)
- Uses
#!/usr/bin/env -S uv run --script --quiet - Has PEP 723 dependencies block with
claude-agent-sdk>=0.1.6 - Reference:
assets/sdk-template.pylines 1-7
- Uses
2. Async Runtime
Required Checks
-
Runtime execution is correct
- Uses
anyio.run(main)(official SDK examples use anyio.run()) - Comment reflects official preference:
# Official SDK examples use anyio.run() - Reference: Official examples consistently use anyio.run()
- Uses
-
Async/await patterns are correct
- Functions marked as
async def - Uses
awaitfor SDK calls - Uses
async forfor message streaming - Uses
async withfor ClaudeSDKClient context manager - Reference:
references/best-practices.mdlines 82-94
- Functions marked as
3. Choosing query() vs ClaudeSDKClient
Required Checks
-
Correct approach for use case
query(): One-shot tasks, no conversation memoryClaudeSDKClient: Multi-turn conversations, context retention- Reference: SKILL.md lines 29-44
-
Hooks/Custom tools only with ClaudeSDKClient
- NOT using hooks with
query()(not supported) - NOT using custom tools with
query()(not supported) - Reference: SKILL.md line 45 (important warning)
- NOT using hooks with
4. Orchestrator Configuration
Required Checks
-
System prompt is set correctly
- Uses
system_prompt={"type": "preset", "preset": "claude_code"}for orchestrators (official examples use dict format) - OR uses
system_prompt="claude_code"(string shorthand, equivalent but less explicit) - Custom prompts only for non-orchestrators
- Reference: Official examples use dict format, SKILL.md lines 226-242,
references/system-prompts.md
- Uses
-
Task tool is included
allowed_toolsincludes"Task"for orchestrators- Orchestrators cannot delegate without Task tool
- Reference: SKILL.md line 39,
references/best-practices.mdlines 72-80
-
Agent definitions are programmatic
- Agents defined in
agents={}parameter (preferred) - Clear
description(when to use agent) - Specific
prompt(agent instructions) - Minimal
toolslist (principle of least privilege) - Reference: SKILL.md lines 195-217,
references/agent-patterns.md
- Agents defined in
5. Agent Definitions
Required Checks
-
Agent definition structure is correct
AgentDefinition( description="...", # When to use this agent prompt="...", # Agent instructions tools=[...], # Minimal tool set model="sonnet" # or "opus", "haiku", "inherit" )- Reference: SKILL.md lines 195-217
-
Agent names match references
- Names in
agents={}match Task tool usage - No naming mismatches between definition and invocation
- Reference:
references/best-practices.mdlines 43-52
- Names in
-
Tools are restricted to minimum needed
- Read-only agents:
["Read", "Grep", "Glob"] - Code modifiers:
["Read", "Edit", "Bash"] - No excessive tool permissions
- Reference: SKILL.md lines 248-256,
references/best-practices.mdlines 54-71
- Read-only agents:
6. Permission Control
Required Checks
-
Permission strategy is appropriate
- Simple use case →
permission_modeonly - Complex logic →
can_use_toolcallback - Reference:
references/tool-permissions.mdlines 13-114
- Simple use case →
-
Permission mode is valid
- One of:
"acceptEdits","rejectEdits","plan","bypassPermissions","default" - Appropriate for use case (e.g., CI/CD uses
"acceptEdits") - Reference:
references/tool-permissions.mdlines 64-70
- One of:
-
Permission callback (if used) is correct
- Signature:
async def(tool_name, input_data, context) -> PermissionResultAllow | PermissionResultDeny - Returns early for unmatched tools
- Uses
.get()for safe input_data access - Clear denial messages
- Reference:
references/tool-permissions.mdlines 120-344,examples/tool_permission_callback.py
- Signature:
7. Hooks (if used)
Required Checks
-
Hooks ONLY used with ClaudeSDKClient
- NOT using hooks with
query()function - Reference: SKILL.md line 45 (critical warning)
- NOT using hooks with
-
Hook types are supported
- Using ONLY:
PreToolUse,PostToolUse,UserPromptSubmit,Stop,SubagentStop,PreCompact - NOT using unsupported:
SessionStart,SessionEnd,Notification - Reference:
references/hooks-guide.mdline 14 (important warning)
- Using ONLY:
-
Hook signature is correct
async def(input_data, tool_use_id, context) -> HookJSONOutput- Returns empty
{}when hook doesn't apply - Uses
HookMatcherfor tool filtering - Reference:
references/hooks-guide.mdlines 46-68,examples/hooks.py
-
Hook output structure is valid
- Includes
hookEventNameinhookSpecificOutput - PreToolUse: includes
permissionDecision("allow" or "deny") - Includes clear
reasonandsystemMessagefields - Reference:
references/hooks-guide.mdlines 70-144
- Includes
8. ClaudeSDKClient Usage
Required Checks
-
Context manager pattern is used
async with ClaudeSDKClient(options=options) as client: await client.query(...) async for message in client.receive_response(): ...- Reference: SKILL.md lines 88-124
-
Query → receive_response flow
- Calls
await client.query(prompt)first - Then iterates
async for message in client.receive_response() - Does NOT interleave queries and receives incorrectly
- Reference:
examples/streaming_mode.py
- Calls
-
Interrupts (if used) are correct
- Uses
await client.interrupt()to stop execution - Only available with ClaudeSDKClient (not query())
- Reference: SKILL.md lines 139-162
- Uses
9. Message Handling
Required Checks
-
Message types are checked correctly
if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, TextBlock): print(block.text) elif isinstance(message, ResultMessage): # Handle completion- Reference: SKILL.md lines 77-91,
examples/streaming_mode.py
- Reference: SKILL.md lines 77-91,
-
TextBlock extraction is correct
- Iterates through
message.content - Checks
isinstance(block, TextBlock)before accessing.text - Reference:
references/best-practices.mdlines 95-113
- Iterates through
-
ResultMessage handling
- Checks for
message.duration_ms,message.total_cost_usd - Uses optional access (fields may be None)
- Reference:
assets/sdk-template.pylines 86-93
- Checks for
10. Error Handling
Required Checks
-
API key validation
- Checks
os.getenv("ANTHROPIC_API_KEY")before SDK calls - Provides clear error message if missing
- Reference:
assets/sdk-template.pylines 58-63
- Checks
-
Safe dictionary access
- Uses
.get()for input_data, tool_response fields - Handles missing/None values gracefully
- Reference:
references/tool-permissions.mdlines 297-344
- Uses
-
Async exception handling
- Try/except blocks for critical sections
- Proper cleanup in exception cases
- Reference:
references/best-practices.md
11. Settings & Configuration
Required Checks
-
setting_sources is configured (if needed)
- Default behavior: NO settings loaded (isolated environment)
- Explicitly set to load:
["user"],["project"],["local"], or combinations like["user", "project"] - Understands isolation vs loading tradeoff
- Reference:
examples/setting_sources.py(official example shows user, project, local options)
-
Model selection is appropriate
- Orchestrator:
"claude-sonnet-4-5"(simplified, official examples prefer this) or"claude-sonnet-4-5-20250929"(dated version) - Subagents:
"sonnet","opus","haiku", or"inherit" - Reference: Official examples use
claude-sonnet-4-5, SKILL.md line 51,references/agent-patterns.md
- Orchestrator:
-
Budget limits (if needed)
- Uses
max_budget_usdfor cost control - Appropriate for CI/CD and automated workflows
- Reference:
examples/max_budget_usd.py
- Uses
12. Best Practices Compliance
Required Checks
-
Follows DRY principle
- Options extracted to function (e.g.,
get_sdk_options()) - Reusable patterns not duplicated
- Reference:
assets/sdk-template.pylines 33-55
- Options extracted to function (e.g.,
-
Clear comments and documentation
- Docstrings for functions
- Inline comments for complex logic
- Usage notes in module docstring
- Reference:
assets/sdk-template.pylines 8-17
-
Type hints are used
- Function return types specified
- Parameter types for clarity
- Reference:
assets/sdk-template.pyline 36
-
No anti-patterns
- Not using agents for simple tasks (use query() instead)
- Not giving excessive tool permissions
- Not bypassing permissions without reason
- Reference:
references/best-practices.md, skill SKILL.md
Validation Summary Template
After reviewing, fill out this summary:
✅ Passed Checks
- Imports & Dependencies
- Async Runtime
- Orchestrator Configuration
- Agent Definitions
- Permission Control
- Message Handling
- Best Practices
❌ Issues Found
- Issue 1: [Description]
- Issue 2: [Description]
🔧 Fixes Required
- [Specific fix with line reference]
- [Specific fix with line reference]
📊 Overall Assessment
- Accuracy: [%]
- Alignment with docs: [High/Medium/Low]
- Production ready: [Yes/No]
Quick Reference Links
Core Documentation:
- Main skill:
SKILL.md - API reference:
references/api-reference.md - Best practices:
references/best-practices.md
Pattern Guides:
- Agent patterns:
references/agent-patterns.md - Hooks:
references/hooks-guide.md - Permissions:
references/tool-permissions.md - System prompts:
references/system-prompts.md - Subagents:
references/subagents.md
Examples:
- Quick start:
examples/quick_start.py - Template:
assets/sdk-template.py - Complete examples:
examples/*.py