Skip to content

Claude Agents API: Building & Deploying Agents

Overview

The Claude Agents API is the production-ready way to build and deploy agents powered by Claude.


Creating Agents with SDK

Basic Agent

from anthropic import Anthropic

class ClaudeAgent:
    """Build agents with Claude SDK"""

    def __init__(self, model: str = "claude-3-5-sonnet-20241022"):
        self.client = Anthropic()
        self.model = model
        self.tools = []

    def add_tool(self, name: str, description: str, input_schema: dict):
        """Register a tool"""

        self.tools.append({
            "name": name,
            "description": description,
            "input_schema": input_schema
        })

    def run(self, task: str):
        """Execute agent loop"""

        messages = [
            {"role": "user", "content": task}
        ]

        while True:
            # Get Claude's response
            response = self.client.messages.create(
                model=self.model,
                max_tokens=4096,
                tools=self.tools,
                messages=messages
            )

            # Check if Claude wants to use tools
            if response.stop_reason == "tool_use":
                # Process tool calls
                tool_results = self.process_tool_calls(response.content)

                # Add Claude's response + tool results
                messages.append({
                    "role": "assistant",
                    "content": response.content
                })
                messages.append({
                    "role": "user",
                    "content": tool_results
                })
            else:
                # Claude is done
                return self.extract_text(response.content)

    def process_tool_calls(self, content):
        """Execute tools Claude requested"""

        results = []

        for block in content:
            if block.type == "tool_use":
                # Call tool
                result = self.execute_tool(
                    block.name,
                    block.input
                )

                results.append({
                    "type": "tool_result",
                    "tool_use_id": block.id,
                    "content": result
                })

        return results

Deployment Options

REST API Endpoint

from fastapi import FastAPI

class DeployedAgent:
    """Deploy agent as API"""

    def __init__(self):
        self.app = FastAPI()
        self.agent = ClaudeAgent()

        @self.app.post("/agent/run")
        async def run_agent(request):
            """Agent endpoint"""

            try:
                result = self.agent.run(request.task)
                return {
                    "status": "success",
                    "result": result
                }
            except Exception as e:
                return {
                    "status": "error",
                    "error": str(e)
                }

    def start(self):
        """Run API server"""
        import uvicorn
        uvicorn.run(self.app, host="0.0.0.0", port=8000)

State Management

Maintaining Context

class StatefulAgent:
    """Agent with persistent state"""

    def __init__(self):
        self.client = Anthropic()
        self.conversation_history = []
        self.user_context = {}

    def add_context(self, user_id: str, context: dict):
        """Add user-specific context"""

        self.user_context[user_id] = context

    def run_with_context(self, user_id: str, task: str):
        """Execute with saved context"""

        # Build system message with context
        context = self.user_context.get(user_id, {})
        system_prompt = self.build_system_prompt(context)

        # Add to conversation
        messages = [
            *self.conversation_history,
            {"role": "user", "content": task}
        ]

        # Get response
        response = self.client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=2048,
            system=system_prompt,
            messages=messages
        )

        # Save to history
        self.conversation_history.append({
            "role": "assistant",
            "content": response.content[0].text
        })

        return response.content[0].text

Monitoring & Cost Optimization

Track Usage

class MonitoredAgent:
    """Agent with monitoring"""

    def __init__(self):
        self.client = Anthropic()
        self.usage_log = []

    def run_with_monitoring(self, task: str):
        """Execute with usage tracking"""

        response = self.client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=1000,
            messages=[{"role": "user", "content": task}]
        )

        # Log usage
        self.usage_log.append({
            'task': task,
            'input_tokens': response.usage.input_tokens,
            'output_tokens': response.usage.output_tokens,
            'cost': self.calculate_cost(response.usage)
        })

        return response.content[0].text

    def calculate_cost(self, usage):
        """Estimate API cost"""

        # Claude 3.5 Sonnet pricing (2024)
        input_cost = usage.input_tokens * 0.003 / 1000
        output_cost = usage.output_tokens * 0.015 / 1000

        return input_cost + output_cost

3 Warnings ⚠️

Warning 1: Unbounded Token Usage

# ❌ WRONG
# No token limits
response = client.messages.create(
    model="claude-3-5-sonnet",
    messages=messages
)
# Costs can spiral

# ✅ RIGHT
# Set max tokens
response = client.messages.create(
    model="claude-3-5-sonnet",
    max_tokens=1000,  # Bounded!
    messages=messages
)

Warning 2: No Error Handling

# ❌ WRONG
result = agent.run(task)  # Might fail

# ✅ RIGHT
try:
    result = agent.run(task)
except RateLimitError:
    retry_with_backoff()
except APIError as e:
    log_and_alert(e)

Warning 3: Forgotten Context Cleanup

# ❌ WRONG
# Conversation history grows forever
while True:
    response = agent.run(task)
    # Memory usage grows unbounded

# ✅ RIGHT
# Truncate old messages
if len(self.conversation_history) > 20:
    # Keep last 20, drop oldest
    self.conversation_history = self.conversation_history[-20:]

Last Updated: August 9, 2026