Agent SDK Quickstart

Build a file-processing agent that reads a directory, summarizes each file, and produces a report.

Install

Python:

pip install claude-agent-sdk

TypeScript:

npm install @anthropic-ai/claude-agent-sdk

Build a File Summarizer (Python)

import asyncio
from claude_agent_sdk import query

async def main():
    prompt = """
    Read all .py files in the current directory.
    For each file, write a one-line summary of what it does.
    Then create a file called SUMMARY.md with a table:
    | File | Purpose |
    |------|---------|
    | ... | ... |
    """

    async for message in query(
        prompt=prompt,
        options={
            "model": "claude-sonnet-4-6",
            "permissionMode": "default",
        }
    ):
        if message.type == "text":
            print(message.text, end="")
        elif message.type == "tool_use":
            print(f"\n[Tool: {message.tool}({message.input})]")

asyncio.run(main())

Run it:

python summarizer.py

Claude will use Glob to find .py files, Read to examine each one, and Write to create SUMMARY.md. You’ll see each tool call as it happens.

Build It in TypeScript

import { query } from "@anthropic-ai/claude-agent-sdk";

const prompt = `
Read all .ts files in the src/ directory.
For each file, write a one-line summary.
Create SUMMARY.md with a table of files and their purposes.
`;

for await (const message of query({
  prompt,
  options: {
    model: "claude-sonnet-4-6",
    permissionMode: "default",
  },
})) {
  if (message.type === "text") {
    process.stdout.write(message.text);
  } else if (message.type === "tool_use") {
    console.log(`\n[Tool: ${message.tool}]`);
  }
}

Add Custom Tools via MCP

Extend the agent with your own tools using in-process MCP servers:

from claude_agent_sdk import query, create_sdk_mcp_server

server = create_sdk_mcp_server("my-tools")

@server.tool
def count_lines(file_path: str) -> int:
    """Count the number of lines in a file."""
    with open(file_path) as f:
        return len(f.readlines())

@server.tool
def check_complexity(file_path: str) -> str:
    """Check if a file is too complex (more than 200 lines)."""
    with open(file_path) as f:
        lines = len(f.readlines())
    if lines > 200:
        return f"WARNING: {file_path} has {lines} lines - consider splitting"
    return f"OK: {file_path} has {lines} lines"

async def main():
    async for msg in query(
        prompt="Analyze all Python files. Flag any that are too complex.",
        options={
            "model": "claude-sonnet-4-6",
            "mcpServers": [server],
        },
    ):
        if msg.type == "text":
            print(msg.text, end="")

asyncio.run(main())

Connect to External MCP Servers

async for msg in query(
    prompt="List all open issues assigned to me",
    options={
        "mcpServers": [
            {
                "type": "stdio",
                "command": "npx",
                "args": ["-y", "@anthropic-ai/mcp-server-github"],
                "env": {"GITHUB_TOKEN": os.environ["GITHUB_TOKEN"]},
            }
        ],
    },
):
    print(msg)

Observe the Agent Loop

The message stream shows you exactly what Claude is doing:

[Tool: Glob(pattern=**/*.py)]
[Tool: Read(file_path=src/main.py)]
Found 3 Python files. Let me read each one...
[Tool: Read(file_path=src/utils.py)]
[Tool: Read(file_path=src/config.py)]
[Tool: Write(file_path=SUMMARY.md)]

Created SUMMARY.md with summaries of all 3 files.

Each tool_use message shows the tool name and input. Each text message shows Claude’s reasoning. This transparency makes debugging straightforward.

Next