Referensi Agent SDK - Python
Referensi API lengkap untuk Python Agent SDK, termasuk semua fungsi, tipe, dan kelas.
Instalasi
pip install claude-agent-sdk
Memilih antara query() dan ClaudeSDKClient
Python SDK menyediakan dua cara untuk berinteraksi dengan Claude Code:
Perbandingan cepat
| Fitur | query() |
ClaudeSDKClient |
|---|---|---|
| Sesi | Membuat sesi baru setiap kali | Menggunakan kembali sesi yang sama |
| Percakapan | Pertukaran tunggal | Beberapa pertukaran dalam konteks yang sama |
| Koneksi | Dikelola secara otomatis | Kontrol manual |
| Streaming Input | ✅ Didukung | ✅ Didukung |
| Interrupts | ❌ Tidak didukung | ✅ Didukung |
| Hooks | ✅ Didukung | ✅ Didukung |
| Custom Tools | ✅ Didukung | ✅ Didukung |
| Continue Chat | ❌ Sesi baru setiap kali | ✅ Mempertahankan percakapan |
| Use Case | Tugas sekali jalan | Percakapan berkelanjutan |
Kapan menggunakan query() (sesi baru setiap kali)
Terbaik untuk:
- Pertanyaan sekali jalan di mana Anda tidak memerlukan riwayat percakapan
- Tugas independen yang tidak memerlukan konteks dari pertukaran sebelumnya
- Skrip otomasi sederhana
- Ketika Anda menginginkan awal yang segar setiap kali
Kapan menggunakan ClaudeSDKClient (percakapan berkelanjutan)
Terbaik untuk:
- Melanjutkan percakapan - Ketika Anda memerlukan Claude untuk mengingat konteks
- Pertanyaan lanjutan - Membangun berdasarkan respons sebelumnya
- Aplikasi interaktif - Antarmuka obrolan, REPL
- Logika berbasis respons - Ketika tindakan berikutnya bergantung pada respons Claude
- Kontrol sesi - Mengelola siklus hidup percakapan secara eksplisit
Fungsi
query()
Membuat sesi baru untuk setiap interaksi dengan Claude Code. Mengembalikan async iterator yang menghasilkan pesan saat tiba. Setiap panggilan ke query() dimulai segar tanpa memori interaksi sebelumnya.
async def query(
*,
prompt: str | AsyncIterable[dict[str, Any]],
options: ClaudeAgentOptions | None = None,
transport: Transport | None = None
) -> AsyncIterator[Message]
Parameter
| Parameter | Tipe | Deskripsi |
|---|---|---|
prompt |
str | AsyncIterable[dict] |
Prompt input sebagai string atau async iterable untuk mode streaming |
options |
ClaudeAgentOptions | None |
Objek konfigurasi opsional (default ke ClaudeAgentOptions() jika None) |
transport |
Transport | None |
Transport kustom opsional untuk berkomunikasi dengan proses CLI |
Pengembalian
Mengembalikan AsyncIterator[Message] yang menghasilkan pesan dari percakapan.
Contoh - Dengan opsi
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
async def main():
options = ClaudeAgentOptions(
system_prompt="You are an expert Python developer",
permission_mode="acceptEdits",
cwd="/home/user/project",
)
async for message in query(prompt="Create a Python web server", options=options):
print(message)
asyncio.run(main())
tool()
Dekorator untuk mendefinisikan tools MCP dengan keamanan tipe.
def tool(
name: str,
description: str,
input_schema: type | dict[str, Any],
annotations: ToolAnnotations | None = None
) -> Callable[[Callable[[Any], Awaitable[dict[str, Any]]]], SdkMcpTool[Any]]
Parameter
| Parameter | Tipe | Deskripsi |
|---|---|---|
name |
str |
Pengenal unik untuk tool |
description |
str |
Deskripsi yang dapat dibaca manusia tentang apa yang dilakukan tool |
input_schema |
type | dict[str, Any] |
Skema yang mendefinisikan parameter input tool (lihat di bawah) |
annotations |
ToolAnnotations | None |
Anotasi tool MCP opsional yang memberikan petunjuk perilaku kepada klien |
Opsi skema input
-
Pemetaan tipe sederhana (direkomendasikan):
{"text": str, "count": int, "enabled": bool} -
Format JSON Schema (untuk validasi kompleks):
{ "type": "object", "properties": { "text": {"type": "string"}, "count": {"type": "integer", "minimum": 0}, }, "required": ["text"], }
Pengembalian
Fungsi dekorator yang membungkus implementasi tool dan mengembalikan instance SdkMcpTool.
Contoh
from claude_agent_sdk import tool
from typing import Any
@tool("greet", "Greet a user", {"name": str})
async def greet(args: dict[str, Any]) -> dict[str, Any]:
return {"content": [{"type": "text", "text": f"Hello, {args['name']}!"}]}
ToolAnnotations
Diimpor ulang dari mcp.types (juga tersedia sebagai from claude_agent_sdk import ToolAnnotations). Semua field adalah petunjuk opsional; klien tidak boleh mengandalkannya untuk keputusan keamanan.
| Field | Tipe | Default | Deskripsi |
|---|---|---|---|
title |
str | None |
None |
Judul yang dapat dibaca manusia untuk tool |
readOnlyHint |
bool | None |
False |
Jika True, tool tidak memodifikasi lingkungannya |
destructiveHint |
bool | None |
True |
Jika True, tool dapat melakukan pembaruan destruktif (hanya bermakna ketika readOnlyHint adalah False) |
idempotentHint |
bool | None |
False |
Jika True, panggilan berulang dengan argumen yang sama tidak memiliki efek tambahan (hanya bermakna ketika readOnlyHint adalah False) |
openWorldHint |
bool | None |
True |
Jika True, tool berinteraksi dengan entitas eksternal (misalnya, pencarian web). Jika False, domain tool ditutup (misalnya, tool memori) |
from claude_agent_sdk import tool, ToolAnnotations
from typing import Any
@tool(
"search",
"Search the web",
{"query": str},
annotations=ToolAnnotations(readOnlyHint=True, openWorldHint=True),
)
async def search(args: dict[str, Any]) -> dict[str, Any]:
return {"content": [{"type": "text", "text": f"Results for: {args['query']}"}]}
create_sdk_mcp_server()
Buat server MCP dalam proses yang berjalan dalam aplikasi Python Anda.
def create_sdk_mcp_server(
name: str,
version: str = "1.0.0",
tools: list[SdkMcpTool[Any]] | None = None
) -> McpSdkServerConfig
Parameter
| Parameter | Tipe | Default | Deskripsi |
|---|---|---|---|
name |
str |
- | Pengenal unik untuk server |
version |
str |
"1.0.0" |
String versi server |
tools |
list[SdkMcpTool[Any]] | None |
None |
Daftar fungsi tool yang dibuat dengan dekorator @tool |
Pengembalian
Mengembalikan objek McpSdkServerConfig yang dapat diteruskan ke ClaudeAgentOptions.mcp_servers.
Contoh
from claude_agent_sdk import tool, create_sdk_mcp_server
@tool("add", "Add two numbers", {"a": float, "b": float})
async def add(args):
return {"content": [{"type": "text", "text": f"Sum: {args['a'] + args['b']}"}]}
@tool("multiply", "Multiply two numbers", {"a": float, "b": float})
async def multiply(args):
return {"content": [{"type": "text", "text": f"Product: {args['a'] * args['b']}"}]}
calculator = create_sdk_mcp_server(
name="calculator",
version="2.0.0",
tools=[add, multiply], # Pass decorated functions
)
# Use with Claude
options = ClaudeAgentOptions(
mcp_servers={"calc": calculator},
allowed_tools=["mcp__calc__add", "mcp__calc__multiply"],
)
list_sessions()
Mencantumkan sesi masa lalu dengan metadata. Filter berdasarkan direktori proyek atau cantumkan sesi di semua proyek. Sinkron; mengembalikan segera.
def list_sessions(
directory: str | None = None,
limit: int | None = None,
include_worktrees: bool = True
) -> list[SDKSessionInfo]
Parameter
| Parameter | Tipe | Default | Deskripsi |
|---|---|---|---|
directory |
str | None |
None |
Direktori untuk mencantumkan sesi. Ketika dihilangkan, mengembalikan sesi di semua proyek |
limit |
int | None |
None |
Jumlah maksimal sesi yang akan dikembalikan |
include_worktrees |
bool |
True |
Ketika directory berada di dalam repositori git, sertakan sesi dari semua jalur worktree |
Tipe pengembalian: SDKSessionInfo
| Properti | Tipe | Deskripsi |
|---|---|---|
session_id |
str |
Pengenal sesi unik |
summary |
str |
Judul tampilan: judul kustom, ringkasan yang dihasilkan otomatis, atau prompt pertama |
last_modified |
int |
Waktu modifikasi terakhir dalam milidetik sejak epoch |
file_size |
int | None |
Ukuran file sesi dalam byte (None untuk backend penyimpanan jarak jauh) |
custom_title |
str | None |
Judul sesi yang ditetapkan pengguna |
first_prompt |
str | None |
Prompt pengguna bermakna pertama dalam sesi |
git_branch |
str | None |
Cabang Git di akhir sesi |
cwd |
str | None |
Direktori kerja untuk sesi |
tag |
str | None |
Tag sesi yang ditetapkan pengguna (lihat tag_session()) |
created_at |
int | None |
Waktu pembuatan sesi dalam milidetik sejak epoch |
Contoh
Cetak 10 sesi terbaru untuk proyek. Hasil diurutkan berdasarkan last_modified menurun, jadi item pertama adalah yang terbaru. Hilangkan directory untuk mencari di semua proyek.
from claude_agent_sdk import list_sessions
for session in list_sessions(directory="/path/to/project", limit=10):
print(f"{session.summary} ({session.session_id})")
get_session_messages()
Mengambil pesan dari sesi masa lalu. Sinkron; mengembalikan segera.
def get_session_messages(
session_id: str,
directory: str | None = None,
limit: int | None = None,
offset: int = 0
) -> list[SessionMessage]
Parameter
| Parameter | Tipe | Default | Deskripsi |
|---|---|---|---|
session_id |
str |
diperlukan | ID sesi untuk mengambil pesan |
directory |
str | None |
None |
Direktori proyek untuk dilihat. Ketika dihilangkan, mencari di semua proyek |
limit |
int | None |
None |
Jumlah maksimal pesan yang akan dikembalikan |
offset |
int |
0 |
Jumlah pesan yang akan dilewati dari awal |
Tipe pengembalian: SessionMessage
| Properti | Tipe | Deskripsi |
|---|---|---|
type |
Literal["user", "assistant"] |
Peran pesan |
uuid |
str |
Pengenal pesan unik |
session_id |
str |
Pengenal sesi |
message |
Any |
Konten pesan mentah |
parent_tool_use_id |
None |
Dicadangkan untuk penggunaan di masa depan |
Contoh
from claude_agent_sdk import list_sessions, get_session_messages
sessions = list_sessions(limit=1)
if sessions:
messages = get_session_messages(sessions[0].session_id)
for msg in messages:
print(f"[{msg.type}] {msg.uuid}")
get_session_info()
Membaca metadata untuk sesi tunggal berdasarkan ID tanpa memindai direktori proyek lengkap. Sinkron; mengembalikan segera.
def get_session_info(
session_id: str,
directory: str | None = None,
) -> SDKSessionInfo | None
Parameter
| Parameter | Tipe | Default | Deskripsi |
|---|---|---|---|
session_id |
str |
diperlukan | UUID sesi untuk dicari |
directory |
str | None |
None |
Jalur direktori proyek. Ketika dihilangkan, mencari di semua direktori proyek |
Mengembalikan SDKSessionInfo, atau None jika sesi tidak ditemukan.
Contoh
Cari metadata sesi tunggal tanpa memindai direktori proyek. Berguna ketika Anda sudah memiliki ID sesi dari run sebelumnya.
from claude_agent_sdk import get_session_info
info = get_session_info("550e8400-e29b-41d4-a716-446655440000")
if info:
print(f"{info.summary} (branch: {info.git_branch}, tag: {info.tag})")
rename_session()
Mengganti nama sesi dengan menambahkan entri judul kustom. Panggilan berulang aman; judul terbaru menang. Sinkron.
def rename_session(
session_id: str,
title: str,
directory: str | None = None,
) -> None
Parameter
| Parameter | Tipe | Default | Deskripsi |
|---|---|---|---|
session_id |
str |
diperlukan | UUID sesi untuk diganti nama |
title |
str |
diperlukan | Judul baru. Harus tidak kosong setelah menghapus spasi putih |
directory |
str | None |
None |
Jalur direktori proyek. Ketika dihilangkan, mencari di semua direktori proyek |
Menimbulkan ValueError jika session_id bukan UUID yang valid atau title kosong; FileNotFoundError jika sesi tidak dapat ditemukan.
Contoh
Ganti nama sesi terbaru sehingga lebih mudah ditemukan nanti. Judul baru muncul di SDKSessionInfo.custom_title pada pembacaan berikutnya.
from claude_agent_sdk import list_sessions, rename_session
sessions = list_sessions(directory="/path/to/project", limit=1)
if sessions:
rename_session(sessions[0].session_id, "Refactor auth module")
tag_session()
Menandai sesi. Teruskan None untuk menghapus tag. Panggilan berulang aman; tag terbaru menang. Sinkron.
def tag_session(
session_id: str,
tag: str | None,
directory: str | None = None,
) -> None
Parameter
| Parameter | Tipe | Default | Deskripsi |
|---|---|---|---|
session_id |
str |
diperlukan | UUID sesi untuk ditandai |
tag |
str | None |
diperlukan | String tag, atau None untuk menghapus. Disanitasi Unicode sebelum disimpan |
directory |
str | None |
None |
Jalur direktori proyek. Ketika dihilangkan, mencari di semua direktori proyek |
Menimbulkan ValueError jika session_id bukan UUID yang valid atau tag kosong setelah sanitasi; FileNotFoundError jika sesi tidak dapat ditemukan.
Contoh
Tandai sesi, kemudian filter berdasarkan tag itu pada pembacaan nanti. Teruskan None untuk menghapus tag yang ada.
from claude_agent_sdk import list_sessions, tag_session
# Tag a session
tag_session("550e8400-e29b-41d4-a716-446655440000", "needs-review")
# Later: find all sessions with that tag
for session in list_sessions(directory="/path/to/project"):
if session.tag == "needs-review":
print(session.summary)
Kelas
ClaudeSDKClient
Mempertahankan sesi percakapan di beberapa pertukaran. Ini adalah setara Python dari cara fungsi query() SDK TypeScript bekerja secara internal - ia membuat objek klien yang dapat melanjutkan percakapan.
Fitur Utama
- Kontinuitas sesi: Mempertahankan konteks percakapan di beberapa panggilan
query() - Percakapan yang sama: Sesi mempertahankan pesan sebelumnya
- Dukungan interrupt: Dapat menghentikan eksekusi di tengah-tengah tugas
- Siklus hidup eksplisit: Anda mengontrol kapan sesi dimulai dan berakhir
- Alur berbasis respons: Dapat bereaksi terhadap respons dan mengirim tindak lanjut
- Tools dan hooks kustom: Mendukung tools kustom (dibuat dengan dekorator
@tool) dan hooks
class ClaudeSDKClient:
def __init__(self, options: ClaudeAgentOptions | None = None, transport: Transport | None = None)
async def connect(self, prompt: str | AsyncIterable[dict] | None = None) -> None
async def query(self, prompt: str | AsyncIterable[dict], session_id: str = "default") -> None
async def receive_messages(self) -> AsyncIterator[Message]
async def receive_response(self) -> AsyncIterator[Message]
async def interrupt(self) -> None
async def set_permission_mode(self, mode: str) -> None
async def set_model(self, model: str | None = None) -> None
async def rewind_files(self, user_message_id: str) -> None
async def get_mcp_status(self) -> McpStatusResponse
async def reconnect_mcp_server(self, server_name: str) -> None
async def toggle_mcp_server(self, server_name: str, enabled: bool) -> None
async def stop_task(self, task_id: str) -> None
async def get_server_info(self) -> dict[str, Any] | None
async def disconnect(self) -> None
Metode
| Metode | Deskripsi |
|---|---|
__init__(options) |
Inisialisasi klien dengan konfigurasi opsional |
connect(prompt) |
Hubungkan ke Claude dengan prompt awal opsional atau aliran pesan |
query(prompt, session_id) |
Kirim permintaan baru dalam mode streaming |
receive_messages() |
Terima semua pesan dari Claude sebagai async iterator |
receive_response() |
Terima pesan hingga dan termasuk ResultMessage |
interrupt() |
Kirim sinyal interrupt (hanya bekerja dalam mode streaming) |
set_permission_mode(mode) |
Ubah mode izin untuk sesi saat ini |
set_model(model) |
Ubah model untuk sesi saat ini. Teruskan None untuk reset ke default |
rewind_files(user_message_id) |
Pulihkan file ke keadaan mereka pada pesan pengguna yang ditentukan. Memerlukan enable_file_checkpointing=True. Lihat File checkpointing |
get_mcp_status() |
Dapatkan status semua server MCP yang dikonfigurasi. Mengembalikan McpStatusResponse |
reconnect_mcp_server(server_name) |
Coba lagi menghubungkan ke server MCP yang gagal atau terputus |
toggle_mcp_server(server_name, enabled) |
Aktifkan atau nonaktifkan server MCP di tengah sesi. Menonaktifkan menghapus toolnya |
stop_task(task_id) |
Hentikan tugas latar belakang yang sedang berjalan. TaskNotificationMessage dengan status "stopped" mengikuti dalam aliran pesan |
get_server_info() |
Dapatkan informasi server termasuk ID sesi dan kemampuan |
disconnect() |
Putuskan sambungan dari Claude |
Dukungan Context Manager
Klien dapat digunakan sebagai async context manager untuk manajemen koneksi otomatis:
async with ClaudeSDKClient() as client:
await client.query("Hello Claude")
async for message in client.receive_response():
print(message)
Penting: Saat mengulangi pesan, hindari menggunakan
breakuntuk keluar lebih awal karena ini dapat menyebabkan masalah pembersihan asyncio. Sebaliknya, biarkan iterasi selesai secara alami atau gunakan flag untuk melacak kapan Anda menemukan apa yang Anda butuhkan.
Contoh - Melanjutkan percakapan
import asyncio
from claude_agent_sdk import ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage
async def main():
async with ClaudeSDKClient() as client:
# First question
await client.query("What's the capital of France?")
# Process response
async for message in client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Claude: {block.text}")
# Follow-up question - the session retains the previous context
await client.query("What's the population of that city?")
async for message in client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Claude: {block.text}")
# Another follow-up - still in the same conversation
await client.query("What are some famous landmarks there?")
async for message in client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Claude: {block.text}")
asyncio.run(main())
Contoh - Streaming input dengan ClaudeSDKClient
import asyncio
from claude_agent_sdk import ClaudeSDKClient
async def message_stream():
"""Generate messages dynamically."""
yield {
"type": "user",
"message": {"role": "user", "content": "Analyze the following data:"},
}
await asyncio.sleep(0.5)
yield {
"type": "user",
"message": {"role": "user", "content": "Temperature: 25°C, Humidity: 60%"},
}
await asyncio.sleep(0.5)
yield {
"type": "user",
"message": {"role": "user", "content": "What patterns do you see?"},
}
async def main():
async with ClaudeSDKClient() as client:
# Stream input to Claude
await client.query(message_stream())
# Process response
async for message in client.receive_response():
print(message)
# Follow-up in same session
await client.query("Should we be concerned about these readings?")
async for message in client.receive_response():
print(message)
asyncio.run(main())
Contoh - Menggunakan interrupts
import asyncio
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, ResultMessage
async def interruptible_task():
options = ClaudeAgentOptions(allowed_tools=["Bash"], permission_mode="acceptEdits")
async with ClaudeSDKClient(options=options) as client:
# Start a long-running task
await client.query("Count from 1 to 100 slowly, using the bash sleep command")
# Let it run for a bit
await asyncio.sleep(2)
# Interrupt the task
await client.interrupt()
print("Task interrupted!")
# Drain the interrupted task's messages (including its ResultMessage)
async for message in client.receive_response():
if isinstance(message, ResultMessage):
print(f"Interrupted task finished with subtype={message.subtype!r}")
# subtype is "error_during_execution" for interrupted tasks
# Send a new command
await client.query("Just say hello instead")
# Now receive the new response
async for message in client.receive_response():
if isinstance(message, ResultMessage) and message.subtype == "success":
print(f"New result: {message.result}")
asyncio.run(interruptible_task())
Perilaku buffer setelah interrupt: interrupt() mengirim sinyal berhenti tetapi tidak menghapus buffer pesan. Pesan yang sudah diproduksi oleh tugas yang terputus, termasuk ResultMessage-nya (dengan subtype="error_during_execution"), tetap berada dalam aliran. Anda harus menguras mereka dengan receive_response() sebelum membaca respons ke query baru. Jika Anda mengirim query baru segera setelah interrupt() dan memanggil receive_response() hanya sekali, Anda akan menerima pesan tugas yang terputus, bukan respons query baru.
Contoh - Kontrol izin lanjutan
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
from claude_agent_sdk.types import (
PermissionResultAllow,
PermissionResultDeny,
ToolPermissionContext,
)
async def custom_permission_handler(
tool_name: str, input_data: dict, context: ToolPermissionContext
) -> PermissionResultAllow | PermissionResultDeny:
"""Custom logic for tool permissions."""
# Block writes to system directories
if tool_name == "Write" and input_data.get("file_path", "").startswith("/system/"):
return PermissionResultDeny(
message="System directory write not allowed", interrupt=True
)
# Redirect sensitive file operations
if tool_name in ["Write", "Edit"] and "config" in input_data.get("file_path", ""):
safe_path = f"./sandbox/{input_data['file_path']}"
return PermissionResultAllow(
updated_input={**input_data, "file_path": safe_path}
)
# Allow everything else
return PermissionResultAllow(updated_input=input_data)
async def main():
options = ClaudeAgentOptions(
can_use_tool=custom_permission_handler, allowed_tools=["Read", "Write", "Edit"]
)
async with ClaudeSDKClient(options=options) as client:
await client.query("Update the system config file")
async for message in client.receive_response():
# Will use sandbox path instead
print(message)
asyncio.run(main())
Tipe
@dataclass vs TypedDict: SDK ini menggunakan dua jenis tipe. Kelas yang didekorasi dengan @dataclass (seperti ResultMessage, AgentDefinition, TextBlock) adalah instance objek saat runtime dan mendukung akses atribut: msg.result. Kelas yang didefinisikan dengan TypedDict (seperti ThinkingConfigEnabled, McpStdioServerConfig, SyncHookJSONOutput) adalah dict biasa saat runtime dan memerlukan akses kunci: config["budget_tokens"], bukan config.budget_tokens. Sintaks panggilan ClassName(field=value) bekerja untuk keduanya, tetapi hanya dataclass yang menghasilkan objek dengan atribut.
SdkMcpTool
Definisi untuk tool SDK MCP yang dibuat dengan dekorator @tool.
@dataclass
class SdkMcpTool(Generic[T]):
name: str
description: str
input_schema: type[T] | dict[str, Any]
handler: Callable[[T], Awaitable[dict[str, Any]]]
annotations: ToolAnnotations | None = None
| Properti | Tipe | Deskripsi |
|---|---|---|
name |
str |
Pengenal unik untuk tool |
description |
str |
Deskripsi yang dapat dibaca manusia |
input_schema |
type[T] | dict[str, Any] |
Skema untuk validasi input |
handler |
Callable[[T], Awaitable[dict[str, Any]]] |
Fungsi async yang menangani eksekusi tool |
annotations |
ToolAnnotations | None |
Anotasi tool MCP opsional (misalnya, readOnlyHint, destructiveHint, openWorldHint). Dari mcp.types |
Transport
Kelas dasar abstrak untuk implementasi transport kustom. Gunakan ini untuk berkomunikasi dengan proses Claude melalui saluran kustom (misalnya, koneksi jarak jauh alih-alih subprocess lokal).
Ini adalah API internal tingkat rendah. Antarmuka dapat berubah di rilis mendatang. Implementasi kustom harus diperbarui agar sesuai dengan perubahan antarmuka apa pun.
from abc import ABC, abstractmethod
from collections.abc import AsyncIterator
from typing import Any
class Transport(ABC):
@abstractmethod
async def connect(self) -> None: ...
@abstractmethod
async def write(self, data: str) -> None: ...
@abstractmethod
def read_messages(self) -> AsyncIterator[dict[str, Any]]: ...
@abstractmethod
async def close(self) -> None: ...
@abstractmethod
def is_ready(self) -> bool: ...
@abstractmethod
async def end_input(self) -> None: ...
| Metode | Deskripsi |
|---|---|
connect() |
Hubungkan transport dan siapkan untuk komunikasi |
write(data) |
Tulis data mentah (JSON + newline) ke transport |
read_messages() |
Async iterator yang menghasilkan pesan JSON yang diuraikan |
close() |
Tutup koneksi dan bersihkan sumber daya |
is_ready() |
Mengembalikan True jika transport dapat mengirim dan menerima |
end_input() |
Tutup aliran input (misalnya, tutup stdin untuk transport subprocess) |
Impor: from claude_agent_sdk import Transport
ClaudeAgentOptions
Dataclass konfigurasi untuk query Claude Code.
@dataclass
class ClaudeAgentOptions:
tools: list[str] | ToolsPreset | None = None
allowed_tools: list[str] = field(default_factory=list)
system_prompt: str | SystemPromptPreset | None = None
mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)
permission_mode: PermissionMode | None = None
continue_conversation: bool = False
resume: str | None = None
max_turns: int | None = None
max_budget_usd: float | None = None
disallowed_tools: list[str] = field(default_factory=list)
model: str | None = None
fallback_model: str | None = None
betas: list[SdkBeta] = field(default_factory=list)
output_format: dict[str, Any] | None = None
permission_prompt_tool_name: str | None = None
cwd: str | Path | None = None
cli_path: str | Path | None = None
settings: str | None = None
add_dirs: list[str | Path] = field(default_factory=list)
env: dict[str, str] = field(default_factory=dict)
extra_args: dict[str, str | None] = field(default_factory=dict)
max_buffer_size: int | None = None
debug_stderr: Any = sys.stderr # Deprecated
stderr: Callable[[str], None] | None = None
can_use_tool: CanUseTool | None = None
hooks: dict[HookEvent, list[HookMatcher]] | None = None
user: str | None = None
include_partial_messages: bool = False
fork_session: bool = False
agents: dict[str, AgentDefinition] | None = None
setting_sources: list[SettingSource] | None = None
sandbox: SandboxSettings | None = None
plugins: list[SdkPluginConfig] = field(default_factory=list)
max_thinking_tokens: int | None = None # Deprecated: use thinking instead
thinking: ThinkingConfig | None = None
effort: Literal["low", "medium", "high", "max"] | None = None
enable_file_checkpointing: bool = False
session_store: SessionStore | None = None
session_store_flush: SessionStoreFlushMode = "batched"
| Properti | Tipe | Default | Deskripsi |
|---|---|---|---|
tools |
list[str] | ToolsPreset | None |
None |
Konfigurasi tools. Gunakan {"type": "preset", "preset": "claude_code"} untuk tools default Claude Code |
allowed_tools |
list[str] |
[] |
Tools untuk auto-approve tanpa prompt. Ini tidak membatasi Claude hanya pada tools ini; tools yang tidak terdaftar jatuh ke permission_mode dan can_use_tool. Gunakan disallowed_tools untuk memblokir tools. Lihat Permissions |
system_prompt |
str | SystemPromptPreset | None |
None |
Konfigurasi system prompt. Teruskan string untuk prompt kustom, atau gunakan {"type": "preset", "preset": "claude_code"} untuk system prompt Claude Code. Tambahkan "append" untuk memperluas preset |
mcp_servers |
dict[str, McpServerConfig] | str | Path |
{} |
Konfigurasi server MCP atau jalur ke file konfigurasi |
permission_mode |
PermissionMode | None |
None |
Mode izin untuk penggunaan tool |
continue_conversation |
bool |
False |
Lanjutkan percakapan terbaru |
resume |
str | None |
None |
ID sesi untuk dilanjutkan |
max_turns |
int | None |
None |
Jumlah maksimal putaran agentic (round trip penggunaan tool) |
max_budget_usd |
float | None |
None |
Hentikan query ketika estimasi biaya sisi klien mencapai nilai USD ini. Dibandingkan dengan estimasi yang sama seperti total_cost_usd; lihat Track cost and usage untuk peringatan akurasi |
disallowed_tools |
list[str] |
[] |
Tools untuk selalu ditolak. Aturan penolakan diperiksa terlebih dahulu dan mengganti allowed_tools dan permission_mode (termasuk bypassPermissions) |
enable_file_checkpointing |
bool |
False |
Aktifkan pelacakan perubahan file untuk rewinding. Lihat File checkpointing |
model |
str | None |
None |
Model Claude yang akan digunakan |
fallback_model |
str | None |
None |
Model fallback yang akan digunakan jika model utama gagal |
betas |
list[SdkBeta] |
[] |
Fitur beta untuk diaktifkan. Lihat SdkBeta untuk opsi yang tersedia |
output_format |
dict[str, Any] | None |
None |
Format output untuk respons terstruktur (misalnya, {"type": "json_schema", "schema": {...}}). Lihat Structured outputs untuk detail |
permission_prompt_tool_name |
str | None |
None |
Nama tool MCP untuk prompt izin |
cwd |
str | Path | None |
None |
Direktori kerja saat ini |
cli_path |
str | Path | None |
None |
Jalur kustom ke executable CLI Claude Code |
settings |
str | None |
None |
Jalur ke file pengaturan |
add_dirs |
list[str | Path] |
[] |
Direktori tambahan yang dapat diakses Claude |
env |
dict[str, str] |
{} |
Variabel lingkungan yang digabungkan di atas lingkungan proses yang diwarisi. Lihat Environment variables untuk variabel yang dibaca CLI yang mendasar |
extra_args |
dict[str, str | None] |
{} |
Argumen CLI tambahan untuk diteruskan langsung ke CLI |
max_buffer_size |
int | None |
None |
Byte maksimal saat membuffer stdout CLI |
debug_stderr |
Any |
sys.stderr |
Deprecated - Objek seperti file untuk output debug. Gunakan callback stderr sebagai gantinya |
stderr |
Callable[[str], None] | None |
None |
Fungsi callback untuk output stderr dari CLI |
can_use_tool |
CanUseTool | None |
None |
Fungsi callback izin tool. Lihat Permission types untuk detail |
hooks |
dict[HookEvent, list[HookMatcher]] | None |
None |
Konfigurasi hook untuk mengintersepsi event |
user |
str | None |
None |
Pengenal pengguna |
include_partial_messages |
bool |
False |
Sertakan event streaming pesan parsial. Ketika diaktifkan, pesan StreamEvent dihasilkan |
fork_session |
bool |
False |
Ketika melanjutkan dengan resume, fork ke ID sesi baru alih-alih melanjutkan sesi asli |
agents |
dict[str, AgentDefinition] | None |
None |
Subagent yang didefinisikan secara programatis |
plugins |
list[SdkPluginConfig] |
[] |
Muat plugin kustom dari jalur lokal. Lihat Plugins untuk detail |
sandbox |
SandboxSettings | None |
None |
Konfigurasi perilaku sandbox secara programatis. Lihat Sandbox settings untuk detail |
setting_sources |
list[SettingSource] | None |
None (CLI defaults: all sources) |
Kontrol pengaturan filesystem mana yang akan dimuat. Teruskan [] untuk menonaktifkan pengaturan pengguna, proyek, dan lokal. Pengaturan kebijakan terkelola dimuat terlepas dari itu. Lihat Use Claude Code features |
max_thinking_tokens |
int | None |
None |
Deprecated - Token maksimal untuk blok thinking. Gunakan thinking sebagai gantinya |
thinking |
ThinkingConfig | None |
None |
Mengontrol perilaku extended thinking. Mengambil prioritas atas max_thinking_tokens |
effort |
Literal["low", "medium", "high", "max"] | None |
None |
Tingkat usaha untuk kedalaman thinking |
session_store |
SessionStore | None |
None |
Cerminkan transkrip sesi ke backend eksternal sehingga host apa pun dapat melanjutkannya. Lihat Persist sessions to external storage |
session_store_flush |
Literal["batched", "eager"] |
"batched" |
Kapan membuang entri transkrip yang dicerminkan ke session_store. "batched" membuang sekali per putaran atau ketika buffer penuh; "eager" memicu pembilasan latar belakang setelah setiap frame. Diabaikan ketika session_store adalah None |
OutputFormat
Konfigurasi untuk validasi output terstruktur. Teruskan ini sebagai dict ke field output_format pada ClaudeAgentOptions:
# Expected dict shape for output_format
{
"type": "json_schema",
"schema": {...}, # Your JSON Schema definition
}
| Field | Diperlukan | Deskripsi |
|---|---|---|
type |
Ya | Harus "json_schema" untuk validasi JSON Schema |
schema |
Ya | Definisi JSON Schema untuk validasi output |
SystemPromptPreset
Konfigurasi untuk menggunakan preset system prompt Claude Code dengan penambahan opsional.
class SystemPromptPreset(TypedDict):
type: Literal["preset"]
preset: Literal["claude_code"]
append: NotRequired[str]
exclude_dynamic_sections: NotRequired[bool]
| Field | Diperlukan | Deskripsi |
|---|---|---|
type |
Ya | Harus "preset" untuk menggunakan preset system prompt |
preset |
Ya | Harus "claude_code" untuk menggunakan system prompt Claude Code |
append |
Tidak | Instruksi tambahan untuk ditambahkan ke preset system prompt |
exclude_dynamic_sections |
Tidak | Pindahkan konteks per-sesi seperti direktori kerja, status git, dan jalur memori dari system prompt ke pesan pengguna pertama. Meningkatkan reuse prompt-cache di seluruh pengguna dan mesin. Lihat Modify system prompts |
SettingSource
Mengontrol sumber konfigurasi berbasis filesystem mana yang dimuat pengaturan SDK.
SettingSource = Literal["user", "project", "local"]
| Nilai | Deskripsi | Lokasi |
|---|---|---|
"user" |
Pengaturan pengguna global | ~/.claude/settings.json |
"project" |
Pengaturan proyek bersama (version controlled) | .claude/settings.json |
"local" |
Pengaturan proyek lokal (gitignored) | .claude/settings.local.json |
Perilaku default
Ketika setting_sources dihilangkan atau None, query() memuat pengaturan filesystem yang sama seperti CLI Claude Code: pengguna, proyek, dan lokal. Pengaturan kebijakan terkelola dimuat dalam semua kasus. Lihat What settingSources does not control untuk input yang dibaca terlepas dari opsi ini, dan cara menonaktifkannya.
Mengapa menggunakan setting_sources
Nonaktifkan pengaturan filesystem:
# Do not load user, project, or local settings from disk
from claude_agent_sdk import query, ClaudeAgentOptions
async for message in query(
prompt="Analyze this code",
options=ClaudeAgentOptions(
setting_sources=[]
),
):
print(message)
Dalam Python SDK 0.1.59 dan lebih awal, daftar kosong diperlakukan sama dengan menghilangkan opsi, jadi setting_sources=[] tidak menonaktifkan pengaturan filesystem. Upgrade ke rilis yang lebih baru jika Anda memerlukan daftar kosong untuk berlaku. SDK TypeScript tidak terpengaruh.
Muat semua pengaturan filesystem secara eksplisit:
from claude_agent_sdk import query, ClaudeAgentOptions
async for message in query(
prompt="Analyze this code",
options=ClaudeAgentOptions(
setting_sources=["user", "project", "local"]
),
):
print(message)
Muat hanya sumber pengaturan tertentu:
# Load only project settings, ignore user and local
async for message in query(
prompt="Run CI checks",
options=ClaudeAgentOptions(
setting_sources=["project"] # Only .claude/settings.json
),
):
print(message)
Lingkungan testing dan CI:
# Ensure consistent behavior in CI by excluding local settings
async for message in query(
prompt="Run tests",
options=ClaudeAgentOptions(
setting_sources=["project"], # Only team-shared settings
permission_mode="bypassPermissions",
),
):
print(message)
Aplikasi SDK-only:
# Define everything programmatically.
# Pass [] to opt out of filesystem setting sources.
async for message in query(
prompt="Review this PR",
options=ClaudeAgentOptions(
setting_sources=[],
agents={...},
mcp_servers={...},
allowed_tools=["Read", "Grep", "Glob"],
),
):
print(message)
Memuat instruksi proyek CLAUDE.md:
# Load project settings to include CLAUDE.md files
async for message in query(
prompt="Add a new feature following project conventions",
options=ClaudeAgentOptions(
system_prompt={
"type": "preset",
"preset": "claude_code", # Use Claude Code's system prompt
},
setting_sources=["project"], # Loads CLAUDE.md from project
allowed_tools=["Read", "Write", "Edit"],
),
):
print(message)
Preseden pengaturan
Ketika beberapa sumber dimuat, pengaturan digabungkan dengan preseden ini (tertinggi ke terendah):
- Pengaturan lokal (
.claude/settings.local.json) - Pengaturan proyek (
.claude/settings.json) - Pengaturan pengguna (
~/.claude/settings.json)
Opsi programatis seperti agents dan allowed_tools mengganti pengaturan filesystem pengguna, proyek, dan lokal. Pengaturan kebijakan terkelola mengambil prioritas atas opsi programatis.
AgentDefinition
Konfigurasi untuk subagent yang didefinisikan secara programatis.
@dataclass
class AgentDefinition:
description: str
prompt: str
tools: list[str] | None = None
disallowedTools: list[str] | None = None
model: str | None = None
skills: list[str] | None = None
memory: Literal["user", "project", "local"] | None = None
mcpServers: list[str | dict[str, Any]] | None = None
initialPrompt: str | None = None
maxTurns: int | None = None
background: bool | None = None
effort: Literal["low", "medium", "high", "max"] | int | None = None
permissionMode: PermissionMode | None = None
| Field | Diperlukan | Deskripsi |
|---|---|---|
description |
Ya | Deskripsi bahasa alami tentang kapan menggunakan agent ini |
prompt |
Ya | System prompt agent |
tools |
Tidak | Array nama tool yang diizinkan. Jika dihilangkan, mewarisi semua tools |
disallowedTools |
Tidak | Array nama tool untuk dihapus dari set tool agent |
model |
Tidak | Penggantian model untuk agent ini. Menerima alias seperti "sonnet", "opus", "haiku", atau "inherit", atau ID model lengkap. Jika dihilangkan, menggunakan model utama |
skills |
Tidak | Daftar nama skill yang tersedia untuk agent ini |
memory |
Tidak | Sumber memori untuk agent ini: "user", "project", atau "local" |
mcpServers |
Tidak | Server MCP yang tersedia untuk agent ini. Setiap entri adalah nama server atau dict {name: config} inline |
initialPrompt |
Tidak | Auto-submitted sebagai putaran pengguna pertama ketika agent ini berjalan sebagai agent thread utama |
maxTurns |
Tidak | Jumlah maksimal putaran agentic sebelum agent berhenti |
background |
Tidak | Jalankan agent ini sebagai tugas latar belakang non-blocking ketika dipanggil |
effort |
Tidak | Tingkat usaha reasoning untuk agent ini. Menerima tingkat bernama atau integer |
permissionMode |
Tidak | Mode izin untuk eksekusi tool dalam agent ini. Lihat PermissionMode |
Field AgentDefinition menggunakan camelCase, seperti disallowedTools, permissionMode, dan maxTurns. Nama-nama ini memetakan langsung ke format wire yang dibagikan dengan SDK TypeScript. Ini berbeda dari ClaudeAgentOptions, yang menggunakan Python snake_case untuk field tingkat atas yang setara seperti disallowed_tools dan permission_mode. Karena AgentDefinition adalah dataclass, melewatkan keyword snake_case menimbulkan TypeError pada waktu konstruksi.
PermissionMode
Mode izin untuk mengontrol eksekusi tool.
PermissionMode = Literal[
"default", # Standard permission behavior
"acceptEdits", # Auto-accept file edits
"plan", # Planning mode - read-only tools only
"dontAsk", # Deny anything not pre-approved instead of prompting
"bypassPermissions", # Bypass all permission checks (use with caution)
]
CanUseTool
Type alias untuk fungsi callback izin tool.
CanUseTool = Callable[
[str, dict[str, Any], ToolPermissionContext], Awaitable[PermissionResult]
]
Callback menerima:
tool_name: Nama tool yang sedang dipanggilinput_data: Parameter input toolcontext:ToolPermissionContextdengan informasi tambahan
Mengembalikan PermissionResult (baik PermissionResultAllow atau PermissionResultDeny).
ToolPermissionContext
Informasi konteks yang diteruskan ke callback izin tool.
@dataclass
class ToolPermissionContext:
signal: Any | None = None # Future: abort signal support
suggestions: list[PermissionUpdate] = field(default_factory=list)
| Field | Tipe | Deskripsi |
|---|---|---|
signal |
Any | None |
Dicadangkan untuk dukungan sinyal abort di masa depan |
suggestions |
list[PermissionUpdate] |
Saran pembaruan izin dari CLI. Prompt Bash menyertakan saran dengan destinasi localSettings, jadi mengembalikannya dalam updated_permissions menulis aturan ke .claude/settings.local.json dan bertahan di seluruh sesi. |
PermissionResult
Tipe union untuk hasil callback izin.
PermissionResult = PermissionResultAllow | PermissionResultDeny
PermissionResultAllow
Hasil yang menunjukkan panggilan tool harus diizinkan.
@dataclass
class PermissionResultAllow:
behavior: Literal["allow"] = "allow"
updated_input: dict[str, Any] | None = None
updated_permissions: list[PermissionUpdate] | None = None
| Field | Tipe | Default | Deskripsi |
|---|---|---|---|
behavior |
Literal["allow"] |
"allow" |
Harus "allow" |
updated_input |
dict[str, Any] | None |
None |
Input yang dimodifikasi untuk digunakan alih-alih asli |
updated_permissions |
list[PermissionUpdate] | None |
None |
Pembaruan izin untuk diterapkan |
PermissionResultDeny
Hasil yang menunjukkan panggilan tool harus ditolak.
@dataclass
class PermissionResultDeny:
behavior: Literal["deny"] = "deny"
message: str = ""
interrupt: bool = False
| Field | Tipe | Default | Deskripsi |
|---|---|---|---|
behavior |
Literal["deny"] |
"deny" |
Harus "deny" |
message |
str |
"" |
Pesan yang menjelaskan mengapa tool ditolak |
interrupt |
bool |
False |
Apakah akan mengganggu eksekusi saat ini |
PermissionUpdate
Konfigurasi untuk memperbarui izin secara programatis.
@dataclass
class PermissionUpdate:
type: Literal[
"addRules",
"replaceRules",
"removeRules",
"setMode",
"addDirectories",
"removeDirectories",
]
rules: list[PermissionRuleValue] | None = None
behavior: Literal["allow", "deny", "ask"] | None = None
mode: PermissionMode | None = None
directories: list[str] | None = None
destination: (
Literal["userSettings", "projectSettings", "localSettings", "session"] | None
) = None
| Field | Tipe | Deskripsi |
|---|---|---|
type |
Literal[...] |
Jenis operasi pembaruan izin |
rules |
list[PermissionRuleValue] | None |
Aturan untuk operasi add/replace/remove |
behavior |
Literal["allow", "deny", "ask"] | None |
Perilaku untuk operasi berbasis aturan |
mode |
PermissionMode | None |
Mode untuk operasi setMode |
directories |
list[str] | None |
Direktori untuk operasi add/remove direktori |
destination |
Literal[...] | None |
Di mana menerapkan pembaruan izin |
PermissionRuleValue
Aturan untuk ditambahkan, diganti, atau dihapus dalam pembaruan izin.
@dataclass
class PermissionRuleValue:
tool_name: str
rule_content: str | None = None
ToolsPreset
Konfigurasi preset tools untuk menggunakan set tool default Claude Code.
class ToolsPreset(TypedDict):
type: Literal["preset"]
preset: Literal["claude_code"]
ThinkingConfig
Mengontrol perilaku extended thinking. Union dari tiga konfigurasi:
class ThinkingConfigAdaptive(TypedDict):
type: Literal["adaptive"]
class ThinkingConfigEnabled(TypedDict):
type: Literal["enabled"]
budget_tokens: int
class ThinkingConfigDisabled(TypedDict):
type: Literal["disabled"]
ThinkingConfig = ThinkingConfigAdaptive | ThinkingConfigEnabled | ThinkingConfigDisabled
| Varian | Field | Deskripsi |
|---|---|---|
adaptive |
type |
Claude secara adaptif memutuskan kapan harus berpikir |
enabled |
type, budget_tokens |
Aktifkan thinking dengan budget token tertentu |
disabled |
type |
Nonaktifkan thinking |
Karena ini adalah kelas TypedDict, mereka adalah dict biasa saat runtime. Baik buatlah sebagai dict literal atau panggil kelas seperti konstruktor; keduanya menghasilkan dict. Akses field dengan config["budget_tokens"], bukan config.budget_tokens:
from claude_agent_sdk import ClaudeAgentOptions, ThinkingConfigEnabled
# Option 1: dict literal (recommended, no import needed)
options = ClaudeAgentOptions(thinking={"type": "enabled", "budget_tokens": 20000})
# Option 2: constructor-style (returns a plain dict)
config = ThinkingConfigEnabled(type="enabled", budget_tokens=20000)
print(config["budget_tokens"]) # 20000
# config.budget_tokens would raise AttributeError
SdkBeta
Tipe literal untuk fitur beta SDK.
SdkBeta = Literal["context-1m-2025-08-07"]
Gunakan dengan field betas dalam ClaudeAgentOptions untuk mengaktifkan fitur beta.
Beta context-1m-2025-08-07 sudah pensiun sejak 30 April 2026. Melewatkan header ini dengan Claude Sonnet 4.5 atau Sonnet 4 tidak berpengaruh, dan permintaan yang melebihi jendela konteks standar 200k-token mengembalikan error. Untuk menggunakan jendela konteks 1M-token, migrasikan ke Claude Sonnet 4.6, Claude Opus 4.6, atau Claude Opus 4.7, yang mencakup konteks 1M pada harga standar tanpa header beta yang diperlukan.
McpSdkServerConfig
Konfigurasi untuk server MCP SDK yang dibuat dengan create_sdk_mcp_server().
class McpSdkServerConfig(TypedDict):
type: Literal["sdk"]
name: str
instance: Any # MCP Server instance
McpServerConfig
Tipe union untuk konfigurasi server MCP.
McpServerConfig = (
McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfig
)
McpStdioServerConfig
class McpStdioServerConfig(TypedDict):
type: NotRequired[Literal["stdio"]] # Optional for backwards compatibility
command: str
args: NotRequired[list[str]]
env: NotRequired[dict[str, str]]
McpSSEServerConfig
class McpSSEServerConfig(TypedDict):
type: Literal["sse"]
url: str
headers: NotRequired[dict[str, str]]
McpHttpServerConfig
class McpHttpServerConfig(TypedDict):
type: Literal["http"]
url: str
headers: NotRequired[dict[str, str]]
McpServerStatusConfig
Konfigurasi server MCP seperti yang dilaporkan oleh get_mcp_status(). Ini adalah union dari semua varian transport McpServerConfig ditambah varian output-only claudeai-proxy untuk server yang di-proxy melalui claude.ai.
McpServerStatusConfig = (
McpStdioServerConfig
| McpSSEServerConfig
| McpHttpServerConfig
| McpSdkServerConfigStatus
| McpClaudeAIProxyServerConfig
)
McpSdkServerConfigStatus adalah bentuk yang dapat diserialisasi dari McpSdkServerConfig dengan hanya field type ("sdk") dan name (str); instance dalam proses dihilangkan. McpClaudeAIProxyServerConfig memiliki field type ("claudeai-proxy"), url (str), dan id (str).
McpStatusResponse
Respons dari ClaudeSDKClient.get_mcp_status(). Membungkus daftar status server di bawah kunci mcpServers.
class McpStatusResponse(TypedDict):
mcpServers: list[McpServerStatus]
McpServerStatus
Status server MCP yang terhubung, terdapat dalam McpStatusResponse.
class McpServerStatus(TypedDict):
name: str
status: McpServerConnectionStatus # "connected" | "failed" | "needs-auth" | "pending" | "disabled"
serverInfo: NotRequired[McpServerInfo]
error: NotRequired[str]
config: NotRequired[McpServerStatusConfig]
scope: NotRequired[str]
tools: NotRequired[list[McpToolInfo]]
| Field | Tipe | Deskripsi |
|---|---|---|
name |
str |
Nama server |
status |
str |
Salah satu dari "connected", "failed", "needs-auth", "pending", atau "disabled" |
serverInfo |
dict (opsional) |
Nama dan versi server ({"name": str, "version": str}) |
error |
str (opsional) |
Pesan error jika server gagal terhubung |
config |
McpServerStatusConfig (opsional) |
Konfigurasi server. Bentuk yang sama seperti McpServerConfig (stdio, SSE, HTTP, atau SDK), ditambah varian claudeai-proxy untuk server yang terhubung melalui claude.ai |
scope |
str (opsional) |
Scope konfigurasi |
tools |
list (opsional) |
Tools yang disediakan oleh server ini, masing-masing dengan field name, description, dan annotations |
SdkPluginConfig
Konfigurasi untuk memuat plugins dalam SDK.
class SdkPluginConfig(TypedDict):
type: Literal["local"]
path: str
| Field | Tipe | Deskripsi |
|---|---|---|
type |
Literal["local"] |
Harus "local" (hanya plugins lokal yang saat ini didukung) |
path |
str |
Jalur absolut atau relatif ke direktori plugin |
Contoh:
plugins = [
{"type": "local", "path": "./my-plugin"},
{"type": "local", "path": "/absolute/path/to/plugin"},
]
Untuk informasi lengkap tentang membuat dan menggunakan plugins, lihat Plugins.
Tipe Pesan
Message
Tipe union dari semua pesan yang mungkin.
Message = (
UserMessage
| AssistantMessage
| SystemMessage
| ResultMessage
| StreamEvent
| RateLimitEvent
)
UserMessage
Pesan input pengguna.
@dataclass
class UserMessage:
content: str | list[ContentBlock]
uuid: str | None = None
parent_tool_use_id: str | None = None
tool_use_result: dict[str, Any] | None = None
| Field | Tipe | Deskripsi |
|---|---|---|
content |
str | list[ContentBlock] |
Konten pesan sebagai teks atau blok konten |
uuid |
str | None |
Pengenal pesan unik |
parent_tool_use_id |
str | None |
ID penggunaan tool jika pesan ini adalah respons hasil tool |
tool_use_result |
dict[str, Any] | None |
Data hasil tool jika berlaku |
AssistantMessage
Pesan respons asisten dengan blok konten.
@dataclass
class AssistantMessage:
content: list[ContentBlock]
model: str
parent_tool_use_id: str | None = None
error: AssistantMessageError | None = None
usage: dict[str, Any] | None = None
message_id: str | None = None
| Field | Tipe | Deskripsi |
|---|---|---|
content |
list[ContentBlock] |
Daftar blok konten dalam respons |
model |
str |
Model yang menghasilkan respons |
parent_tool_use_id |
str | None |
ID penggunaan tool jika ini adalah respons bersarang |
error |
AssistantMessageError | None |
Tipe error jika respons mengalami error |
usage |
dict[str, Any] | None |
Penggunaan token per-pesan (kunci yang sama seperti ResultMessage.usage) |
message_id |
str | None |
ID pesan API. Beberapa pesan dari satu putaran berbagi ID yang sama |
AssistantMessageError
Tipe error yang mungkin untuk pesan asisten.
AssistantMessageError = Literal[
"authentication_failed",
"billing_error",
"rate_limit",
"invalid_request",
"server_error",
"max_output_tokens",
"unknown",
]
SystemMessage
Pesan sistem dengan metadata.
@dataclass
class SystemMessage:
subtype: str
data: dict[str, Any]
ResultMessage
Pesan hasil akhir dengan informasi biaya dan penggunaan.
@dataclass
class ResultMessage:
subtype: str
duration_ms: int
duration_api_ms: int
is_error: bool
num_turns: int
session_id: str
total_cost_usd: float | None = None
usage: dict[str, Any] | None = None
result: str | None = None
stop_reason: str | None = None
structured_output: Any = None
model_usage: dict[str, Any] | None = None
Dict usage berisi kunci berikut ketika ada:
| Kunci | Tipe | Deskripsi |
|---|---|---|
input_tokens |
int |
Total token input yang dikonsumsi. |
output_tokens |
int |
Total token output yang dihasilkan. |
cache_creation_input_tokens |
int |
Token yang digunakan untuk membuat entri cache baru. |
cache_read_input_tokens |
int |
Token yang dibaca dari entri cache yang ada. |
Dict model_usage memetakan nama model ke penggunaan per-model. Kunci dict dalam menggunakan camelCase karena nilai diteruskan tanpa modifikasi dari proses CLI yang mendasar, cocok dengan tipe ModelUsage TypeScript:
| Kunci | Tipe | Deskripsi |
|---|---|---|
inputTokens |
int |
Token input untuk model ini. |
outputTokens |
int |
Token output untuk model ini. |
cacheReadInputTokens |
int |
Token baca cache untuk model ini. |
cacheCreationInputTokens |
int |
Token pembuatan cache untuk model ini. |
webSearchRequests |
int |
Permintaan pencarian web yang dibuat oleh model ini. |
costUSD |
float |
Biaya yang diperkirakan dalam USD untuk model ini, dihitung sisi klien. Lihat Track cost and usage untuk peringatan penagihan. |
contextWindow |
int |
Ukuran jendela konteks untuk model ini. |
maxOutputTokens |
int |
Batas token output maksimal untuk model ini. |
StreamEvent
Event stream untuk pembaruan pesan parsial selama streaming. Hanya diterima ketika include_partial_messages=True dalam ClaudeAgentOptions. Impor via from claude_agent_sdk.types import StreamEvent.
@dataclass
class StreamEvent:
uuid: str
session_id: str
event: dict[str, Any] # The raw Claude API stream event
parent_tool_use_id: str | None = None
| Field | Tipe | Deskripsi |
|---|---|---|
uuid |
str |
Pengenal unik untuk event ini |
session_id |
str |
Pengenal sesi |
event |
dict[str, Any] |
Data event stream Claude API mentah |
parent_tool_use_id |
str | None |
ID penggunaan tool induk jika event ini dari subagent |
RateLimitEvent
Dipancarkan ketika status rate limit berubah (misalnya, dari "allowed" ke "allowed_warning"). Gunakan ini untuk memperingatkan pengguna sebelum mereka mencapai batas keras, atau untuk mundur ketika status adalah "rejected".
@dataclass
class RateLimitEvent:
rate_limit_info: RateLimitInfo
uuid: str
session_id: str
| Field | Tipe | Deskripsi |
|---|---|---|
rate_limit_info |
RateLimitInfo |
Status rate limit saat ini |
uuid |
str |
Pengenal event unik |
session_id |
str |
Pengenal sesi |
RateLimitInfo
Status rate limit yang dibawa oleh RateLimitEvent.
RateLimitStatus = Literal["allowed", "allowed_warning", "rejected"]
RateLimitType = Literal[
"five_hour", "seven_day", "seven_day_opus", "seven_day_sonnet", "overage"
]
@dataclass
class RateLimitInfo:
status: RateLimitStatus
resets_at: int | None = None
rate_limit_type: RateLimitType | None = None
utilization: float | None = None
overage_status: RateLimitStatus | None = None
overage_resets_at: int | None = None
overage_disabled_reason: str | None = None
raw: dict[str, Any] = field(default_factory=dict)
| Field | Tipe | Deskripsi |
|---|---|---|
status |
RateLimitStatus |
Status saat ini. "allowed_warning" berarti mendekati batas; "rejected" berarti batas tercapai |
resets_at |
int | None |
Timestamp Unix ketika jendela rate limit direset |
rate_limit_type |
RateLimitType | None |
Jendela rate limit mana yang berlaku |
utilization |
float | None |
Fraksi rate limit yang dikonsumsi (0.0 hingga 1.0) |
overage_status |
RateLimitStatus | None |
Status penggunaan overage pay-as-you-go, jika berlaku |
overage_resets_at |
int | None |
Timestamp Unix ketika jendela overage direset |
overage_disabled_reason |
str | None |
Mengapa overage tidak tersedia, jika status adalah "rejected" |
raw |
dict[str, Any] |
Dict mentah lengkap dari CLI, termasuk field yang tidak dimodelkan di atas |
TaskStartedMessage
Dipancarkan ketika tugas latar belakang dimulai. Tugas latar belakang adalah apa pun yang dilacak di luar putaran utama: perintah Bash yang di-background, Monitor watch, subagent yang dihasilkan melalui tool Agent, atau agent jarak jauh. Field task_type memberi tahu Anda yang mana. Penamaan ini tidak terkait dengan penggantian nama tool Task-ke-Agent.
@dataclass
class TaskStartedMessage(SystemMessage):
task_id: str
description: str
uuid: str
session_id: str
tool_use_id: str | None = None
task_type: str | None = None
| Field | Tipe | Deskripsi |
|---|---|---|
task_id |
str |
Pengenal unik untuk tugas |
description |
str |
Deskripsi tugas |
uuid |
str |
Pengenal pesan unik |
session_id |
str |
Pengenal sesi |
tool_use_id |
str | None |
ID penggunaan tool yang terkait |
task_type |
str | None |
Jenis tugas latar belakang: "local_bash" untuk Bash dan Monitor watches di background, "local_agent", atau "remote_agent" |
TaskUsage
Data token dan timing untuk tugas latar belakang.
class TaskUsage(TypedDict):
total_tokens: int
tool_uses: int
duration_ms: int
TaskProgressMessage
Dipancarkan secara berkala dengan pembaruan kemajuan untuk tugas latar belakang yang sedang berjalan.
@dataclass
class TaskProgressMessage(SystemMessage):
task_id: str
description: str
usage: TaskUsage
uuid: str
session_id: str
tool_use_id: str | None = None
last_tool_name: str | None = None
| Field | Tipe | Deskripsi |
|---|---|---|
task_id |
str |
Pengenal unik untuk tugas |
description |
str |
Deskripsi status saat ini |
usage |
TaskUsage |
Penggunaan token untuk tugas ini sejauh ini |
uuid |
str |
Pengenal pesan unik |
session_id |
str |
Pengenal sesi |
tool_use_id |
str | None |
ID penggunaan tool yang terkait |
last_tool_name |
str | None |
Nama tool terakhir yang digunakan tugas |
TaskNotificationMessage
Dipancarkan ketika tugas latar belakang selesai, gagal, atau dihentikan. Tugas latar belakang termasuk perintah Bash run_in_background, Monitor watches, dan subagent latar belakang.
@dataclass
class TaskNotificationMessage(SystemMessage):
task_id: str
status: TaskNotificationStatus # "completed" | "failed" | "stopped"
output_file: str
summary: str
uuid: str
session_id: str
tool_use_id: str | None = None
usage: TaskUsage | None = None
| Field | Tipe | Deskripsi |
|---|---|---|
task_id |
str |
Pengenal unik untuk tugas |
status |
TaskNotificationStatus |
Salah satu dari "completed", "failed", atau "stopped" |
output_file |
str |
Jalur ke file output tugas |
summary |
str |
Ringkasan hasil tugas |
uuid |
str |
Pengenal pesan unik |
session_id |
str |
Pengenal sesi |
tool_use_id |
str | None |
ID penggunaan tool yang terkait |
usage |
TaskUsage | None |
Penggunaan token akhir untuk tugas |
Tipe Blok Konten
ContentBlock
Tipe union dari semua blok konten.
ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock
TextBlock
Blok konten teks.
@dataclass
class TextBlock:
text: str
ThinkingBlock
Blok konten thinking (untuk model dengan kemampuan thinking).
@dataclass
class ThinkingBlock:
thinking: str
signature: str
ToolUseBlock
Blok permintaan penggunaan tool.
@dataclass
class ToolUseBlock:
id: str
name: str
input: dict[str, Any]
ToolResultBlock
Blok hasil eksekusi tool.
@dataclass
class ToolResultBlock:
tool_use_id: str
content: str | list[dict[str, Any]] | None = None
is_error: bool | None = None
Tipe Error
ClaudeSDKError
Kelas exception dasar untuk semua error SDK.
class ClaudeSDKError(Exception):
"""Base error for Claude SDK."""
CLINotFoundError
Diangkat ketika Claude Code CLI tidak diinstal atau tidak ditemukan.
class CLINotFoundError(CLIConnectionError):
def __init__(
self, message: str = "Claude Code not found", cli_path: str | None = None
):
"""
Args:
message: Error message (default: "Claude Code not found")
cli_path: Optional path to the CLI that was not found
"""
CLIConnectionError
Diangkat ketika koneksi ke Claude Code gagal.
class CLIConnectionError(ClaudeSDKError):
"""Failed to connect to Claude Code."""
ProcessError
Diangkat ketika proses Claude Code gagal.
class ProcessError(ClaudeSDKError):
def __init__(
self, message: str, exit_code: int | None = None, stderr: str | None = None
):
self.exit_code = exit_code
self.stderr = stderr
CLIJSONDecodeError
Diangkat ketika parsing JSON gagal.
class CLIJSONDecodeError(ClaudeSDKError):
def __init__(self, line: str, original_error: Exception):
"""
Args:
line: The line that failed to parse
original_error: The original JSON decode exception
"""
self.line = line
self.original_error = original_error
Tipe Hook
Untuk panduan komprehensif tentang menggunakan hooks dengan contoh dan pola umum, lihat Hooks guide.
HookEvent
Tipe event hook yang didukung.
HookEvent = Literal[
"PreToolUse", # Called before tool execution
"PostToolUse", # Called after tool execution
"PostToolUseFailure", # Called when a tool execution fails
"UserPromptSubmit", # Called when user submits a prompt
"Stop", # Called when stopping execution
"SubagentStop", # Called when a subagent stops
"PreCompact", # Called before message compaction
"Notification", # Called for notification events
"SubagentStart", # Called when a subagent starts
"PermissionRequest", # Called when a permission decision is needed
]
SDK TypeScript mendukung event hook tambahan yang belum tersedia di Python: SessionStart, SessionEnd, Setup, TeammateIdle, TaskCompleted, ConfigChange, WorktreeCreate, WorktreeRemove, dan PostToolBatch.
HookCallback
Definisi tipe untuk fungsi callback hook.
HookCallback = Callable[[HookInput, str | None, HookContext], Awaitable[HookJSONOutput]]
Parameter:
input: Input hook yang kuat dengan union yang dibedakan berdasarkanhook_event_name(lihatHookInput)tool_use_id: Pengenal penggunaan tool opsional (untuk hook terkait tool)context: Konteks hook dengan informasi tambahan
Mengembalikan HookJSONOutput yang mungkin berisi:
decision:"block"untuk memblokir tindakansystemMessage: Pesan sistem untuk ditambahkan ke transkriphookSpecificOutput: Data output spesifik hook
HookContext
Informasi konteks yang diteruskan ke callback hook.
class HookContext(TypedDict):
signal: Any | None # Future: abort signal support
HookMatcher
Konfigurasi untuk mencocokkan hooks ke event atau tools tertentu.
@dataclass
class HookMatcher:
matcher: str | None = (
None # Tool name or pattern to match (e.g., "Bash", "Write|Edit")
)
hooks: list[HookCallback] = field(
default_factory=list
) # List of callbacks to execute
timeout: float | None = (
None # Timeout in seconds for all hooks in this matcher (default: 60)
)
HookInput
Tipe union dari semua tipe input hook. Tipe aktual bergantung pada field hook_event_name.
HookInput = (
PreToolUseHookInput
| PostToolUseHookInput
| PostToolUseFailureHookInput
| UserPromptSubmitHookInput
| StopHookInput
| SubagentStopHookInput
| PreCompactHookInput
| NotificationHookInput
| SubagentStartHookInput
| PermissionRequestHookInput
)
BaseHookInput
Field dasar yang ada di semua tipe input hook.
class BaseHookInput(TypedDict):
session_id: str
transcript_path: str
cwd: str
permission_mode: NotRequired[str]
| Field | Tipe | Deskripsi |
|---|---|---|
session_id |
str |
Pengenal sesi saat ini |
transcript_path |
str |
Jalur ke file transkrip sesi |
cwd |
str |
Direktori kerja saat ini |
permission_mode |
str (opsional) |
Mode izin saat ini |
PreToolUseHookInput
Data input untuk event hook PreToolUse.
class PreToolUseHookInput(BaseHookInput):
hook_event_name: Literal["PreToolUse"]
tool_name: str
tool_input: dict[str, Any]
tool_use_id: str
agent_id: NotRequired[str]
agent_type: NotRequired[str]
| Field | Tipe | Deskripsi |
|---|---|---|
hook_event_name |
Literal["PreToolUse"] |
Selalu "PreToolUse" |
tool_name |
str |
Nama tool yang akan dieksekusi |
tool_input |
dict[str, Any] |
Parameter input untuk tool |
tool_use_id |
str |
Pengenal unik untuk penggunaan tool ini |
agent_id |
str (opsional) |
Pengenal subagent, ada ketika hook menyala di dalam subagent |
agent_type |
str (opsional) |
Tipe subagent, ada ketika hook menyala di dalam subagent |
PostToolUseHookInput
Data input untuk event hook PostToolUse.
class PostToolUseHookInput(BaseHookInput):
hook_event_name: Literal["PostToolUse"]
tool_name: str
tool_input: dict[str, Any]
tool_response: Any
tool_use_id: str
agent_id: NotRequired[str]
agent_type: NotRequired[str]
| Field | Tipe | Deskripsi |
|---|---|---|
hook_event_name |
Literal["PostToolUse"] |
Selalu "PostToolUse" |
tool_name |
str |
Nama tool yang dieksekusi |
tool_input |
dict[str, Any] |
Parameter input yang digunakan |
tool_response |
Any |
Respons dari eksekusi tool |
tool_use_id |
str |
Pengenal unik untuk penggunaan tool ini |
agent_id |
str (opsional) |
Pengenal subagent, ada ketika hook menyala di dalam subagent |
agent_type |
str (opsional) |
Tipe subagent, ada ketika hook menyala di dalam subagent |
PostToolUseFailureHookInput
Data input untuk event hook PostToolUseFailure. Dipanggil ketika eksekusi tool gagal.
class PostToolUseFailureHookInput(BaseHookInput):
hook_event_name: Literal["PostToolUseFailure"]
tool_name: str
tool_input: dict[str, Any]
tool_use_id: str
error: str
is_interrupt: NotRequired[bool]
agent_id: NotRequired[str]
agent_type: NotRequired[str]
| Field | Tipe | Deskripsi |
|---|---|---|
hook_event_name |
Literal["PostToolUseFailure"] |
Selalu "PostToolUseFailure" |
tool_name |
str |
Nama tool yang gagal |
tool_input |
dict[str, Any] |
Parameter input yang digunakan |
tool_use_id |
str |
Pengenal unik untuk penggunaan tool ini |
error |
str |
Pesan error dari eksekusi yang gagal |
is_interrupt |
bool (opsional) |
Apakah kegagalan disebabkan oleh interrupt |
agent_id |
str (opsional) |
Pengenal subagent, ada ketika hook menyala di dalam subagent |
agent_type |
str (opsional) |
Tipe subagent, ada ketika hook menyala di dalam subagent |
UserPromptSubmitHookInput
Data input untuk event hook UserPromptSubmit.
class UserPromptSubmitHookInput(BaseHookInput):
hook_event_name: Literal["UserPromptSubmit"]
prompt: str
| Field | Tipe | Deskripsi |
|---|---|---|
hook_event_name |
Literal["UserPromptSubmit"] |
Selalu "UserPromptSubmit" |
prompt |
str |
Prompt yang dikirimkan pengguna |
StopHookInput
Data input untuk event hook Stop.
class StopHookInput(BaseHookInput):
hook_event_name: Literal["Stop"]
stop_hook_active: bool
| Field | Tipe | Deskripsi |
|---|---|---|
hook_event_name |
Literal["Stop"] |
Selalu "Stop" |
stop_hook_active |
bool |
Apakah stop hook aktif |
SubagentStopHookInput
Data input untuk event hook SubagentStop.
class SubagentStopHookInput(BaseHookInput):
hook_event_name: Literal["SubagentStop"]
stop_hook_active: bool
agent_id: str
agent_transcript_path: str
agent_type: str
| Field | Tipe | Deskripsi |
|---|---|---|
hook_event_name |
Literal["SubagentStop"] |
Selalu "SubagentStop" |
stop_hook_active |
bool |
Apakah stop hook aktif |
agent_id |
str |
Pengenal unik untuk subagent |
agent_transcript_path |
str |
Jalur ke file transkrip subagent |
agent_type |
str |
Tipe subagent |
PreCompactHookInput
Data input untuk event hook PreCompact.
class PreCompactHookInput(BaseHookInput):
hook_event_name: Literal["PreCompact"]
trigger: Literal["manual", "auto"]
custom_instructions: str | None
| Field | Tipe | Deskripsi |
|---|---|---|
hook_event_name |
Literal["PreCompact"] |
Selalu "PreCompact" |
trigger |
Literal["manual", "auto"] |
Apa yang memicu pemadatan |
custom_instructions |
str | None |
Instruksi kustom untuk pemadatan |
NotificationHookInput
Data input untuk event hook Notification.
class NotificationHookInput(BaseHookInput):
hook_event_name: Literal["Notification"]
message: str
title: NotRequired[str]
notification_type: str
| Field | Tipe | Deskripsi |
|---|---|---|
hook_event_name |
Literal["Notification"] |
Selalu "Notification" |
message |
str |
Konten pesan notifikasi |
title |
str (opsional) |
Judul notifikasi |
notification_type |
str |
Tipe notifikasi |
SubagentStartHookInput
Data input untuk event hook SubagentStart.
class SubagentStartHookInput(BaseHookInput):
hook_event_name: Literal["SubagentStart"]
agent_id: str
agent_type: str
| Field | Tipe | Deskripsi |
|---|---|---|
hook_event_name |
Literal["SubagentStart"] |
Selalu "SubagentStart" |
agent_id |
str |
Pengenal unik untuk subagent |
agent_type |
str |
Tipe subagent |
PermissionRequestHookInput
Data input untuk event hook PermissionRequest. Memungkinkan hooks untuk menangani keputusan izin secara programatis.
class PermissionRequestHookInput(BaseHookInput):
hook_event_name: Literal["PermissionRequest"]
tool_name: str
tool_input: dict[str, Any]
permission_suggestions: NotRequired[list[Any]]
| Field | Tipe | Deskripsi |
|---|---|---|
hook_event_name |
Literal["PermissionRequest"] |
Selalu "PermissionRequest" |
tool_name |
str |
Nama tool yang meminta izin |
tool_input |
dict[str, Any] |
Parameter input untuk tool |
permission_suggestions |
list[Any] (opsional) |
Saran pembaruan izin dari CLI |
HookJSONOutput
Tipe union untuk nilai pengembalian callback hook.
HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutput
SyncHookJSONOutput
Output hook sinkron dengan field kontrol dan keputusan.
class SyncHookJSONOutput(TypedDict):
# Control fields
continue_: NotRequired[bool] # Whether to proceed (default: True)
suppressOutput: NotRequired[bool] # Hide stdout from transcript
stopReason: NotRequired[str] # Message when continue is False
# Decision fields
decision: NotRequired[Literal["block"]]
systemMessage: NotRequired[str] # Warning message for user
reason: NotRequired[str] # Feedback for Claude
# Hook-specific output
hookSpecificOutput: NotRequired[HookSpecificOutput]
Gunakan continue_ (dengan underscore) dalam kode Python. Ini secara otomatis dikonversi ke continue ketika dikirim ke CLI.
HookSpecificOutput
TypedDict yang berisi nama event hook dan field spesifik event. Bentuknya bergantung pada nilai hookEventName. Untuk detail lengkap tentang field yang tersedia per event hook, lihat Control execution with hooks.
Union yang dibedakan dari tipe output spesifik event. Field hookEventName menentukan field mana yang valid.
class PreToolUseHookSpecificOutput(TypedDict):
hookEventName: Literal["PreToolUse"]
permissionDecision: NotRequired[Literal["allow", "deny", "ask"]]
permissionDecisionReason: NotRequired[str]
updatedInput: NotRequired[dict[str, Any]]
additionalContext: NotRequired[str]
class PostToolUseHookSpecificOutput(TypedDict):
hookEventName: Literal["PostToolUse"]
additionalContext: NotRequired[str]
updatedMCPToolOutput: NotRequired[Any]
class PostToolUseFailureHookSpecificOutput(TypedDict):
hookEventName: Literal["PostToolUseFailure"]
additionalContext: NotRequired[str]
class UserPromptSubmitHookSpecificOutput(TypedDict):
hookEventName: Literal["UserPromptSubmit"]
additionalContext: NotRequired[str]
class NotificationHookSpecificOutput(TypedDict):
hookEventName: Literal["Notification"]
additionalContext: NotRequired[str]
class SubagentStartHookSpecificOutput(TypedDict):
hookEventName: Literal["SubagentStart"]
additionalContext: NotRequired[str]
class PermissionRequestHookSpecificOutput(TypedDict):
hookEventName: Literal["PermissionRequest"]
decision: dict[str, Any]
HookSpecificOutput = (
PreToolUseHookSpecificOutput
| PostToolUseHookSpecificOutput
| PostToolUseFailureHookSpecificOutput
| UserPromptSubmitHookSpecificOutput
| NotificationHookSpecificOutput
| SubagentStartHookSpecificOutput
| PermissionRequestHookSpecificOutput
)
AsyncHookJSONOutput
Output hook async yang menunda eksekusi hook.
class AsyncHookJSONOutput(TypedDict):
async_: Literal[True] # Set to True to defer execution
asyncTimeout: NotRequired[int] # Timeout in milliseconds
Gunakan async_ (dengan underscore) dalam kode Python. Ini secara otomatis dikonversi ke async ketika dikirim ke CLI.
Contoh Penggunaan Hook
Contoh ini mendaftarkan dua hooks: satu yang memblokir perintah bash berbahaya seperti rm -rf /, dan satu lagi yang mencatat semua penggunaan tool untuk audit. Hook keamanan hanya berjalan pada perintah Bash (melalui matcher), sementara hook logging berjalan pada semua tools.
from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher, HookContext
from typing import Any
async def validate_bash_command(
input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
"""Validate and potentially block dangerous bash commands."""
if input_data["tool_name"] == "Bash":
command = input_data["tool_input"].get("command", "")
if "rm -rf /" in command:
return {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Dangerous command blocked",
}
}
return {}
async def log_tool_use(
input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
"""Log all tool usage for auditing."""
print(f"Tool used: {input_data.get('tool_name')}")
return {}
options = ClaudeAgentOptions(
hooks={
"PreToolUse": [
HookMatcher(
matcher="Bash", hooks=[validate_bash_command], timeout=120
), # 2 min for validation
HookMatcher(
hooks=[log_tool_use]
), # Applies to all tools (default 60s timeout)
],
"PostToolUse": [HookMatcher(hooks=[log_tool_use])],
}
)
async for message in query(prompt="Analyze this codebase", options=options):
print(message)
Tipe Input/Output Tool
Dokumentasi skema input/output untuk semua tools Claude Code bawaan. Meskipun Python SDK tidak mengekspor ini sebagai tipe, mereka mewakili struktur input dan output tool dalam pesan.
Agent
Nama tool: Agent (sebelumnya Task, yang masih diterima sebagai alias)
Input:
{
"description": str, # A short (3-5 word) description of the task
"prompt": str, # The task for the agent to perform
"subagent_type": str, # The type of specialized agent to use
}
Output:
{
"result": str, # Final result from the subagent
"usage": dict | None, # Token usage statistics
"total_cost_usd": float | None, # Estimated total cost in USD
"duration_ms": int | None, # Execution duration in milliseconds
}
AskUserQuestion
Nama tool: AskUserQuestion
Mengajukan pertanyaan klarifikasi kepada pengguna selama eksekusi. Lihat Handle approvals and user input untuk detail penggunaan.
Input:
{
"questions": [ # Questions to ask the user (1-4 questions)
{
"question": str, # The complete question to ask the user
"header": str, # Very short label displayed as a chip/tag (max 12 chars)
"options": [ # The available choices (2-4 options)
{
"label": str, # Display text for this option (1-5 words)
"description": str, # Explanation of what this option means
}
],
"multiSelect": bool, # Set to true to allow multiple selections
}
],
"answers": dict | None, # User answers populated by the permission system
}
Output:
{
"questions": [ # The questions that were asked
{
"question": str,
"header": str,
"options": [{"label": str, "description": str}],
"multiSelect": bool,
}
],
"answers": dict[str, str], # Maps question text to answer string
# Multi-select answers are comma-separated
}
Bash
Nama tool: Bash
Input:
{
"command": str, # The command to execute
"timeout": int | None, # Optional timeout in milliseconds (max 600000)
"description": str | None, # Clear, concise description (5-10 words)
"run_in_background": bool | None, # Set to true to run in background
}
Output:
{
"output": str, # Combined stdout and stderr output
"exitCode": int, # Exit code of the command
"killed": bool | None, # Whether command was killed due to timeout
"shellId": str | None, # Shell ID for background processes
}
Monitor
Nama tool: Monitor
Menjalankan skrip latar belakang dan mengirimkan setiap baris stdout ke Claude sebagai event sehingga dapat bereaksi tanpa polling. Monitor mengikuti aturan izin yang sama seperti Bash. Lihat Monitor tool reference untuk perilaku dan ketersediaan penyedia.
Input:
{
"command": str, # Shell script; each stdout line is an event, exit ends the watch
"description": str, # Short description shown in notifications
"timeout_ms": int | None, # Kill after this deadline (default 300000, max 3600000)
"persistent": bool | None, # Run for the lifetime of the session; stop with TaskStop
}
Output:
{
"taskId": str, # ID of the background monitor task
"timeoutMs": int, # Timeout deadline in milliseconds
"persistent": bool | None, # True when running until TaskStop or session end
}
Edit
Nama tool: Edit
Input:
{
"file_path": str, # The absolute path to the file to modify
"old_string": str, # The text to replace
"new_string": str, # The text to replace it with
"replace_all": bool | None, # Replace all occurrences (default False)
}
Output:
{
"message": str, # Confirmation message
"replacements": int, # Number of replacements made
"file_path": str, # File path that was edited
}
Read
Nama tool: Read
Input:
{
"file_path": str, # The absolute path to the file to read
"offset": int | None, # The line number to start reading from
"limit": int | None, # The number of lines to read
}
Output (File teks):
{
"content": str, # File contents with line numbers
"total_lines": int, # Total number of lines in file
"lines_returned": int, # Lines actually returned
}
Output (Gambar):
{
"image": str, # Base64 encoded image data
"mime_type": str, # Image MIME type
"file_size": int, # File size in bytes
}
Write
Nama tool: Write
Input:
{
"file_path": str, # The absolute path to the file to write
"content": str, # The content to write to the file
}
Output:
{
"message": str, # Success message
"bytes_written": int, # Number of bytes written
"file_path": str, # File path that was written
}
Glob
Nama tool: Glob
Input:
{
"pattern": str, # The glob pattern to match files against
"path": str | None, # The directory to search in (defaults to cwd)
}
Output:
{
"matches": list[str], # Array of matching file paths
"count": int, # Number of matches found
"search_path": str, # Search directory used
}
Grep
Nama tool: Grep
Input:
{
"pattern": str, # The regular expression pattern
"path": str | None, # File or directory to search in
"glob": str | None, # Glob pattern to filter files
"type": str | None, # File type to search
"output_mode": str | None, # "content", "files_with_matches", or "count"
"-i": bool | None, # Case insensitive search
"-n": bool | None, # Show line numbers
"-B": int | None, # Lines to show before each match
"-A": int | None, # Lines to show after each match
"-C": int | None, # Lines to show before and after
"head_limit": int | None, # Limit output to first N lines/entries
"multiline": bool | None, # Enable multiline mode
}
Output (content mode):
{
"matches": [
{
"file": str,
"line_number": int | None,
"line": str,
"before_context": list[str] | None,
"after_context": list[str] | None,
}
],
"total_matches": int,
}
Output (files_with_matches mode):
{
"files": list[str], # Files containing matches
"count": int, # Number of files with matches
}
NotebookEdit
Nama tool: NotebookEdit
Input:
{
"notebook_path": str, # Absolute path to the Jupyter notebook
"cell_id": str | None, # The ID of the cell to edit
"new_source": str, # The new source for the cell
"cell_type": "code" | "markdown" | None, # The type of the cell
"edit_mode": "replace" | "insert" | "delete" | None, # Edit operation type
}
Output:
{
"message": str, # Success message
"edit_type": "replaced" | "inserted" | "deleted", # Type of edit performed
"cell_id": str | None, # Cell ID that was affected
"total_cells": int, # Total cells in notebook after edit
}
WebFetch
Nama tool: WebFetch
Input:
{
"url": str, # The URL to fetch content from
"prompt": str, # The prompt to run on the fetched content
}
Output:
{
"response": str, # AI model's response to the prompt
"url": str, # URL that was fetched
"final_url": str | None, # Final URL after redirects
"status_code": int | None, # HTTP status code
}
WebSearch
Nama tool: WebSearch
Input:
{
"query": str, # The search query to use
"allowed_domains": list[str] | None, # Only include results from these domains
"blocked_domains": list[str] | None, # Never include results from these domains
}
Output:
{
"results": [{"title": str, "url": str, "snippet": str, "metadata": dict | None}],
"total_results": int,
"query": str,
}
TodoWrite
Nama tool: TodoWrite
Input:
{
"todos": [
{
"content": str, # The task description
"status": "pending" | "in_progress" | "completed", # Task status
"activeForm": str, # Active form of the description
}
]
}
Output:
{
"message": str, # Success message
"stats": {"total": int, "pending": int, "in_progress": int, "completed": int},
}
BashOutput
Nama tool: BashOutput
Input:
{
"bash_id": str, # The ID of the background shell
"filter": str | None, # Optional regex to filter output lines
}
Output:
{
"output": str, # New output since last check
"status": "running" | "completed" | "failed", # Current shell status
"exitCode": int | None, # Exit code when completed
}
KillBash
Nama tool: KillBash
Input:
{
"shell_id": str # The ID of the background shell to kill
}
Output:
{
"message": str, # Success message
"shell_id": str, # ID of the killed shell
}
ExitPlanMode
Nama tool: ExitPlanMode
Input:
{
"plan": str # The plan to run by the user for approval
}
Output:
{
"message": str, # Confirmation message
"approved": bool | None, # Whether user approved the plan
}
ListMcpResources
Nama tool: ListMcpResources
Input:
{
"server": str | None # Optional server name to filter resources by
}
Output:
{
"resources": [
{
"uri": str,
"name": str,
"description": str | None,
"mimeType": str | None,
"server": str,
}
],
"total": int,
}
ReadMcpResource
Nama tool: ReadMcpResource
Input:
{
"server": str, # The MCP server name
"uri": str, # The resource URI to read
}
Output:
{
"contents": [
{"uri": str, "mimeType": str | None, "text": str | None, "blob": str | None}
],
"server": str,
}
Fitur Lanjutan dengan ClaudeSDKClient
Membangun Antarmuka Percakapan Berkelanjutan
from claude_agent_sdk import (
ClaudeSDKClient,
ClaudeAgentOptions,
AssistantMessage,
TextBlock,
)
import asyncio
class ConversationSession:
"""Maintains a single conversation session with Claude."""
def __init__(self, options: ClaudeAgentOptions | None = None):
self.client = ClaudeSDKClient(options)
self.turn_count = 0
async def start(self):
await self.client.connect()
print("Starting conversation session. Claude will remember context.")
print(
"Commands: 'exit' to quit, 'interrupt' to stop current task, 'new' for new session"
)
while True:
user_input = input(f"\n[Turn {self.turn_count + 1}] You: ")
if user_input.lower() == "exit":
break
elif user_input.lower() == "interrupt":
await self.client.interrupt()
print("Task interrupted!")
continue
elif user_input.lower() == "new":
# Disconnect and reconnect for a fresh session
await self.client.disconnect()
await self.client.connect()
self.turn_count = 0
print("Started new conversation session (previous context cleared)")
continue
# Send message - the session retains all previous messages
await self.client.query(user_input)
self.turn_count += 1
# Process response
print(f"[Turn {self.turn_count}] Claude: ", end="")
async for message in self.client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(block.text, end="")
print() # New line after response
await self.client.disconnect()
print(f"Conversation ended after {self.turn_count} turns.")
async def main():
options = ClaudeAgentOptions(
allowed_tools=["Read", "Write", "Bash"], permission_mode="acceptEdits"
)
session = ConversationSession(options)
await session.start()
# Example conversation:
# Turn 1 - You: "Create a file called hello.py"
# Turn 1 - Claude: "I'll create a hello.py file for you..."
# Turn 2 - You: "What's in that file?"
# Turn 2 - Claude: "The hello.py file I just created contains..." (remembers!)
# Turn 3 - You: "Add a main function to it"
# Turn 3 - Claude: "I'll add a main function to hello.py..." (knows which file!)
asyncio.run(main())
Menggunakan Hooks untuk Modifikasi Perilaku
from claude_agent_sdk import (
ClaudeSDKClient,
ClaudeAgentOptions,
HookMatcher,
HookContext,
)
import asyncio
from typing import Any
async def pre_tool_logger(
input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
"""Log all tool usage before execution."""
tool_name = input_data.get("tool_name", "unknown")
print(f"[PRE-TOOL] About to use: {tool_name}")
# You can modify or block the tool execution here
if tool_name == "Bash" and "rm -rf" in str(input_data.get("tool_input", {})):
return {
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Dangerous command blocked",
}
}
return {}
async def post_tool_logger(
input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
"""Log results after tool execution."""
tool_name = input_data.get("tool_name", "unknown")
print(f"[POST-TOOL] Completed: {tool_name}")
return {}
async def user_prompt_modifier(
input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
"""Add context to user prompts."""
original_prompt = input_data.get("prompt", "")
# Add a timestamp as additional context for Claude to see
from datetime import datetime
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return {
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": f"[Submitted at {timestamp}] Original prompt: {original_prompt}",
}
}
async def main():
options = ClaudeAgentOptions(
hooks={
"PreToolUse": [
HookMatcher(hooks=[pre_tool_logger]),
HookMatcher(matcher="Bash", hooks=[pre_tool_logger]),
],
"PostToolUse": [HookMatcher(hooks=[post_tool_logger])],
"UserPromptSubmit": [HookMatcher(hooks=[user_prompt_modifier])],
},
allowed_tools=["Read", "Write", "Bash"],
)
async with ClaudeSDKClient(options=options) as client:
await client.query("List files in current directory")
async for message in client.receive_response():
# Hooks will automatically log tool usage
pass
asyncio.run(main())
Pemantauan Kemajuan Real-time
from claude_agent_sdk import (
ClaudeSDKClient,
ClaudeAgentOptions,
AssistantMessage,
ToolUseBlock,
ToolResultBlock,
TextBlock,
)
import asyncio
async def monitor_progress():
options = ClaudeAgentOptions(
allowed_tools=["Write", "Bash"], permission_mode="acceptEdits"
)
async with ClaudeSDKClient(options=options) as client:
await client.query("Create 5 Python files with different sorting algorithms")
# Monitor progress in real-time
async for message in client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, ToolUseBlock):
if block.name == "Write":
file_path = block.input.get("file_path", "")
print(f"Creating: {file_path}")
elif isinstance(block, ToolResultBlock):
print("Completed tool execution")
elif isinstance(block, TextBlock):
print(f"Claude says: {block.text[:100]}...")
print("Task completed!")
asyncio.run(monitor_progress())
Contoh Penggunaan
Operasi file dasar (menggunakan query)
from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ToolUseBlock
import asyncio
async def create_project():
options = ClaudeAgentOptions(
allowed_tools=["Read", "Write", "Bash"],
permission_mode="acceptEdits",
cwd="/home/user/project",
)
async for message in query(
prompt="Create a Python project structure with setup.py", options=options
):
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, ToolUseBlock):
print(f"Using tool: {block.name}")
asyncio.run(create_project())
Penanganan error
from claude_agent_sdk import query, CLINotFoundError, ProcessError, CLIJSONDecodeError
try:
async for message in query(prompt="Hello"):
print(message)
except CLINotFoundError:
print(
"Claude Code CLI not found. Try reinstalling: pip install --force-reinstall claude-agent-sdk"
)
except ProcessError as e:
print(f"Process failed with exit code: {e.exit_code}")
except CLIJSONDecodeError as e:
print(f"Failed to parse response: {e}")
Mode streaming dengan klien
from claude_agent_sdk import ClaudeSDKClient
import asyncio
async def interactive_session():
async with ClaudeSDKClient() as client:
# Send initial message
await client.query("What's the weather like?")
# Process responses
async for msg in client.receive_response():
print(msg)
# Send follow-up
await client.query("Tell me more about that")
# Process follow-up response
async for msg in client.receive_response():
print(msg)
asyncio.run(interactive_session())
Menggunakan tools kustom dengan ClaudeSDKClient
from claude_agent_sdk import (
ClaudeSDKClient,
ClaudeAgentOptions,
tool,
create_sdk_mcp_server,
AssistantMessage,
TextBlock,
)
import asyncio
from typing import Any
# Define custom tools with @tool decorator
@tool("calculate", "Perform mathematical calculations", {"expression": str})
async def calculate(args: dict[str, Any]) -> dict[str, Any]:
try:
result = eval(args["expression"], {"__builtins__": {}})
return {"content": [{"type": "text", "text": f"Result: {result}"}]}
except Exception as e:
return {
"content": [{"type": "text", "text": f"Error: {str(e)}"}],
"is_error": True,
}
@tool("get_time", "Get current time", {})
async def get_time(args: dict[str, Any]) -> dict[str, Any]:
from datetime import datetime
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return {"content": [{"type": "text", "text": f"Current time: {current_time}"}]}
async def main():
# Create SDK MCP server with custom tools
my_server = create_sdk_mcp_server(
name="utilities", version="1.0.0", tools=[calculate, get_time]
)
# Configure options with the server
options = ClaudeAgentOptions(
mcp_servers={"utils": my_server},
allowed_tools=["mcp__utils__calculate", "mcp__utils__get_time"],
)
# Use ClaudeSDKClient for interactive tool usage
async with ClaudeSDKClient(options=options) as client:
await client.query("What's 123 * 456?")
# Process calculation response
async for message in client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Calculation: {block.text}")
# Follow up with time query
await client.query("What time is it now?")
async for message in client.receive_response():
if isinstance(message, AssistantMessage):
for block in message.content:
if isinstance(block, TextBlock):
print(f"Time: {block.text}")
asyncio.run(main())
Konfigurasi Sandbox
SandboxSettings
Konfigurasi untuk perilaku sandbox. Gunakan ini untuk mengaktifkan sandboxing perintah dan mengonfigurasi pembatasan jaringan secara programatis.
class SandboxSettings(TypedDict, total=False):
enabled: bool
autoAllowBashIfSandboxed: bool
excludedCommands: list[str]
allowUnsandboxedCommands: bool
network: SandboxNetworkConfig
ignoreViolations: SandboxIgnoreViolations
enableWeakerNestedSandbox: bool
| Properti | Tipe | Default | Deskripsi |
|---|---|---|---|
enabled |
bool |
False |
Aktifkan mode sandbox untuk eksekusi perintah |
autoAllowBashIfSandboxed |
bool |
True |
Auto-approve perintah bash ketika sandbox diaktifkan |
excludedCommands |
list[str] |
[] |
Perintah yang selalu melewati pembatasan sandbox (misalnya, ["docker"]). Ini berjalan tanpa sandbox secara otomatis tanpa keterlibatan model |
allowUnsandboxedCommands |
bool |
True |
Izinkan model untuk meminta menjalankan perintah di luar sandbox. Ketika True, model dapat mengatur dangerouslyDisableSandbox dalam input tool, yang jatuh kembali ke sistem izin |
network |
SandboxNetworkConfig |
None |
Konfigurasi sandbox spesifik jaringan |
ignoreViolations |
SandboxIgnoreViolations |
None |
Konfigurasi pelanggaran sandbox mana yang akan diabaikan |
enableWeakerNestedSandbox |
bool |
False |
Aktifkan sandbox bersarang yang lebih lemah untuk kompatibilitas |
Contoh penggunaan
from claude_agent_sdk import query, ClaudeAgentOptions, SandboxSettings
sandbox_settings: SandboxSettings = {
"enabled": True,
"autoAllowBashIfSandboxed": True,
"network": {"allowLocalBinding": True},
}
async for message in query(
prompt="Build and test my project",
options=ClaudeAgentOptions(sandbox=sandbox_settings),
):
print(message)
Keamanan Unix socket: Opsi allowUnixSockets dapat memberikan akses ke layanan sistem yang kuat. Misalnya, mengizinkan /var/run/docker.sock secara efektif memberikan akses sistem host penuh melalui API Docker, melewati isolasi sandbox. Hanya izinkan Unix sockets yang benar-benar diperlukan dan pahami implikasi keamanan dari masing-masing.
SandboxNetworkConfig
Konfigurasi spesifik jaringan untuk mode sandbox.
class SandboxNetworkConfig(TypedDict, total=False):
allowedDomains: list[str]
deniedDomains: list[str]
allowManagedDomainsOnly: bool
allowUnixSockets: list[str]
allowAllUnixSockets: bool
allowLocalBinding: bool
allowMachLookup: list[str]
httpProxyPort: int
socksProxyPort: int
| Properti | Tipe | Default | Deskripsi |
|---|---|---|---|
allowedDomains |
list[str] |
[] |
Nama domain yang dapat diakses oleh proses dalam sandbox |
deniedDomains |
list[str] |
[] |
Nama domain yang tidak dapat diakses oleh proses dalam sandbox. Mengambil prioritas atas allowedDomains |
allowManagedDomainsOnly |
bool |
False |
Hanya pengaturan terkelola: ketika diatur dalam pengaturan terkelola, abaikan allowedDomains dari sumber pengaturan non-terkelola. Tidak berpengaruh ketika diatur melalui opsi SDK |
allowUnixSockets |
list[str] |
[] |
Jalur Unix socket yang dapat diakses proses (misalnya, Docker socket) |
allowAllUnixSockets |
bool |
False |
Izinkan akses ke semua Unix socket |
allowLocalBinding |
bool |
False |
Izinkan proses untuk mengikat ke port lokal (misalnya, untuk dev server) |
allowMachLookup |
list[str] |
[] |
Hanya macOS: nama layanan XPC/Mach yang diizinkan. Mendukung wildcard di akhir |
httpProxyPort |
int |
None |
Port proxy HTTP untuk permintaan jaringan |
socksProxyPort |
int |
None |
Port proxy SOCKS untuk permintaan jaringan |
Proxy sandbox bawaan memberlakukan daftar izin jaringan berdasarkan nama host yang diminta dan tidak menghentikan atau memeriksa lalu lintas TLS, sehingga teknik seperti domain fronting dapat berpotensi melewatinya. Lihat Batasan keamanan sandboxing untuk detail dan Penyebaran aman untuk mengonfigurasi proxy yang menghentikan TLS.
SandboxIgnoreViolations
Konfigurasi untuk mengabaikan pelanggaran sandbox tertentu.
class SandboxIgnoreViolations(TypedDict, total=False):
file: list[str]
network: list[str]
| Properti | Tipe | Default | Deskripsi |
|---|---|---|---|
file |
list[str] |
[] |
Pola jalur file untuk mengabaikan pelanggaran |
network |
list[str] |
[] |
Pola jaringan untuk mengabaikan pelanggaran |
Fallback Izin untuk Perintah Tanpa Sandbox
Ketika allowUnsandboxedCommands diaktifkan, model dapat meminta untuk menjalankan perintah di luar sandbox dengan mengatur dangerouslyDisableSandbox: True dalam input tool. Permintaan ini jatuh kembali ke sistem izin yang ada, berarti handler can_use_tool Anda akan dipanggil, memungkinkan Anda menerapkan logika otorisasi kustom.
excludedCommands vs allowUnsandboxedCommands:
excludedCommands: Daftar statis perintah yang selalu melewati sandbox secara otomatis (misalnya,["docker"]). Model tidak memiliki kontrol atas ini.allowUnsandboxedCommands: Memungkinkan model memutuskan saat runtime apakah akan meminta eksekusi tanpa sandbox dengan mengaturdangerouslyDisableSandbox: Truedalam input tool.
from claude_agent_sdk import (
query,
ClaudeAgentOptions,
HookMatcher,
PermissionResultAllow,
PermissionResultDeny,
ToolPermissionContext,
)
async def can_use_tool(
tool: str, input: dict, context: ToolPermissionContext
) -> PermissionResultAllow | PermissionResultDeny:
# Check if the model is requesting to bypass the sandbox
if tool == "Bash" and input.get("dangerouslyDisableSandbox"):
# The model is requesting to run this command outside the sandbox
print(f"Unsandboxed command requested: {input.get('command')}")
if is_command_authorized(input.get("command")):
return PermissionResultAllow()
return PermissionResultDeny(
message="Command not authorized for unsandboxed execution"
)
return PermissionResultAllow()
# Required: dummy hook keeps the stream open for can_use_tool
async def dummy_hook(input_data, tool_use_id, context):
return {"continue_": True}
async def prompt_stream():
yield {
"type": "user",
"message": {"role": "user", "content": "Deploy my application"},
}
async def main():
async for message in query(
prompt=prompt_stream(),
options=ClaudeAgentOptions(
sandbox={
"enabled": True,
"allowUnsandboxedCommands": True, # Model can request unsandboxed execution
},
permission_mode="default",
can_use_tool=can_use_tool,
hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]},
),
):
print(message)
Pola ini memungkinkan Anda untuk:
- Audit permintaan model: Catat ketika model meminta eksekusi tanpa sandbox
- Implementasikan allowlist: Hanya izinkan perintah tertentu untuk berjalan tanpa sandbox
- Tambahkan alur persetujuan: Memerlukan otorisasi eksplisit untuk operasi istimewa
Perintah yang berjalan dengan dangerouslyDisableSandbox: True memiliki akses sistem penuh. Pastikan handler can_use_tool Anda memvalidasi permintaan ini dengan hati-hati.
Jika permission_mode diatur ke bypassPermissions dan allow_unsandboxed_commands diaktifkan, model dapat secara otonom menjalankan perintah di luar sandbox tanpa prompt persetujuan apa pun. Kombinasi ini secara efektif memungkinkan model untuk melarikan diri dari isolasi sandbox secara diam-diam.
Lihat juga
- SDK overview - Konsep SDK umum
- TypeScript SDK reference - Dokumentasi SDK TypeScript
- CLI reference - Antarmuka baris perintah
- Common workflows - Panduan langkah demi langkah