Skip to content

Claude Agent SDK Beginner Guide: Build a Read-Only Python Agent

For / Key Points

For: Python developers delegating file investigation and tool use to Claude

Key Points:

  • The current Python package is claude-agent-sdk, imported as claude_agent_sdk
  • Use query() for one run and ClaudeSDKClient for multi-turn sessions and custom tools
  • Begin with Read, Grep, and Glob, then add mutation rights deliberately

Claude Agent SDK embeds the agent loop, file tools, permissions, and sessions derived from Claude Code into an application. The Python package supports Python 3.10+ and bundles the required Claude Code CLI, so a separate CLI installation is not mandatory.1

Older examples using anthropic-agent-sdk, AgentSDK, or agent.run() do not match the current Python API.

1. Create an environment

python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade claude-agent-sdk anyio

On Windows PowerShell, activate it with:

.venv\Scripts\Activate.ps1

For direct Claude API authentication, provide ANTHROPIC_API_KEY from secret management. Do not place the key in source code, committed .env files, or logs.

2. Run a minimal query

query() returns an asynchronous message stream.

import anyio
from claude_agent_sdk import ResultMessage, query


async def main() -> None:
    async for message in query(prompt="What is 2 + 2?"):
        if isinstance(message, ResultMessage):
            print(message.result)


anyio.run(main)

The stream includes initialization, assistant output, tool events, and the final result. The last ResultMessage exposes the result, usage, cost, and session ID.1

3. Expand to read-only code investigation

Do not grant shell or write access in the first practical run.

import anyio
from claude_agent_sdk import ClaudeAgentOptions, ResultMessage, query


async def main() -> None:
    options = ClaudeAgentOptions(
        allowed_tools=["Read", "Grep", "Glob"],
        max_turns=6,
    )

    prompt = """
    Investigate authentication in this project.
    Using implementation files, configuration, and tests as evidence,
    summarize the path from login to session establishment.
    Do not modify files.
    """

    async for message in query(prompt=prompt, options=options):
        if isinstance(message, ResultMessage):
            if message.is_error:
                raise RuntimeError(message.result or "Agent run failed")
            print(message.result)
            print(f"cost_usd={message.total_cost_usd}")


anyio.run(main)

allowed_tools narrows the available toolset. If you add writing or shell tools, availability and automatic approval remain separate concerns controlled by permission_mode or can_use_tool.2

Choose query() or ClaudeSDKClient

APIStateBest fit
query()Per invocationOne investigation or independent batch item
ClaudeSDKClientMulti-turn while openConversational UI, steering, custom tools, continued sessions

Use query() when a run behaves like a function. Use ClaudeSDKClient for follow-up input in the same context, mid-run interaction, or in-process SDK MCP tools.2

Custom tool design

Define a Python function with @tool and expose it through create_sdk_mcp_server as an in-process MCP server.

  • Separate read and write operations
  • Use typed target IDs and actions rather than one free-text input
  • Require application approval for sends, deletion, and publishing
  • Log input, outcome, and failure
  • Do not convert a tool exception into a success message

The SDK supplies the loop; the application still owns external authorization and side effects.

Production checklist

Limit the working directory

Built-in tools act on the process filesystem. Use a dedicated worktree, container, or temporary directory rather than a broad home directory.

Set limits

Bound turns, timeout, API budget, and concurrency. Store ResultMessage usage and total_cost_usd, including failed runs.

Validate outputs

Do not feed final prose directly into a mutation step. Apply JSON Schema, row reconciliation, static analysis, or tests appropriate to the deliverable.

Separate secrets

Keep API keys out of prompts and files. Inject narrow credentials only inside the tool that needs them, and redact authorization headers and personal data from logs.

Common errors

No matching distribution found

Check Python and the package name.

python --version
python -m pip install --upgrade claude-agent-sdk

Old imports fail

Use from claude_agent_sdk import .... The migration from the former Claude Code SDK includes breaking class and message changes; consult the current README.1

A tool waits for approval

An allowlist and approval mode are separate. Keep the toolset small and implement can_use_tool or hooks before removing write confirmations.

Summary

  • Install claude-agent-sdk and import from claude_agent_sdk
  • Use query() for one run and ClaudeSDKClient for continued interaction or custom tools
  • Start with Read, Grep, and Glob; approve Bash and writes separately
  • Bound filesystem scope, turns, cost, and side effects in the application

Few lines of code are a useful on-ramp, not a safety property. A minimal agent also needs narrow tools, validated results, and a reliable stop path.