or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

agent-definitions.mdagents.mdclient.mdconfiguration-options.mdcontent-blocks.mdcore-query-interface.mdcustom-tools.mderror-handling.mderrors.mdhook-system.mdhooks.mdindex.mdmcp-config.mdmcp-server-configuration.mdmessages-and-content.mdmessages.mdoptions.mdpermission-control.mdpermissions.mdquery.mdtransport.md
COMPLETION_SUMMARY.md

index.mddocs/

0

# Claude Agent SDK

1

2

Python SDK for Claude Code enabling developers to build AI agents with tool usage, hooks, permission control, and bidirectional conversations. Provides both simple query-based interactions and advanced streaming client capabilities for complex use cases.

3

4

## Package Information

5

6

- **Package Name**: claude-agent-sdk

7

- **Package Type**: pypi

8

- **Language**: Python

9

- **Installation**: `pip install claude-agent-sdk`

10

- **Python Version**: 3.10+

11

- **Dependencies**: anyio>=4.0.0, typing_extensions>=4.0.0 (Python <3.11), mcp>=0.1.0

12

13

## Core Imports

14

15

```python

16

from claude_agent_sdk import query, ClaudeSDKClient, ClaudeAgentOptions

17

```

18

19

All public exports are available from the main package namespace:

20

21

```python

22

from claude_agent_sdk import (

23

# Main functions

24

query,

25

__version__,

26

27

# Client

28

ClaudeSDKClient,

29

Transport,

30

31

# Configuration

32

ClaudeAgentOptions,

33

34

# Message types

35

UserMessage,

36

AssistantMessage,

37

SystemMessage,

38

ResultMessage,

39

StreamEvent,

40

Message,

41

42

# Content blocks

43

TextBlock,

44

ThinkingBlock,

45

ToolUseBlock,

46

ToolResultBlock,

47

ContentBlock,

48

49

# MCP server support

50

create_sdk_mcp_server,

51

tool,

52

SdkMcpTool,

53

McpServerConfig,

54

McpSdkServerConfig,

55

56

# Hook system

57

HookCallback,

58

HookContext,

59

HookInput,

60

HookJSONOutput,

61

HookMatcher,

62

63

# Permission system

64

PermissionMode,

65

CanUseTool,

66

ToolPermissionContext,

67

PermissionResult,

68

PermissionResultAllow,

69

PermissionResultDeny,

70

PermissionUpdate,

71

72

# Agent system

73

AgentDefinition,

74

SettingSource,

75

76

# Plugin support

77

SdkPluginConfig,

78

79

# Error types

80

ClaudeSDKError,

81

CLIConnectionError,

82

CLINotFoundError,

83

ProcessError,

84

CLIJSONDecodeError,

85

)

86

```

87

88

## Basic Usage

89

90

### Simple Query

91

92

The `query()` function provides the simplest way to interact with Claude:

93

94

```python

95

import anyio

96

from claude_agent_sdk import query, AssistantMessage, TextBlock

97

98

async def main():

99

# Simple question

100

async for message in query(prompt="What is 2 + 2?"):

101

if isinstance(message, AssistantMessage):

102

for block in message.content:

103

if isinstance(block, TextBlock):

104

print(block.text)

105

106

anyio.run(main)

107

```

108

109

### Query with Tools

110

111

Enable Claude to use file operations and shell commands:

112

113

```python

114

from claude_agent_sdk import query, ClaudeAgentOptions

115

116

async def main():

117

options = ClaudeAgentOptions(

118

allowed_tools=["Read", "Write", "Bash"],

119

permission_mode="acceptEdits", # Auto-accept file edits

120

cwd="/path/to/project"

121

)

122

123

async for message in query(

124

prompt="Create a hello.py file that prints Hello World",

125

options=options

126

):

127

print(message)

128

129

anyio.run(main)

130

```

131

132

### Interactive Client

133

134

For bidirectional conversations with state:

135

136

```python

137

from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions

138

139

async def main():

140

options = ClaudeAgentOptions(

141

allowed_tools=["Read", "Write"],

142

permission_mode="acceptEdits"

143

)

144

145

async with ClaudeSDKClient(options=options) as client:

146

# First query

147

await client.query("Create a todo.txt file")

148

async for msg in client.receive_response():

149

print(msg)

150

151

# Follow-up query in same session

152

await client.query("Add 'Buy groceries' to the file")

153

async for msg in client.receive_response():

154

print(msg)

155

156

anyio.run(main)

157

```

158

159

## Architecture

160

161

The SDK provides two interaction patterns:

162

163

1. **`query()` Function**: Stateless, one-shot interactions. Best for simple queries, batch processing, or when you don't need conversation context.

164

165

2. **`ClaudeSDKClient` Class**: Stateful, bidirectional streaming. Supports custom tools (via in-process MCP servers), hooks for intercepting operations, and multi-turn conversations with session management.

166

167

**Key Components**:

168

- **Messages**: Structured communication with `UserMessage`, `AssistantMessage`, `SystemMessage`, `ResultMessage`, `StreamEvent`

169

- **Content Blocks**: Message content as `TextBlock`, `ThinkingBlock`, `ToolUseBlock`, `ToolResultBlock`

170

- **Configuration**: Comprehensive options via `ClaudeAgentOptions` dataclass

171

- **MCP Servers**: In-process tool execution without subprocess overhead

172

- **Hooks**: Intercept and control operations at PreToolUse, PostToolUse, UserPromptSubmit, Stop, SubagentStop, PreCompact

173

- **Permissions**: Runtime control via modes, callbacks, and hooks

174

175

**Bundled CLI**: Claude Code CLI is automatically included—no separate installation needed. The SDK manages the CLI lifecycle transparently.

176

177

## Capabilities

178

179

### Core Query Interface

180

181

The `query()` function for simple, stateless interactions and `ClaudeSDKClient` for bidirectional streaming with state management.

182

183

```python { .api }

184

async def query(

185

*,

186

prompt: str | AsyncIterable[dict[str, Any]],

187

options: ClaudeAgentOptions | None = None,

188

transport: Transport | None = None,

189

) -> AsyncIterator[Message]:

190

"""

191

One-shot or unidirectional streaming query to Claude.

192

193

Args:

194

prompt: User message string or async iterable of message dicts

195

options: Configuration options (default: ClaudeAgentOptions())

196

transport: Custom transport implementation (default: subprocess CLI)

197

198

Returns:

199

AsyncIterator yielding Message objects

200

"""

201

```

202

203

```python { .api }

204

class ClaudeSDKClient:

205

"""Bidirectional streaming client for interactive conversations."""

206

207

def __init__(

208

self,

209

options: ClaudeAgentOptions | None = None,

210

transport: Transport | None = None,

211

):

212

"""

213

Initialize client.

214

215

Args:

216

options: Configuration options

217

transport: Custom transport implementation

218

"""

219

220

async def connect(

221

self, prompt: str | AsyncIterable[dict[str, Any]] | None = None

222

) -> None:

223

"""Establish connection and optionally send initial prompt."""

224

225

async def query(

226

self, prompt: str | AsyncIterable[dict[str, Any]], session_id: str = "default"

227

) -> None:

228

"""Send a message to Claude."""

229

230

async def receive_messages(self) -> AsyncIterator[Message]:

231

"""Receive all messages until connection closes."""

232

233

async def receive_response(self) -> AsyncIterator[Message]:

234

"""Receive messages until ResultMessage is received."""

235

236

async def interrupt(self) -> None:

237

"""Send interrupt signal to stop current operation."""

238

239

async def set_permission_mode(self, mode: str) -> None:

240

"""Change permission mode during conversation."""

241

242

async def set_model(self, model: str | None = None) -> None:

243

"""Switch AI model during conversation."""

244

245

async def get_server_info(self) -> dict[str, Any] | None:

246

"""Get server capabilities and information."""

247

248

async def disconnect(self) -> None:

249

"""Close connection and clean up resources."""

250

```

251

252

[Core Query Interface](./core-query-interface.md)

253

254

### Messages and Content

255

256

Message types for communication between user and Claude, and content blocks that compose messages.

257

258

```python { .api }

259

@dataclass

260

class UserMessage:

261

"""Message from user to Claude."""

262

content: str | list[ContentBlock]

263

parent_tool_use_id: str | None = None

264

265

@dataclass

266

class AssistantMessage:

267

"""Message from Claude to user."""

268

content: list[ContentBlock]

269

model: str

270

parent_tool_use_id: str | None = None

271

272

@dataclass

273

class SystemMessage:

274

"""System-level message."""

275

subtype: str

276

data: dict[str, Any]

277

278

@dataclass

279

class ResultMessage:

280

"""Final result of conversation turn."""

281

subtype: str

282

duration_ms: int

283

duration_api_ms: int

284

is_error: bool

285

num_turns: int

286

session_id: str

287

total_cost_usd: float | None = None

288

usage: dict[str, Any] | None = None

289

result: str | None = None

290

structured_output: Any = None

291

292

@dataclass

293

class StreamEvent:

294

"""Raw stream event from Anthropic API."""

295

uuid: str

296

session_id: str

297

event: dict[str, Any]

298

parent_tool_use_id: str | None = None

299

300

Message = UserMessage | AssistantMessage | SystemMessage | ResultMessage | StreamEvent

301

```

302

303

```python { .api }

304

@dataclass

305

class TextBlock:

306

"""Plain text content."""

307

text: str

308

309

@dataclass

310

class ThinkingBlock:

311

"""Extended thinking content."""

312

thinking: str

313

signature: str

314

315

@dataclass

316

class ToolUseBlock:

317

"""Tool invocation request."""

318

id: str

319

name: str

320

input: dict[str, Any]

321

322

@dataclass

323

class ToolResultBlock:

324

"""Tool execution result."""

325

tool_use_id: str

326

content: str | list[dict[str, Any]] | None = None

327

is_error: bool | None = None

328

329

ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock

330

```

331

332

[Messages and Content](./messages-and-content.md)

333

334

### Configuration Options

335

336

Comprehensive configuration via `ClaudeAgentOptions` dataclass covering tools, prompts, permissions, budgets, models, and more.

337

338

```python { .api }

339

@dataclass

340

class ClaudeAgentOptions:

341

"""Configuration options for Claude SDK."""

342

343

# Tool configuration

344

allowed_tools: list[str] = field(default_factory=list)

345

disallowed_tools: list[str] = field(default_factory=list)

346

347

# Prompt configuration

348

system_prompt: str | SystemPromptPreset | None = None

349

350

# MCP server configuration

351

mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)

352

353

# Permission configuration

354

permission_mode: PermissionMode | None = None

355

permission_prompt_tool_name: str | None = None

356

can_use_tool: CanUseTool | None = None

357

358

# Session configuration

359

continue_conversation: bool = False

360

resume: str | None = None

361

fork_session: bool = False

362

363

# Budget and limits

364

max_turns: int | None = None

365

max_budget_usd: float | None = None

366

max_thinking_tokens: int | None = None

367

368

# Model configuration

369

model: str | None = None

370

fallback_model: str | None = None

371

372

# Working directory and CLI

373

cwd: str | Path | None = None

374

cli_path: str | Path | None = None

375

add_dirs: list[str | Path] = field(default_factory=list)

376

377

# Settings and sources

378

settings: str | None = None

379

setting_sources: list[SettingSource] | None = None

380

381

# Environment

382

env: dict[str, str] = field(default_factory=dict)

383

extra_args: dict[str, str | None] = field(default_factory=dict)

384

385

# Callbacks

386

stderr: Callable[[str], None] | None = None

387

debug_stderr: Any = sys.stderr # Deprecated: Use stderr callback instead

388

389

# Hooks and plugins

390

hooks: dict[HookEvent, list[HookMatcher]] | None = None

391

agents: dict[str, AgentDefinition] | None = None

392

plugins: list[SdkPluginConfig] = field(default_factory=list)

393

394

# Advanced features

395

include_partial_messages: bool = False

396

output_format: dict[str, Any] | None = None

397

max_buffer_size: int | None = None

398

user: str | None = None

399

```

400

401

[Configuration Options](./configuration-options.md)

402

403

### Custom Tools (In-Process MCP Servers)

404

405

Define custom tools as Python functions that Claude can invoke, running in the same process without subprocess overhead.

406

407

```python { .api }

408

def tool(

409

name: str,

410

description: str,

411

input_schema: type | dict[str, Any]

412

) -> Callable[[Callable[[Any], Awaitable[dict[str, Any]]]], SdkMcpTool[Any]]:

413

"""

414

Decorator for creating custom tools.

415

416

Args:

417

name: Tool name

418

description: Tool description for Claude

419

input_schema: Input schema as type or dict

420

421

Returns:

422

Decorator that wraps handler function

423

"""

424

425

def create_sdk_mcp_server(

426

name: str,

427

version: str = "1.0.0",

428

tools: list[SdkMcpTool[Any]] | None = None

429

) -> McpSdkServerConfig:

430

"""

431

Create an in-process MCP server with custom tools.

432

433

Args:

434

name: Server name

435

version: Server version

436

tools: List of tool definitions

437

438

Returns:

439

Server configuration for use in ClaudeAgentOptions.mcp_servers

440

"""

441

442

@dataclass

443

class SdkMcpTool(Generic[T]):

444

"""Custom tool definition."""

445

name: str

446

description: str

447

input_schema: type[T] | dict[str, Any]

448

handler: Callable[[T], Awaitable[dict[str, Any]]]

449

```

450

451

[Custom Tools (MCP Servers)](./custom-tools.md)

452

453

### Hook System

454

455

Intercept and control Claude's operations at specific points in the agent loop with PreToolUse, PostToolUse, UserPromptSubmit, Stop, SubagentStop, and PreCompact hooks.

456

457

```python { .api }

458

HookEvent = Literal[

459

"PreToolUse",

460

"PostToolUse",

461

"UserPromptSubmit",

462

"Stop",

463

"SubagentStop",

464

"PreCompact"

465

]

466

467

@dataclass

468

class HookMatcher:

469

"""Hook configuration with pattern matching."""

470

matcher: str | None = None # Tool name pattern (e.g., "Bash", "Write|Edit")

471

hooks: list[HookCallback] = field(default_factory=list)

472

473

HookCallback = Callable[

474

[HookInput, str | None, HookContext],

475

Awaitable[HookJSONOutput],

476

]

477

478

class HookContext(TypedDict):

479

"""Context provided to hooks."""

480

signal: Any | None

481

```

482

483

[Hook System](./hook-system.md)

484

485

### Permission Control

486

487

Runtime permission control via modes, programmatic callbacks, and permission updates.

488

489

```python { .api }

490

PermissionMode = Literal["default", "acceptEdits", "plan", "bypassPermissions"]

491

492

CanUseTool = Callable[

493

[str, dict[str, Any], ToolPermissionContext],

494

Awaitable[PermissionResult]

495

]

496

497

@dataclass

498

class ToolPermissionContext:

499

"""Context for permission callbacks."""

500

signal: Any | None = None

501

suggestions: list[PermissionUpdate] = field(default_factory=list)

502

503

@dataclass

504

class PermissionResultAllow:

505

"""Allow permission decision."""

506

behavior: Literal["allow"] = "allow"

507

updated_input: dict[str, Any] | None = None

508

updated_permissions: list[PermissionUpdate] | None = None

509

510

@dataclass

511

class PermissionResultDeny:

512

"""Deny permission decision."""

513

behavior: Literal["deny"] = "deny"

514

message: str = ""

515

interrupt: bool = False

516

517

PermissionResult = PermissionResultAllow | PermissionResultDeny

518

519

@dataclass

520

class PermissionUpdate:

521

"""Permission configuration update."""

522

type: Literal[

523

"addRules", "replaceRules", "removeRules",

524

"setMode", "addDirectories", "removeDirectories"

525

]

526

rules: list[PermissionRuleValue] | None = None

527

behavior: PermissionBehavior | None = None

528

mode: PermissionMode | None = None

529

directories: list[str] | None = None

530

destination: PermissionUpdateDestination | None = None

531

532

def to_dict(self) -> dict[str, Any]:

533

"""Convert to dictionary for CLI."""

534

```

535

536

[Permission Control](./permission-control.md)

537

538

### Agent Definitions

539

540

Define custom agents with specific tools, prompts, and models for specialized tasks.

541

542

```python { .api }

543

@dataclass

544

class AgentDefinition:

545

"""Custom agent configuration."""

546

description: str

547

prompt: str

548

tools: list[str] | None = None

549

model: Literal["sonnet", "opus", "haiku", "inherit"] | None = None

550

551

SettingSource = Literal["user", "project", "local"]

552

```

553

554

[Agent Definitions](./agent-definitions.md)

555

556

### MCP Server Configuration

557

558

Configure external MCP servers via stdio, SSE, or HTTP transports, in addition to in-process SDK servers.

559

560

```python { .api }

561

class McpStdioServerConfig(TypedDict):

562

"""Subprocess MCP server via stdio."""

563

type: NotRequired[Literal["stdio"]]

564

command: str

565

args: NotRequired[list[str]]

566

env: NotRequired[dict[str, str]]

567

568

class McpSSEServerConfig(TypedDict):

569

"""MCP server via Server-Sent Events."""

570

type: Literal["sse"]

571

url: str

572

headers: NotRequired[dict[str, str]]

573

574

class McpHttpServerConfig(TypedDict):

575

"""MCP server via HTTP."""

576

type: Literal["http"]

577

url: str

578

headers: NotRequired[dict[str, str]]

579

580

class McpSdkServerConfig(TypedDict):

581

"""In-process SDK MCP server."""

582

type: Literal["sdk"]

583

name: str

584

instance: McpServer

585

586

McpServerConfig = (

587

McpStdioServerConfig | McpSSEServerConfig |

588

McpHttpServerConfig | McpSdkServerConfig

589

)

590

```

591

592

[MCP Server Configuration](./mcp-server-configuration.md)

593

594

### Error Handling

595

596

Exception types for handling SDK errors including connection issues, process failures, and parsing errors.

597

598

```python { .api }

599

class ClaudeSDKError(Exception):

600

"""Base exception for all Claude SDK errors."""

601

602

class CLIConnectionError(ClaudeSDKError):

603

"""Raised when unable to connect to Claude Code."""

604

605

class CLINotFoundError(CLIConnectionError):

606

"""Raised when Claude Code is not found or not installed."""

607

608

def __init__(

609

self,

610

message: str = "Claude Code not found",

611

cli_path: str | None = None

612

):

613

...

614

615

cli_path: str | None

616

617

class ProcessError(ClaudeSDKError):

618

"""Raised when the CLI process fails."""

619

620

def __init__(

621

self,

622

message: str,

623

exit_code: int | None = None,

624

stderr: str | None = None

625

):

626

...

627

628

exit_code: int | None

629

stderr: str | None

630

631

class CLIJSONDecodeError(ClaudeSDKError):

632

"""Raised when unable to decode JSON from CLI output."""

633

634

def __init__(self, line: str, original_error: Exception):

635

...

636

637

line: str

638

original_error: Exception

639

```

640

641

[Error Handling](./error-handling.md)

642

643

### Version Information

644

645

```python { .api }

646

__version__: str # Current SDK version (e.g., "0.1.8")

647

```

648

649

## System Prompt Configuration

650

651

Configure Claude's system prompt using presets or custom text:

652

653

```python { .api }

654

class SystemPromptPreset(TypedDict):

655

"""System prompt preset configuration."""

656

type: Literal["preset"]

657

preset: Literal["claude_code"]

658

append: NotRequired[str]

659

```

660

661

**Usage**:

662

663

```python

664

# Use Claude Code's default system prompt

665

options = ClaudeAgentOptions(

666

system_prompt={"type": "preset", "preset": "claude_code"}

667

)

668

669

# Append additional instructions

670

options = ClaudeAgentOptions(

671

system_prompt={

672

"type": "preset",

673

"preset": "claude_code",

674

"append": "Always explain your reasoning step by step."

675

}

676

)

677

678

# Use custom system prompt

679

options = ClaudeAgentOptions(

680

system_prompt="You are a helpful Python expert specializing in async programming."

681

)

682

```

683

684

## Plugin Support

685

686

Load external plugins to extend SDK functionality:

687

688

```python { .api }

689

class SdkPluginConfig(TypedDict):

690

"""Plugin configuration."""

691

type: Literal["local"]

692

path: str

693

```

694

695

**Usage**:

696

697

```python

698

options = ClaudeAgentOptions(

699

plugins=[

700

{"type": "local", "path": "/path/to/plugin"}

701

]

702

)

703

```

704