Building Autonomous Agents with the Claude Agent SDK
Learn how to build fully autonomous AI agents using the Claude Agent SDK. Covers the agentic loop, tool configuration, permission management, session persistence, and production deployment patterns.
What Makes an Agent Autonomous?
An autonomous agent is not just a chatbot with tools. It is a system that can independently plan a multi-step approach, execute those steps, observe results, adapt its strategy when things go wrong, and deliver a final outcome -- all without human intervention at each step.
The Claude Agent SDK provides the runtime for this kind of autonomy. It wraps Claude's reasoning capabilities with a tool execution environment, session management, and cost tracking. The same agentic loop powers Claude Code, which has demonstrated autonomous task completion rates exceeding 72% on the SWE-bench Verified benchmark.
The Agentic Loop in Detail
At its core, the Claude Agent SDK runs a loop:
User Input -> Claude Reasoning -> Tool Call -> Tool Result -> Claude Reasoning -> ... -> Final Output
Each iteration is a "turn." The max_turns parameter controls how many iterations the agent can execute before being forced to stop. For simple tasks, 5-10 turns suffice. For complex codebase refactoring, you might need 50 or more.
Python Implementation
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def run_autonomous_agent(task: str) -> str:
options = ClaudeAgentOptions(
model="claude-sonnet-4-5-20250514",
system_prompt="""You are an autonomous software engineering agent.
You can read, write, and execute code. When given a task:
1. Analyze the current state of the codebase
2. Plan your approach
3. Implement changes
4. Verify your changes work by running tests
5. Report what you did and any issues found""",
allowed_tools=["Read", "Write", "Edit", "Bash", "Glob", "Grep"],
max_turns=30,
permission_mode="auto", # Auto-approve tool calls
)
final_response = ""
total_cost = 0.0
turn_count = 0
async for message in query(task, options=options):
if message.type == "text":
final_response = message.content
elif message.type == "tool_use":
turn_count += 1
print(f" Turn {turn_count}: {message.tool_name}({summarize(message.input)})")
elif message.type == "result":
total_cost = message.total_cost_usd
print(f"\nCompleted in {turn_count} turns | Cost: ${total_cost:.4f}")
return final_response
asyncio.run(run_autonomous_agent(
"Find all API endpoints in this project that don't have input validation, and add Pydantic models for request bodies."
))
Permission Modes
The SDK offers three permission modes that control how tool calls are authorized:
Auto Mode
options = ClaudeAgentOptions(
permission_mode="auto", # All tools auto-approved
)
Use for trusted environments (CI/CD pipelines, sandboxed containers). The agent runs without any human approval gates.
Interactive Mode
options = ClaudeAgentOptions(
permission_mode="interactive", # Prompt user for approval
)
Each tool call pauses execution and asks the user to approve or reject. Useful for development and learning.
Policy-Based Mode
options = ClaudeAgentOptions(
permission_mode="policy",
permission_policy={
"Read": "auto", # Always allow reads
"Glob": "auto", # Always allow file search
"Grep": "auto", # Always allow content search
"Write": "prompt", # Ask before writing
"Edit": "prompt", # Ask before editing
"Bash": "deny", # Never allow shell commands
}
)
This is the recommended mode for production. It applies the principle of least privilege -- read operations are always safe, write operations require approval, and dangerous operations are blocked.
Session Persistence
Autonomous agents often need to work across multiple interactions. The SDK supports session persistence so an agent can pick up where it left off.
# Start a persistent session
options = ClaudeAgentOptions(
session_id="project-refactor-2026-01",
persist_session=True,
session_storage_path="/tmp/agent-sessions/",
)
# First interaction
async for msg in query("Analyze the codebase and create a refactoring plan.", options=options):
handle_message(msg)
# Later interaction -- same session, agent remembers context
async for msg in query("Now implement step 1 of the plan you created.", options=options):
handle_message(msg)
Building a File Migration Agent
Here is a complete example of an autonomous agent that migrates JavaScript files to TypeScript:
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
JS_TO_TS_PROMPT = """You are a JavaScript-to-TypeScript migration agent.
Your task: Convert JavaScript files to TypeScript in the target directory.
For each .js file:
1. Read the file contents
2. Analyze the code to infer types
3. Add TypeScript type annotations
4. Rename the file from .js to .ts
5. Run the TypeScript compiler to check for errors
6. Fix any compiler errors
Rules:
- Prefer explicit types over 'any'
- Use interfaces for object shapes
- Add return types to all functions
- Use strict TypeScript config
- Preserve all existing functionality"""
async def migrate_to_typescript(directory: str):
options = ClaudeAgentOptions(
model="claude-sonnet-4-5-20250514",
system_prompt=JS_TO_TS_PROMPT,
allowed_tools=["Read", "Write", "Edit", "Bash", "Glob", "Grep"],
max_turns=100, # Large codebases need many turns
permission_mode="auto",
)
results = []
async for message in query(f"Migrate all .js files in {directory} to TypeScript.", options=options):
if message.type == "text":
results.append(message.content)
elif message.type == "tool_use":
print(f" [{message.tool_name}] {summarize(message.input)}")
return results[-1] if results else "No output produced."
asyncio.run(migrate_to_typescript("./src"))
Error Recovery Strategies
Autonomous agents will encounter errors. The quality of your error recovery determines whether the agent gracefully handles problems or spirals into failure loops.
Built-in Recovery
The SDK automatically feeds tool execution errors back to Claude. If a Bash command fails, Claude sees the error output and can adjust its approach. This handles most cases.
Custom Recovery
For domain-specific errors, add recovery instructions to your system prompt:
system_prompt = """...
Error recovery procedures:
- If a test fails, read the test file and the failing assertion to understand why
- If a file does not exist, search for similar filenames with Glob
- If a command times out, try breaking it into smaller operations
- If you encounter a permission error, report it and move to the next file
- Never retry the same failing command more than 3 times"""
Circuit Breakers
For production agents, implement circuit breakers that stop execution if the agent enters a failure loop:
class CircuitBreaker:
def __init__(self, max_consecutive_failures: int = 3):
self.consecutive_failures = 0
self.max_failures = max_consecutive_failures
def record_success(self):
self.consecutive_failures = 0
def record_failure(self):
self.consecutive_failures += 1
if self.consecutive_failures >= self.max_failures:
raise RuntimeError(
f"Circuit breaker tripped: {self.max_failures} consecutive failures"
)
Cost Control
Autonomous agents can be expensive if they run unchecked. The SDK provides built-in cost tracking:
options = ClaudeAgentOptions(
max_cost_usd=5.00, # Hard stop at $5
max_turns=50, # Hard stop at 50 turns
)
async for message in query(task, options=options):
if message.type == "result":
print(f"Total cost: ${message.total_cost_usd:.4f}")
print(f"Turns used: {message.turns_used}")
print(f"Tokens: {message.total_input_tokens} in / {message.total_output_tokens} out")
When to Use Autonomous Agents
Use autonomous agents when:
- The task requires multiple steps that depend on intermediate results
- Human intervention at each step would be impractical
- The agent has a clear success criteria it can verify (e.g., tests pass)
- The environment is sandboxed so mistakes are recoverable
Avoid autonomous agents when:
- The task requires real-world irreversible actions (sending money, deleting production data)
- There is no way for the agent to verify its own work
- The cost of a mistake exceeds the value of automation
- A simple API call or script would suffice
NYC News
Expert insights on AI voice agents and customer communication automation.
Try CallSphere AI Voice Agents
See how AI voice agents work for your industry. Live demo available -- no signup required.