Agent SDK and programmatic usage
Use the Claude Code Agent SDK for programmatic agent creation: API reference, TypeScript integration, and advanced patterns.
What is the Claude Agent SDK?
The Claude Agent SDK is an official Anthropic development kit that lets you create programmatic agents directly in your TypeScript or Python code. Unlike Claude Code's native sub-agents (which live in the terminal), SDK agents integrate into your applications, scripts, and pipelines.
The remote control vs home automation analogy
Claude Code's native sub-agents are like a remote control: you press a button and the agent executes a predefined action. The Claude Agent SDK is full home automation: you program complex scenarios that trigger automatically based on conditions, with total control over every step.
Why use the SDK instead of native sub-agents?
| Criterion | Native sub-agents | Agent SDK |
|---|---|---|
| Environment | Claude Code terminal | Your application (server, script, CI) |
| Language | Markdown prompts | TypeScript or Python |
| Control | Delegated to the model | Full programmatic control |
| Integration | Claude Code tools (Bash, Read, Edit...) | Custom tools you define |
| Triggering | Manual via the terminal | Automatic (webhook, cron, event) |
| Persistence | Session duration | Your choice (database, file...) |
| Scalability | One session at a time | Multiple agents in parallel |
In short: native sub-agents are perfect for interactive work in the terminal, the SDK is built for automation and integration into your systems.
Installation
TypeScript
# Install the TypeScript SDKnpm install @anthropic-ai/claude-code-sdk# Prerequisite: Claude Code must be installed globallynpm install -g @anthropic-ai/claude-code
The TypeScript SDK uses Claude Code under the hood. Make sure Claude Code is installed and authenticated.
Python
# Install the Python SDKpip install claude-code-sdk# Prerequisite: Claude Code accessible in the PATHnpm install -g @anthropic-ai/claude-code
The Python SDK works the same way: it orchestrates Claude Code via a child process.
First agent in TypeScript
Here's a minimal agent that analyzes a file and produces a report.
import { claude } from "@anthropic-ai/claude-code-sdk";async function analyzeFile(filePath: string): Promise<string> {// Launch an agent with a prompt and optionsconst result = await claude({prompt: `Analyze the file ${filePath} and produce a reportwith: line count, exported functions,estimated cyclomatic complexity, and suggestions.`,options: {maxTurns: 10,allowedTools: ["Read", "Bash", "Grep"],},});// The result contains the response textreturn result.text;}// Usageconst report = await analyzeFile("src/lib/utils.ts");console.log(report);
maxTurns controls the depth
The maxTurns parameter limits the number of agent iterations. A simple review agent needs 5 to 10 turns. A complex refactoring agent may need 20 to 30. Start low and increase if the agent stops too early.
First agent in Python
The same agent in Python, with similar syntax.
import asynciofrom claude_code_sdk import claude, ClaudeOptionsasync def analyze_file(file_path: str) -> str:"""Analyze a file and produce a structured report."""result = await claude(prompt=f"Analyze the file {file_path} and produce a report "f"with: line count, exported functions, "f"estimated cyclomatic complexity, and suggestions.",options=ClaudeOptions(max_turns=10,allowed_tools=["Read", "Bash", "Grep"],),)return result.text# Usagereport = asyncio.run(analyze_file("src/lib/utils.ts"))print(report)
Integrating external tools
The real power of the SDK lies in the ability to add your own tools. The agent can call functions from your codebase, APIs, databases, anything you can code.
import { claude, Tool } from "@anthropic-ai/claude-code-sdk";// Define a custom toolconst slackNotifier: Tool = {name: "notify_slack",description: "Send a notification to a Slack channel",parameters: {type: "object",properties: {channel: { type: "string", description: "The Slack channel" },message: { type: "string", description: "The message to send" },},required: ["channel", "message"],},// The tool implementationasync execute({ channel, message }) {const response = await fetch(SLACK_WEBHOOK_URL, {method: "POST",headers: { "Content-Type": "application/json" },body: JSON.stringify({ channel, text: message }),});return { success: response.ok };},};// Use the agent with the custom toolconst result = await claude({prompt: "Check that all tests pass. If a test fails, "+ "notify the #dev channel on Slack with the error details.",options: {maxTurns: 15,allowedTools: ["Bash", "Read"],customTools: [slackNotifier],},});
Practical examples
1. Automated monitoring
An agent that runs on a cron and monitors your application's health.
import { claude } from "@anthropic-ai/claude-code-sdk";async function healthCheck() {const result = await claude({prompt: `You are a monitoring agent. Check:1. That the server responds on http://localhost:3000/health2. That the database is accessible3. That disk space is sufficient (> 20% free)4. That recent logs don't contain critical errorsProduce a JSON report with the status of each check.If a problem is detected, use notify_slack to alert.`,options: {maxTurns: 10,allowedTools: ["Bash"],customTools: [slackNotifier],},});return JSON.parse(result.text);}// Run every 5 minutes via a cron or scheduler
2. Deployment pipeline
An agent that orchestrates a full deployment.
import asynciofrom claude_code_sdk import claude, ClaudeOptionsasync def deploy_pipeline(version: str) -> dict:"""4-step deployment pipeline."""# Step 1: Pre-deployment checkspre_check = await claude(prompt=f"Verify that the main branch is clean, "f"that all tests pass, and that the build "f"for version {version} is OK.",options=ClaudeOptions(max_turns=10,allowed_tools=["Bash", "Read"],),)if "FAILURE" in pre_check.text:return {"status": "blocked", "reason": pre_check.text}# Step 2: Build and tagbuild = await claude(prompt=f"Create the v{version} tag, build the Docker image "f"and push it to the registry.",options=ClaudeOptions(max_turns=15,allowed_tools=["Bash"],),)# Step 3: Deploymentdeploy = await claude(prompt="Deploy the new image to the staging environment. ""Verify that the health check passes.",options=ClaudeOptions(max_turns=10,allowed_tools=["Bash"],),)return {"status": "success","version": version,"pre_check": pre_check.text,"build": build.text,"deploy": deploy.text,}
3. Automated bug triage
An agent that reads new GitHub issues and categorizes them automatically.
import { claude, Tool } from "@anthropic-ai/claude-code-sdk";const githubTool: Tool = {name: "github_api",description: "Interact with the GitHub API",parameters: {type: "object",properties: {action: { type: "string", enum: ["list_issues", "add_labels", "add_comment"] },repo: { type: "string" },issueNumber: { type: "number" },labels: { type: "array", items: { type: "string" } },comment: { type: "string" },},required: ["action", "repo"],},async execute(params) {// Implementation with the GitHub API (Octokit, gh CLI, etc.)// ...return { success: true };},};async function triageNewIssues() {const result = await claude({prompt: `You are a bug triage agent. For each new untriagedissue in the "my-org/my-app" repo:1. Read the title and description2. Categorize: bug, feature-request, question, documentation3. Estimate priority: P0 (critical), P1 (high), P2 (medium), P3 (low)4. Add the appropriate labels5. If it's a P0, add a comment to alert the teamProcess all issues created in the last 24 hours.`,options: {maxTurns: 30,customTools: [githubTool],},});return result.text;}
SDK configuration options
The main options for controlling agent behavior:
| Option | Type | Description |
|---|---|---|
prompt | string | The agent's mission |
maxTurns | number | Maximum number of iterations (default: 10) |
allowedTools | string[] | Authorized Claude Code tools |
customTools | Tool[] | Your custom tools |
cwd | string | The agent's working directory |
model | string | Model to use (sonnet, opus, haiku) |
outputFormat | string | Output format (text, json, stream-json) |
systemPrompt | string | Additional system instructions |
// Example with all optionsconst result = await claude({prompt: "Refactor the auth module to use JWT tokens",options: {maxTurns: 25,allowedTools: ["Read", "Edit", "Bash", "Grep", "Glob"],cwd: "/home/user/my-project",model: "sonnet",outputFormat: "json",systemPrompt: "You are a security expert. "+ "Always prioritize security over performance.",},});
Detailed comparison with native sub-agents
When to choose what?
Use native sub-agents for interactive day-to-day development: review, debug, refactoring while you code. Use the SDK when you need automation without human intervention: CI/CD, monitoring, triage, nightly pipelines.
Native sub-agents: strengths
- Simple configuration (Markdown file)
- Full access to Claude Code tools
- Natural integration into the terminal workflow
- No code to write or maintain
- Ideal for exploration and prototyping
Agent SDK: strengths
- Full programmatic control (conditions, loops, errors)
- Integration into your existing applications and pipelines
- Unlimited custom tools (APIs, databases, services)
- Automatic execution (cron, webhooks, events)
- Fine-grained error handling and retries
- Built-in logging and observability
Best practices
1. Limit each agent's scope
An agent should have a clear and bounded mission. If the task is too broad, split it into multiple coordinated agents.
// BAD: one agent that does everythingconst result = await claude({prompt: "Refactor the project, write the tests, do the review, "+ "update the docs, and deploy to production",});// GOOD: specialized and coordinated agentsconst refactorResult = await claude({prompt: "Refactor the auth module according to the provided plan",options: { maxTurns: 20 },});const testResult = await claude({prompt: "Write tests for the refactored auth module",options: { maxTurns: 15 },});
2. Handle errors explicitly
try {const result = await claude({prompt: "Run the database migrations",options: { maxTurns: 10 },});if (result.text.includes("ERROR")) {// Rollback or notificationawait notifyTeam("Migration failed", result.text);}} catch (error) {// Timeout, network error, etc.console.error("Agent SDK error:", error);await notifyTeam("Agent unavailable", String(error));}
3. Use JSON format for structured results
const result = await claude({prompt: "Analyze the project's dependencies and produce a report "+ "in JSON format with: total, outdated, vulnerable, suggestions.",options: {maxTurns: 10,outputFormat: "json",},});const report = JSON.parse(result.text);console.log(`${report.vulnerable} vulnerabilities found`);
Next steps
Now that you know the Claude Agent SDK, explore related topics.
- Agent performance and limits: Costs, recursion depth, and production best practices
- Multi-agent orchestration: Patterns for combining multiple agents
- Headless mode and CI/CD: Integrate Claude Code into your pipelines