Skip to main content
This guide shows you how to build an agent using Anthropic’s Claude models with the Claude Agent SDK, which provides tool use capabilities out of the box.

Prerequisites

  • Python 3.9+
  • cycls package installed
  • Anthropic API key
  • Docker installed (for local testing)
pip install cycls

Basic Claude Agent

Create a file called app.py:
import cycls

@cycls.app(pip=["anthropic"], copy=[".env"])
async def app(context):
    from anthropic import AsyncAnthropic

    client = AsyncAnthropic()

    async with client.messages.stream(
        model="claude-sonnet-4-20250514",
        max_tokens=1024,
        messages=context.messages
    ) as stream:
        async for text in stream.text_stream:
            yield text

app.local()
Create a .env file:
ANTHROPIC_API_KEY=sk-ant-...
Run the agent:
python app.py

Claude Agent SDK with Tools

For more advanced use cases, you can use the Claude Agent SDK which provides built-in tool support:
import cycls

@cycls.app(pip=["claude-agent-sdk"], copy=[".env"])
async def app(context):
    from claude_agent_sdk import (
        ClaudeSDKClient,
        ClaudeAgentOptions,
        AssistantMessage,
        TextBlock,
        ToolUseBlock,
        ThinkingBlock,
        ResultMessage,
    )

    async with ClaudeSDKClient(
        options=ClaudeAgentOptions(
            allowed_tools=["Read", "Edit", "Glob", "Grep", "Bash", "WebSearch"],
            permission_mode="acceptEdits",
        )
    ) as client:
        await client.query(context.last_message)

        async for message in client.receive_response():
            if isinstance(message, AssistantMessage):
                for block in message.content:
                    if isinstance(block, TextBlock):
                        yield block.text
                    elif isinstance(block, ThinkingBlock):
                        yield {"type": "thinking", "thinking": block.thinking}
                    elif isinstance(block, ToolUseBlock):
                        yield {"type": "thinking", "thinking": f"Using tool: {block.name}"}

            elif isinstance(message, ResultMessage):
                yield {"type": "thinking", "thinking": "Tool completed"}

app.local()
This example:
  • Uses the Claude Agent SDK for tool-based interactions
  • Streams text responses directly to the user
  • Shows thinking blocks for reasoning visibility
  • Displays tool usage as thinking bubbles

Configuration

Create a .env file with your API key:
ANTHROPIC_API_KEY=sk-ant-...

Deploy to Cloud

import cycls
import os

cycls.api_key = os.getenv("CYCLS_API_KEY")

@cycls.app(pip=["anthropic"], copy=[".env"])
async def app(context):
    from anthropic import AsyncAnthropic

    client = AsyncAnthropic()

    async with client.messages.stream(
        model="claude-sonnet-4-20250514",
        max_tokens=1024,
        messages=context.messages
    ) as stream:
        async for text in stream.text_stream:
            yield text

app.deploy()