By Sagar Shankaran, Founder of CallSphere
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.
Key takeaways
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.
At its core, the Claude Agent SDK runs a loop:
flowchart LR
USER(["User message"])
LOOP{"messages.create<br/>agent loop"}
THINK["Extended thinking<br/>optional"]
TOOL{"stop_reason<br/>tool_use?"}
EXEC["Execute tool<br/>append tool_result"]
DONE(["stop_reason<br/>end_turn"])
USER --> LOOP --> THINK --> TOOL
TOOL -->|Yes| EXEC --> LOOP
TOOL -->|No| DONE
style LOOP fill:#4f46e5,stroke:#4338ca,color:#fff
style THINK fill:#ede9fe,stroke:#7c3aed,color:#1e1b4b
style DONE fill:#059669,stroke:#047857,color:#fff
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.
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."
))
The SDK offers three permission modes that control how tool calls are authorized:
Hear it before you finish reading
Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.
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.
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.
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.
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)
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"))
Autonomous agents will encounter errors. The quality of your error recovery determines whether the agent gracefully handles problems or spirals into failure loops.
Still reading? Stop comparing — try CallSphere live.
CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.
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.
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"""
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"
)
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")
Use autonomous agents when:
Avoid autonomous agents when:

Written by
Sagar Shankaran· Founder, CallSphere
LinkedInSagar Shankaran is the founder of CallSphere, where he builds production AI voice and chat agents deployed across healthcare, hospitality, real estate, and home services. He writes about agentic AI, LLM engineering, and shipping voice agents that handle real calls in production.
See how AI voice agents work for your industry. Live demo available -- no signup required.
May 2026's biggest agent-architecture shift: planning, tool selection, and self-correction move inside the model. Framework code shrinks. Here is what changes.
A three-way comparison of Gemini Enterprise, Anthropic managed agents and OpenAI Frontier Platform after Cloud Next 2026 — strengths, gaps, buyer fit.
Anthropic's May 2026 push positions Claude as a vertical platform for financial services. The strategic positioning versus OpenAI and Google.
A clean before/after of agent architecture in 2026. The control loop moved from your framework code into the model's reasoning chain. What that looks like.
ServiceNow Project Arc vs Anthropic Managed Agents — runtime, governance, integration, and use cases. The 2026 enterprise autonomous agent comparison.
Anthropic and Moody's announced a data partnership in May 2026 that grounds Claude in audited financial reference data. Why grounding reduces hallucination and what it unlocks.
© 2026 CallSphere Inc. All rights reserved.
Made within San Francisco
Watch how CallSphere handles real customer calls, schedules appointments, and processes payments — live.
Try Live DemoBook a DemoCalculate Your ROI