1> ## Documentation Index
2> Fetch the complete documentation index at: https://code.claude.com/docs/llms.txt
3> Use this file to discover all available pages before exploring further.
4
5# Referensi Agent SDK - Python
6
7> Referensi API lengkap untuk Python Agent SDK, termasuk semua fungsi, tipe, dan kelas.
8
9## Instalasi
10
11```bash theme={null}
12pip install claude-agent-sdk
13```
14
15## Memilih antara `query()` dan `ClaudeSDKClient`
16
17Python SDK menyediakan dua cara untuk berinteraksi dengan Claude Code:
18
19### Perbandingan cepat
20
21| Fitur | `query()` | `ClaudeSDKClient` |
22| :------------------ | :---------------------------- | :------------------------------------------ |
23| **Sesi** | Membuat sesi baru setiap kali | Menggunakan kembali sesi yang sama |
24| **Percakapan** | Pertukaran tunggal | Beberapa pertukaran dalam konteks yang sama |
25| **Koneksi** | Dikelola secara otomatis | Kontrol manual |
26| **Streaming Input** | ✅ Didukung | ✅ Didukung |
27| **Interrupts** | ❌ Tidak didukung | ✅ Didukung |
28| **Hooks** | ✅ Didukung | ✅ Didukung |
29| **Custom Tools** | ✅ Didukung | ✅ Didukung |
30| **Continue Chat** | ❌ Sesi baru setiap kali | ✅ Mempertahankan percakapan |
31| **Use Case** | Tugas sekali jalan | Percakapan berkelanjutan |
32
33### Kapan menggunakan `query()` (sesi baru setiap kali)
34
35**Terbaik untuk:**
36
37* Pertanyaan sekali jalan di mana Anda tidak memerlukan riwayat percakapan
38* Tugas independen yang tidak memerlukan konteks dari pertukaran sebelumnya
39* Skrip otomasi sederhana
40* Ketika Anda menginginkan awal yang segar setiap kali
41
42### Kapan menggunakan `ClaudeSDKClient` (percakapan berkelanjutan)
43
44**Terbaik untuk:**
45
46* **Melanjutkan percakapan** - Ketika Anda memerlukan Claude untuk mengingat konteks
47* **Pertanyaan lanjutan** - Membangun berdasarkan respons sebelumnya
48* **Aplikasi interaktif** - Antarmuka obrolan, REPL
49* **Logika berbasis respons** - Ketika tindakan berikutnya bergantung pada respons Claude
50* **Kontrol sesi** - Mengelola siklus hidup percakapan secara eksplisit
51
52## Fungsi
53
54### `query()`
55
56Membuat 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.
57
58```python theme={null}
59async def query(
60 *,
61 prompt: str | AsyncIterable[dict[str, Any]],
62 options: ClaudeAgentOptions | None = None,
63 transport: Transport | None = None
64) -> AsyncIterator[Message]
65```
66
67#### Parameter
68
69| Parameter | Tipe | Deskripsi |
70| :---------- | :--------------------------- | :----------------------------------------------------------------------- |
71| `prompt` | `str \| AsyncIterable[dict]` | Prompt input sebagai string atau async iterable untuk mode streaming |
72| `options` | `ClaudeAgentOptions \| None` | Objek konfigurasi opsional (default ke `ClaudeAgentOptions()` jika None) |
73| `transport` | `Transport \| None` | Transport kustom opsional untuk berkomunikasi dengan proses CLI |
74
75#### Pengembalian
76
77Mengembalikan `AsyncIterator[Message]` yang menghasilkan pesan dari percakapan.
78
79#### Contoh - Dengan opsi
80
81```python theme={null}
82import asyncio
83from claude_agent_sdk import query, ClaudeAgentOptions
84
85
86async def main():
87 options = ClaudeAgentOptions(
88 system_prompt="You are an expert Python developer",
89 permission_mode="acceptEdits",
90 cwd="/home/user/project",
91 )
92
93 async for message in query(prompt="Create a Python web server", options=options):
94 print(message)
95
96
97asyncio.run(main())
98```
99
100### `tool()`
101
102Dekorator untuk mendefinisikan tools MCP dengan keamanan tipe.
103
104```python theme={null}
105def tool(
106 name: str,
107 description: str,
108 input_schema: type | dict[str, Any],
109 annotations: ToolAnnotations | None = None
110) -> Callable[[Callable[[Any], Awaitable[dict[str, Any]]]], SdkMcpTool[Any]]
111```
112
113#### Parameter
114
115| Parameter | Tipe | Deskripsi |
116| :------------- | :----------------------------------------------- | :----------------------------------------------------------------------- |
117| `name` | `str` | Pengenal unik untuk tool |
118| `description` | `str` | Deskripsi yang dapat dibaca manusia tentang apa yang dilakukan tool |
119| `input_schema` | `type \| dict[str, Any]` | Skema yang mendefinisikan parameter input tool (lihat di bawah) |
120| `annotations` | [`ToolAnnotations`](#tool-annotations)` \| None` | Anotasi tool MCP opsional yang memberikan petunjuk perilaku kepada klien |
121
122#### Opsi skema input
123
1241. **Pemetaan tipe sederhana** (direkomendasikan):
125
126 ```python theme={null}
127 {"text": str, "count": int, "enabled": bool}
128 ```
129
1302. **Format JSON Schema** (untuk validasi kompleks):
131 ```python theme={null}
132 {
133 "type": "object",
134 "properties": {
135 "text": {"type": "string"},
136 "count": {"type": "integer", "minimum": 0},
137 },
138 "required": ["text"],
139 }
140 ```
141
142#### Pengembalian
143
144Fungsi dekorator yang membungkus implementasi tool dan mengembalikan instance `SdkMcpTool`.
145
146#### Contoh
147
148```python theme={null}
149from claude_agent_sdk import tool
150from typing import Any
151
152
153@tool("greet", "Greet a user", {"name": str})
154async def greet(args: dict[str, Any]) -> dict[str, Any]:
155 return {"content": [{"type": "text", "text": f"Hello, {args['name']}!"}]}
156```
157
158#### `ToolAnnotations`
159
160Diimpor 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.
161
162| Field | Tipe | Default | Deskripsi |
163| :---------------- | :------------- | :------ | :------------------------------------------------------------------------------------------------------------------------------------------- |
164| `title` | `str \| None` | `None` | Judul yang dapat dibaca manusia untuk tool |
165| `readOnlyHint` | `bool \| None` | `False` | Jika `True`, tool tidak memodifikasi lingkungannya |
166| `destructiveHint` | `bool \| None` | `True` | Jika `True`, tool dapat melakukan pembaruan destruktif (hanya bermakna ketika `readOnlyHint` adalah `False`) |
167| `idempotentHint` | `bool \| None` | `False` | Jika `True`, panggilan berulang dengan argumen yang sama tidak memiliki efek tambahan (hanya bermakna ketika `readOnlyHint` adalah `False`) |
168| `openWorldHint` | `bool \| None` | `True` | Jika `True`, tool berinteraksi dengan entitas eksternal (misalnya, pencarian web). Jika `False`, domain tool ditutup (misalnya, tool memori) |
169
170```python theme={null}
171from claude_agent_sdk import tool, ToolAnnotations
172from typing import Any
173
174
175@tool(
176 "search",
177 "Search the web",
178 {"query": str},
179 annotations=ToolAnnotations(readOnlyHint=True, openWorldHint=True),
180)
181async def search(args: dict[str, Any]) -> dict[str, Any]:
182 return {"content": [{"type": "text", "text": f"Results for: {args['query']}"}]}
183```
184
185### `create_sdk_mcp_server()`
186
187Buat server MCP dalam proses yang berjalan dalam aplikasi Python Anda.
188
189```python theme={null}
190def create_sdk_mcp_server(
191 name: str,
192 version: str = "1.0.0",
193 tools: list[SdkMcpTool[Any]] | None = None
194) -> McpSdkServerConfig
195```
196
197#### Parameter
198
199| Parameter | Tipe | Default | Deskripsi |
200| :-------- | :------------------------------ | :-------- | :------------------------------------------------------ |
201| `name` | `str` | - | Pengenal unik untuk server |
202| `version` | `str` | `"1.0.0"` | String versi server |
203| `tools` | `list[SdkMcpTool[Any]] \| None` | `None` | Daftar fungsi tool yang dibuat dengan dekorator `@tool` |
204
205#### Pengembalian
206
207Mengembalikan objek `McpSdkServerConfig` yang dapat diteruskan ke `ClaudeAgentOptions.mcp_servers`.
208
209#### Contoh
210
211```python theme={null}
212from claude_agent_sdk import tool, create_sdk_mcp_server
213
214
215@tool("add", "Add two numbers", {"a": float, "b": float})
216async def add(args):
217 return {"content": [{"type": "text", "text": f"Sum: {args['a'] + args['b']}"}]}
218
219
220@tool("multiply", "Multiply two numbers", {"a": float, "b": float})
221async def multiply(args):
222 return {"content": [{"type": "text", "text": f"Product: {args['a'] * args['b']}"}]}
223
224
225calculator = create_sdk_mcp_server(
226 name="calculator",
227 version="2.0.0",
228 tools=[add, multiply], # Pass decorated functions
229)
230
231# Use with Claude
232options = ClaudeAgentOptions(
233 mcp_servers={"calc": calculator},
234 allowed_tools=["mcp__calc__add", "mcp__calc__multiply"],
235)
236```
237
238### `list_sessions()`
239
240Mencantumkan sesi masa lalu dengan metadata. Filter berdasarkan direktori proyek atau cantumkan sesi di semua proyek. Sinkron; mengembalikan segera.
241
242```python theme={null}
243def list_sessions(
244 directory: str | None = None,
245 limit: int | None = None,
246 include_worktrees: bool = True
247) -> list[SDKSessionInfo]
248```
249
250#### Parameter
251
252| Parameter | Tipe | Default | Deskripsi |
253| :------------------ | :------------ | :------ | :----------------------------------------------------------------------------------------- |
254| `directory` | `str \| None` | `None` | Direktori untuk mencantumkan sesi. Ketika dihilangkan, mengembalikan sesi di semua proyek |
255| `limit` | `int \| None` | `None` | Jumlah maksimal sesi yang akan dikembalikan |
256| `include_worktrees` | `bool` | `True` | Ketika `directory` berada di dalam repositori git, sertakan sesi dari semua jalur worktree |
257
258#### Tipe pengembalian: `SDKSessionInfo`
259
260| Properti | Tipe | Deskripsi |
261| :-------------- | :------------ | :------------------------------------------------------------------------------------ |
262| `session_id` | `str` | Pengenal sesi unik |
263| `summary` | `str` | Judul tampilan: judul kustom, ringkasan yang dihasilkan otomatis, atau prompt pertama |
264| `last_modified` | `int` | Waktu modifikasi terakhir dalam milidetik sejak epoch |
265| `file_size` | `int \| None` | Ukuran file sesi dalam byte (`None` untuk backend penyimpanan jarak jauh) |
266| `custom_title` | `str \| None` | Judul sesi yang ditetapkan pengguna |
267| `first_prompt` | `str \| None` | Prompt pengguna bermakna pertama dalam sesi |
268| `git_branch` | `str \| None` | Cabang Git di akhir sesi |
269| `cwd` | `str \| None` | Direktori kerja untuk sesi |
270| `tag` | `str \| None` | Tag sesi yang ditetapkan pengguna (lihat [`tag_session()`](#tag-session)) |
271| `created_at` | `int \| None` | Waktu pembuatan sesi dalam milidetik sejak epoch |
272
273#### Contoh
274
275Cetak 10 sesi terbaru untuk proyek. Hasil diurutkan berdasarkan `last_modified` menurun, jadi item pertama adalah yang terbaru. Hilangkan `directory` untuk mencari di semua proyek.
276
277```python theme={null}
278from claude_agent_sdk import list_sessions
279
280for session in list_sessions(directory="/path/to/project", limit=10):
281 print(f"{session.summary} ({session.session_id})")
282```
283
284### `get_session_messages()`
285
286Mengambil pesan dari sesi masa lalu. Sinkron; mengembalikan segera.
287
288```python theme={null}
289def get_session_messages(
290 session_id: str,
291 directory: str | None = None,
292 limit: int | None = None,
293 offset: int = 0
294) -> list[SessionMessage]
295```
296
297#### Parameter
298
299| Parameter | Tipe | Default | Deskripsi |
300| :----------- | :------------ | :--------- | :-------------------------------------------------------------------------- |
301| `session_id` | `str` | diperlukan | ID sesi untuk mengambil pesan |
302| `directory` | `str \| None` | `None` | Direktori proyek untuk dilihat. Ketika dihilangkan, mencari di semua proyek |
303| `limit` | `int \| None` | `None` | Jumlah maksimal pesan yang akan dikembalikan |
304| `offset` | `int` | `0` | Jumlah pesan yang akan dilewati dari awal |
305
306#### Tipe pengembalian: `SessionMessage`
307
308| Properti | Tipe | Deskripsi |
309| :------------------- | :----------------------------- | :----------------------------------------- |
310| `type` | `Literal["user", "assistant"]` | Peran pesan |
311| `uuid` | `str` | Pengenal pesan unik |
312| `session_id` | `str` | Pengenal sesi |
313| `message` | `Any` | Konten pesan mentah |
314| `parent_tool_use_id` | `None` | Dicadangkan untuk penggunaan di masa depan |
315
316#### Contoh
317
318```python theme={null}
319from claude_agent_sdk import list_sessions, get_session_messages
320
321sessions = list_sessions(limit=1)
322if sessions:
323 messages = get_session_messages(sessions[0].session_id)
324 for msg in messages:
325 print(f"[{msg.type}] {msg.uuid}")
326```
327
328### `get_session_info()`
329
330Membaca metadata untuk sesi tunggal berdasarkan ID tanpa memindai direktori proyek lengkap. Sinkron; mengembalikan segera.
331
332```python theme={null}
333def get_session_info(
334 session_id: str,
335 directory: str | None = None,
336) -> SDKSessionInfo | None
337```
338
339#### Parameter
340
341| Parameter | Tipe | Default | Deskripsi |
342| :----------- | :------------ | :--------- | :---------------------------------------------------------------------------- |
343| `session_id` | `str` | diperlukan | UUID sesi untuk dicari |
344| `directory` | `str \| None` | `None` | Jalur direktori proyek. Ketika dihilangkan, mencari di semua direktori proyek |
345
346Mengembalikan [`SDKSessionInfo`](#return-type-sdk-session-info), atau `None` jika sesi tidak ditemukan.
347
348#### Contoh
349
350Cari metadata sesi tunggal tanpa memindai direktori proyek. Berguna ketika Anda sudah memiliki ID sesi dari run sebelumnya.
351
352```python theme={null}
353from claude_agent_sdk import get_session_info
354
355info = get_session_info("550e8400-e29b-41d4-a716-446655440000")
356if info:
357 print(f"{info.summary} (branch: {info.git_branch}, tag: {info.tag})")
358```
359
360### `rename_session()`
361
362Mengganti nama sesi dengan menambahkan entri judul kustom. Panggilan berulang aman; judul terbaru menang. Sinkron.
363
364```python theme={null}
365def rename_session(
366 session_id: str,
367 title: str,
368 directory: str | None = None,
369) -> None
370```
371
372#### Parameter
373
374| Parameter | Tipe | Default | Deskripsi |
375| :----------- | :------------ | :--------- | :---------------------------------------------------------------------------- |
376| `session_id` | `str` | diperlukan | UUID sesi untuk diganti nama |
377| `title` | `str` | diperlukan | Judul baru. Harus tidak kosong setelah menghapus spasi putih |
378| `directory` | `str \| None` | `None` | Jalur direktori proyek. Ketika dihilangkan, mencari di semua direktori proyek |
379
380Menimbulkan `ValueError` jika `session_id` bukan UUID yang valid atau `title` kosong; `FileNotFoundError` jika sesi tidak dapat ditemukan.
381
382#### Contoh
383
384Ganti nama sesi terbaru sehingga lebih mudah ditemukan nanti. Judul baru muncul di [`SDKSessionInfo.custom_title`](#return-type-sdk-session-info) pada pembacaan berikutnya.
385
386```python theme={null}
387from claude_agent_sdk import list_sessions, rename_session
388
389sessions = list_sessions(directory="/path/to/project", limit=1)
390if sessions:
391 rename_session(sessions[0].session_id, "Refactor auth module")
392```
393
394### `tag_session()`
395
396Menandai sesi. Teruskan `None` untuk menghapus tag. Panggilan berulang aman; tag terbaru menang. Sinkron.
397
398```python theme={null}
399def tag_session(
400 session_id: str,
401 tag: str | None,
402 directory: str | None = None,
403) -> None
404```
405
406#### Parameter
407
408| Parameter | Tipe | Default | Deskripsi |
409| :----------- | :------------ | :--------- | :---------------------------------------------------------------------------- |
410| `session_id` | `str` | diperlukan | UUID sesi untuk ditandai |
411| `tag` | `str \| None` | diperlukan | String tag, atau `None` untuk menghapus. Disanitasi Unicode sebelum disimpan |
412| `directory` | `str \| None` | `None` | Jalur direktori proyek. Ketika dihilangkan, mencari di semua direktori proyek |
413
414Menimbulkan `ValueError` jika `session_id` bukan UUID yang valid atau `tag` kosong setelah sanitasi; `FileNotFoundError` jika sesi tidak dapat ditemukan.
415
416#### Contoh
417
418Tandai sesi, kemudian filter berdasarkan tag itu pada pembacaan nanti. Teruskan `None` untuk menghapus tag yang ada.
419
420```python theme={null}
421from claude_agent_sdk import list_sessions, tag_session
422
423# Tag a session
424tag_session("550e8400-e29b-41d4-a716-446655440000", "needs-review")
425
426# Later: find all sessions with that tag
427for session in list_sessions(directory="/path/to/project"):
428 if session.tag == "needs-review":
429 print(session.summary)
430```
431
432## Kelas
433
434### `ClaudeSDKClient`
435
436**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.
437
438#### Fitur Utama
439
440* **Kontinuitas sesi**: Mempertahankan konteks percakapan di beberapa panggilan `query()`
441* **Percakapan yang sama**: Sesi mempertahankan pesan sebelumnya
442* **Dukungan interrupt**: Dapat menghentikan eksekusi di tengah-tengah tugas
443* **Siklus hidup eksplisit**: Anda mengontrol kapan sesi dimulai dan berakhir
444* **Alur berbasis respons**: Dapat bereaksi terhadap respons dan mengirim tindak lanjut
445* **Tools dan hooks kustom**: Mendukung tools kustom (dibuat dengan dekorator `@tool`) dan hooks
446
447```python theme={null}
448class ClaudeSDKClient:
449 def __init__(self, options: ClaudeAgentOptions | None = None, transport: Transport | None = None)
450 async def connect(self, prompt: str | AsyncIterable[dict] | None = None) -> None
451 async def query(self, prompt: str | AsyncIterable[dict], session_id: str = "default") -> None
452 async def receive_messages(self) -> AsyncIterator[Message]
453 async def receive_response(self) -> AsyncIterator[Message]
454 async def interrupt(self) -> None
455 async def set_permission_mode(self, mode: str) -> None
456 async def set_model(self, model: str | None = None) -> None
457 async def rewind_files(self, user_message_id: str) -> None
458 async def get_mcp_status(self) -> McpStatusResponse
459 async def reconnect_mcp_server(self, server_name: str) -> None
460 async def toggle_mcp_server(self, server_name: str, enabled: bool) -> None
461 async def stop_task(self, task_id: str) -> None
462 async def get_server_info(self) -> dict[str, Any] | None
463 async def disconnect(self) -> None
464```
465
466#### Metode
467
468| Metode | Deskripsi |
469| :---------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
470| `__init__(options)` | Inisialisasi klien dengan konfigurasi opsional |
471| `connect(prompt)` | Hubungkan ke Claude dengan prompt awal opsional atau aliran pesan |
472| `query(prompt, session_id)` | Kirim permintaan baru dalam mode streaming |
473| `receive_messages()` | Terima semua pesan dari Claude sebagai async iterator |
474| `receive_response()` | Terima pesan hingga dan termasuk ResultMessage |
475| `interrupt()` | Kirim sinyal interrupt (hanya bekerja dalam mode streaming) |
476| `set_permission_mode(mode)` | Ubah mode izin untuk sesi saat ini |
477| `set_model(model)` | Ubah model untuk sesi saat ini. Teruskan `None` untuk reset ke default |
478| `rewind_files(user_message_id)` | Pulihkan file ke keadaan mereka pada pesan pengguna yang ditentukan. Memerlukan `enable_file_checkpointing=True`. Lihat [File checkpointing](/id/agent-sdk/file-checkpointing) |
479| `get_mcp_status()` | Dapatkan status semua server MCP yang dikonfigurasi. Mengembalikan [`McpStatusResponse`](#mcp-status-response) |
480| `reconnect_mcp_server(server_name)` | Coba lagi menghubungkan ke server MCP yang gagal atau terputus |
481| `toggle_mcp_server(server_name, enabled)` | Aktifkan atau nonaktifkan server MCP di tengah sesi. Menonaktifkan menghapus toolnya |
482| `stop_task(task_id)` | Hentikan tugas latar belakang yang sedang berjalan. [`TaskNotificationMessage`](#task-notification-message) dengan status `"stopped"` mengikuti dalam aliran pesan |
483| `get_server_info()` | Dapatkan informasi server termasuk ID sesi dan kemampuan |
484| `disconnect()` | Putuskan sambungan dari Claude |
485
486#### Dukungan Context Manager
487
488Klien dapat digunakan sebagai async context manager untuk manajemen koneksi otomatis:
489
490```python theme={null}
491async with ClaudeSDKClient() as client:
492 await client.query("Hello Claude")
493 async for message in client.receive_response():
494 print(message)
495```
496
497> **Penting:** Saat mengulangi pesan, hindari menggunakan `break` untuk 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.
498
499#### Contoh - Melanjutkan percakapan
500
501```python theme={null}
502import asyncio
503from claude_agent_sdk import ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage
504
505
506async def main():
507 async with ClaudeSDKClient() as client:
508 # First question
509 await client.query("What's the capital of France?")
510
511 # Process response
512 async for message in client.receive_response():
513 if isinstance(message, AssistantMessage):
514 for block in message.content:
515 if isinstance(block, TextBlock):
516 print(f"Claude: {block.text}")
517
518 # Follow-up question - the session retains the previous context
519 await client.query("What's the population of that city?")
520
521 async for message in client.receive_response():
522 if isinstance(message, AssistantMessage):
523 for block in message.content:
524 if isinstance(block, TextBlock):
525 print(f"Claude: {block.text}")
526
527 # Another follow-up - still in the same conversation
528 await client.query("What are some famous landmarks there?")
529
530 async for message in client.receive_response():
531 if isinstance(message, AssistantMessage):
532 for block in message.content:
533 if isinstance(block, TextBlock):
534 print(f"Claude: {block.text}")
535
536
537asyncio.run(main())
538```
539
540#### Contoh - Streaming input dengan ClaudeSDKClient
541
542```python theme={null}
543import asyncio
544from claude_agent_sdk import ClaudeSDKClient
545
546
547async def message_stream():
548 """Generate messages dynamically."""
549 yield {
550 "type": "user",
551 "message": {"role": "user", "content": "Analyze the following data:"},
552 }
553 await asyncio.sleep(0.5)
554 yield {
555 "type": "user",
556 "message": {"role": "user", "content": "Temperature: 25°C, Humidity: 60%"},
557 }
558 await asyncio.sleep(0.5)
559 yield {
560 "type": "user",
561 "message": {"role": "user", "content": "What patterns do you see?"},
562 }
563
564
565async def main():
566 async with ClaudeSDKClient() as client:
567 # Stream input to Claude
568 await client.query(message_stream())
569
570 # Process response
571 async for message in client.receive_response():
572 print(message)
573
574 # Follow-up in same session
575 await client.query("Should we be concerned about these readings?")
576
577 async for message in client.receive_response():
578 print(message)
579
580
581asyncio.run(main())
582```
583
584#### Contoh - Menggunakan interrupts
585
586```python theme={null}
587import asyncio
588from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, ResultMessage
589
590
591async def interruptible_task():
592 options = ClaudeAgentOptions(allowed_tools=["Bash"], permission_mode="acceptEdits")
593
594 async with ClaudeSDKClient(options=options) as client:
595 # Start a long-running task
596 await client.query("Count from 1 to 100 slowly, using the bash sleep command")
597
598 # Let it run for a bit
599 await asyncio.sleep(2)
600
601 # Interrupt the task
602 await client.interrupt()
603 print("Task interrupted!")
604
605 # Drain the interrupted task's messages (including its ResultMessage)
606 async for message in client.receive_response():
607 if isinstance(message, ResultMessage):
608 print(f"Interrupted task finished with subtype={message.subtype!r}")
609 # subtype is "error_during_execution" for interrupted tasks
610
611 # Send a new command
612 await client.query("Just say hello instead")
613
614 # Now receive the new response
615 async for message in client.receive_response():
616 if isinstance(message, ResultMessage) and message.subtype == "success":
617 print(f"New result: {message.result}")
618
619
620asyncio.run(interruptible_task())
621```
622
623<Note>
624 **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.
625</Note>
626
627#### Contoh - Kontrol izin lanjutan
628
629```python theme={null}
630from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
631from claude_agent_sdk.types import (
632 PermissionResultAllow,
633 PermissionResultDeny,
634 ToolPermissionContext,
635)
636
637
638async def custom_permission_handler(
639 tool_name: str, input_data: dict, context: ToolPermissionContext
640) -> PermissionResultAllow | PermissionResultDeny:
641 """Custom logic for tool permissions."""
642
643 # Block writes to system directories
644 if tool_name == "Write" and input_data.get("file_path", "").startswith("/system/"):
645 return PermissionResultDeny(
646 message="System directory write not allowed", interrupt=True
647 )
648
649 # Redirect sensitive file operations
650 if tool_name in ["Write", "Edit"] and "config" in input_data.get("file_path", ""):
651 safe_path = f"./sandbox/{input_data['file_path']}"
652 return PermissionResultAllow(
653 updated_input={**input_data, "file_path": safe_path}
654 )
655
656 # Allow everything else
657 return PermissionResultAllow(updated_input=input_data)
658
659
660async def main():
661 options = ClaudeAgentOptions(
662 can_use_tool=custom_permission_handler, allowed_tools=["Read", "Write", "Edit"]
663 )
664
665 async with ClaudeSDKClient(options=options) as client:
666 await client.query("Update the system config file")
667
668 async for message in client.receive_response():
669 # Will use sandbox path instead
670 print(message)
671
672
673asyncio.run(main())
674```
675
676## Tipe
677
678<Note>
679 **`@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.
680</Note>
681
682### `SdkMcpTool`
683
684Definisi untuk tool SDK MCP yang dibuat dengan dekorator `@tool`.
685
686```python theme={null}
687@dataclass
688class SdkMcpTool(Generic[T]):
689 name: str
690 description: str
691 input_schema: type[T] | dict[str, Any]
692 handler: Callable[[T], Awaitable[dict[str, Any]]]
693 annotations: ToolAnnotations | None = None
694```
695
696| Properti | Tipe | Deskripsi |
697| :------------- | :----------------------------------------- | :--------------------------------------------------------------------------------------------------------- |
698| `name` | `str` | Pengenal unik untuk tool |
699| `description` | `str` | Deskripsi yang dapat dibaca manusia |
700| `input_schema` | `type[T] \| dict[str, Any]` | Skema untuk validasi input |
701| `handler` | `Callable[[T], Awaitable[dict[str, Any]]]` | Fungsi async yang menangani eksekusi tool |
702| `annotations` | `ToolAnnotations \| None` | Anotasi tool MCP opsional (misalnya, `readOnlyHint`, `destructiveHint`, `openWorldHint`). Dari `mcp.types` |
703
704### `Transport`
705
706Kelas dasar abstrak untuk implementasi transport kustom. Gunakan ini untuk berkomunikasi dengan proses Claude melalui saluran kustom (misalnya, koneksi jarak jauh alih-alih subprocess lokal).
707
708<Warning>
709 Ini adalah API internal tingkat rendah. Antarmuka dapat berubah di rilis mendatang. Implementasi kustom harus diperbarui agar sesuai dengan perubahan antarmuka apa pun.
710</Warning>
711
712```python theme={null}
713from abc import ABC, abstractmethod
714from collections.abc import AsyncIterator
715from typing import Any
716
717
718class Transport(ABC):
719 @abstractmethod
720 async def connect(self) -> None: ...
721
722 @abstractmethod
723 async def write(self, data: str) -> None: ...
724
725 @abstractmethod
726 def read_messages(self) -> AsyncIterator[dict[str, Any]]: ...
727
728 @abstractmethod
729 async def close(self) -> None: ...
730
731 @abstractmethod
732 def is_ready(self) -> bool: ...
733
734 @abstractmethod
735 async def end_input(self) -> None: ...
736```
737
738| Metode | Deskripsi |
739| :---------------- | :-------------------------------------------------------------------- |
740| `connect()` | Hubungkan transport dan siapkan untuk komunikasi |
741| `write(data)` | Tulis data mentah (JSON + newline) ke transport |
742| `read_messages()` | Async iterator yang menghasilkan pesan JSON yang diuraikan |
743| `close()` | Tutup koneksi dan bersihkan sumber daya |
744| `is_ready()` | Mengembalikan `True` jika transport dapat mengirim dan menerima |
745| `end_input()` | Tutup aliran input (misalnya, tutup stdin untuk transport subprocess) |
746
747Impor: `from claude_agent_sdk import Transport`
748
749### `ClaudeAgentOptions`
750
751Dataclass konfigurasi untuk query Claude Code.
752
753```python theme={null}
754@dataclass
755class ClaudeAgentOptions:
756 tools: list[str] | ToolsPreset | None = None
757 allowed_tools: list[str] = field(default_factory=list)
758 system_prompt: str | SystemPromptPreset | None = None
759 mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)
760 permission_mode: PermissionMode | None = None
761 continue_conversation: bool = False
762 resume: str | None = None
763 max_turns: int | None = None
764 max_budget_usd: float | None = None
765 disallowed_tools: list[str] = field(default_factory=list)
766 model: str | None = None
767 fallback_model: str | None = None
768 betas: list[SdkBeta] = field(default_factory=list)
769 output_format: dict[str, Any] | None = None
770 permission_prompt_tool_name: str | None = None
771 cwd: str | Path | None = None
772 cli_path: str | Path | None = None
773 settings: str | None = None
774 add_dirs: list[str | Path] = field(default_factory=list)
775 env: dict[str, str] = field(default_factory=dict)
776 extra_args: dict[str, str | None] = field(default_factory=dict)
777 max_buffer_size: int | None = None
778 debug_stderr: Any = sys.stderr # Deprecated
779 stderr: Callable[[str], None] | None = None
780 can_use_tool: CanUseTool | None = None
781 hooks: dict[HookEvent, list[HookMatcher]] | None = None
782 user: str | None = None
783 include_partial_messages: bool = False
784 fork_session: bool = False
785 agents: dict[str, AgentDefinition] | None = None
786 setting_sources: list[SettingSource] | None = None
787 sandbox: SandboxSettings | None = None
788 plugins: list[SdkPluginConfig] = field(default_factory=list)
789 max_thinking_tokens: int | None = None # Deprecated: use thinking instead
790 thinking: ThinkingConfig | None = None
791 effort: Literal["low", "medium", "high", "max"] | None = None
792 enable_file_checkpointing: bool = False
793 session_store: SessionStore | None = None
794```
795
796| Properti | Tipe | Default | Deskripsi |
797| :---------------------------- | :------------------------------------------------------------------------------------- | :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
798| `tools` | `list[str] \| ToolsPreset \| None` | `None` | Konfigurasi tools. Gunakan `{"type": "preset", "preset": "claude_code"}` untuk tools default Claude Code |
799| `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](/id/agent-sdk/permissions#allow-and-deny-rules) |
800| `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 |
801| `mcp_servers` | `dict[str, McpServerConfig] \| str \| Path` | `{}` | Konfigurasi server MCP atau jalur ke file konfigurasi |
802| `permission_mode` | `PermissionMode \| None` | `None` | Mode izin untuk penggunaan tool |
803| `continue_conversation` | `bool` | `False` | Lanjutkan percakapan terbaru |
804| `resume` | `str \| None` | `None` | ID sesi untuk dilanjutkan |
805| `max_turns` | `int \| None` | `None` | Jumlah maksimal putaran agentic (round trip penggunaan tool) |
806| `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](/id/agent-sdk/cost-tracking) untuk peringatan akurasi |
807| `disallowed_tools` | `list[str]` | `[]` | Tools untuk selalu ditolak. Aturan penolakan diperiksa terlebih dahulu dan mengganti `allowed_tools` dan `permission_mode` (termasuk `bypassPermissions`) |
808| `enable_file_checkpointing` | `bool` | `False` | Aktifkan pelacakan perubahan file untuk rewinding. Lihat [File checkpointing](/id/agent-sdk/file-checkpointing) |
809| `model` | `str \| None` | `None` | Model Claude yang akan digunakan |
810| `fallback_model` | `str \| None` | `None` | Model fallback yang akan digunakan jika model utama gagal |
811| `betas` | `list[SdkBeta]` | `[]` | Fitur beta untuk diaktifkan. Lihat [`SdkBeta`](#sdk-beta) untuk opsi yang tersedia |
812| `output_format` | `dict[str, Any] \| None` | `None` | Format output untuk respons terstruktur (misalnya, `{"type": "json_schema", "schema": {...}}`). Lihat [Structured outputs](/id/agent-sdk/structured-outputs) untuk detail |
813| `permission_prompt_tool_name` | `str \| None` | `None` | Nama tool MCP untuk prompt izin |
814| `cwd` | `str \| Path \| None` | `None` | Direktori kerja saat ini |
815| `cli_path` | `str \| Path \| None` | `None` | Jalur kustom ke executable CLI Claude Code |
816| `settings` | `str \| None` | `None` | Jalur ke file pengaturan |
817| `add_dirs` | `list[str \| Path]` | `[]` | Direktori tambahan yang dapat diakses Claude |
818| `env` | `dict[str, str]` | `{}` | Variabel lingkungan yang digabungkan di atas lingkungan proses yang diwarisi. Lihat [Environment variables](/id/env-vars) untuk variabel yang dibaca CLI yang mendasar |
819| `extra_args` | `dict[str, str \| None]` | `{}` | Argumen CLI tambahan untuk diteruskan langsung ke CLI |
820| `max_buffer_size` | `int \| None` | `None` | Byte maksimal saat membuffer stdout CLI |
821| `debug_stderr` | `Any` | `sys.stderr` | *Deprecated* - Objek seperti file untuk output debug. Gunakan callback `stderr` sebagai gantinya |
822| `stderr` | `Callable[[str], None] \| None` | `None` | Fungsi callback untuk output stderr dari CLI |
823| `can_use_tool` | [`CanUseTool`](#can-use-tool) ` \| None` | `None` | Fungsi callback izin tool. Lihat [Permission types](#can-use-tool) untuk detail |
824| `hooks` | `dict[HookEvent, list[HookMatcher]] \| None` | `None` | Konfigurasi hook untuk mengintersepsi event |
825| `user` | `str \| None` | `None` | Pengenal pengguna |
826| `include_partial_messages` | `bool` | `False` | Sertakan event streaming pesan parsial. Ketika diaktifkan, pesan [`StreamEvent`](#stream-event) dihasilkan |
827| `fork_session` | `bool` | `False` | Ketika melanjutkan dengan `resume`, fork ke ID sesi baru alih-alih melanjutkan sesi asli |
828| `agents` | `dict[str, AgentDefinition] \| None` | `None` | Subagent yang didefinisikan secara programatis |
829| `plugins` | `list[SdkPluginConfig]` | `[]` | Muat plugin kustom dari jalur lokal. Lihat [Plugins](/id/agent-sdk/plugins) untuk detail |
830| `sandbox` | [`SandboxSettings`](#sandbox-settings) ` \| None` | `None` | Konfigurasi perilaku sandbox secara programatis. Lihat [Sandbox settings](#sandbox-settings) untuk detail |
831| `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](/id/agent-sdk/claude-code-features#what-settingsources-does-not-control) |
832| `max_thinking_tokens` | `int \| None` | `None` | *Deprecated* - Token maksimal untuk blok thinking. Gunakan `thinking` sebagai gantinya |
833| `thinking` | [`ThinkingConfig`](#thinking-config) ` \| None` | `None` | Mengontrol perilaku extended thinking. Mengambil prioritas atas `max_thinking_tokens` |
834| `effort` | `Literal["low", "medium", "high", "max"] \| None` | `None` | Tingkat usaha untuk kedalaman thinking |
835| `session_store` | [`SessionStore`](/id/agent-sdk/session-storage#the-session-store-interface) ` \| None` | `None` | Cerminkan transkrip sesi ke backend eksternal sehingga host apa pun dapat melanjutkannya. Lihat [Persist sessions to external storage](/id/agent-sdk/session-storage) |
836
837### `OutputFormat`
838
839Konfigurasi untuk validasi output terstruktur. Teruskan ini sebagai `dict` ke field `output_format` pada `ClaudeAgentOptions`:
840
841```python theme={null}
842# Expected dict shape for output_format
843{
844 "type": "json_schema",
845 "schema": {...}, # Your JSON Schema definition
846}
847```
848
849| Field | Diperlukan | Deskripsi |
850| :------- | :--------- | :----------------------------------------------- |
851| `type` | Ya | Harus `"json_schema"` untuk validasi JSON Schema |
852| `schema` | Ya | Definisi JSON Schema untuk validasi output |
853
854### `SystemPromptPreset`
855
856Konfigurasi untuk menggunakan preset system prompt Claude Code dengan penambahan opsional.
857
858```python theme={null}
859class SystemPromptPreset(TypedDict):
860 type: Literal["preset"]
861 preset: Literal["claude_code"]
862 append: NotRequired[str]
863 exclude_dynamic_sections: NotRequired[bool]
864```
865
866| Field | Diperlukan | Deskripsi |
867| :------------------------- | :--------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
868| `type` | Ya | Harus `"preset"` untuk menggunakan preset system prompt |
869| `preset` | Ya | Harus `"claude_code"` untuk menggunakan system prompt Claude Code |
870| `append` | Tidak | Instruksi tambahan untuk ditambahkan ke preset system prompt |
871| `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](/id/agent-sdk/modifying-system-prompts#improve-prompt-caching-across-users-and-machines) |
872
873### `SettingSource`
874
875Mengontrol sumber konfigurasi berbasis filesystem mana yang dimuat pengaturan SDK.
876
877```python theme={null}
878SettingSource = Literal["user", "project", "local"]
879```
880
881| Nilai | Deskripsi | Lokasi |
882| :---------- | :--------------------------------------------- | :---------------------------- |
883| `"user"` | Pengaturan pengguna global | `~/.claude/settings.json` |
884| `"project"` | Pengaturan proyek bersama (version controlled) | `.claude/settings.json` |
885| `"local"` | Pengaturan proyek lokal (gitignored) | `.claude/settings.local.json` |
886
887#### Perilaku default
888
889Ketika `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](/id/agent-sdk/claude-code-features#what-settingsources-does-not-control) untuk input yang dibaca terlepas dari opsi ini, dan cara menonaktifkannya.
890
891#### Mengapa menggunakan setting\_sources
892
893**Nonaktifkan pengaturan filesystem:**
894
895```python theme={null}
896# Do not load user, project, or local settings from disk
897from claude_agent_sdk import query, ClaudeAgentOptions
898
899async for message in query(
900 prompt="Analyze this code",
901 options=ClaudeAgentOptions(
902 setting_sources=[]
903 ),
904):
905 print(message)
906```
907
908<Note>
909 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.
910</Note>
911
912**Muat semua pengaturan filesystem secara eksplisit:**
913
914```python theme={null}
915from claude_agent_sdk import query, ClaudeAgentOptions
916
917async for message in query(
918 prompt="Analyze this code",
919 options=ClaudeAgentOptions(
920 setting_sources=["user", "project", "local"]
921 ),
922):
923 print(message)
924```
925
926**Muat hanya sumber pengaturan tertentu:**
927
928```python theme={null}
929# Load only project settings, ignore user and local
930async for message in query(
931 prompt="Run CI checks",
932 options=ClaudeAgentOptions(
933 setting_sources=["project"] # Only .claude/settings.json
934 ),
935):
936 print(message)
937```
938
939**Lingkungan testing dan CI:**
940
941```python theme={null}
942# Ensure consistent behavior in CI by excluding local settings
943async for message in query(
944 prompt="Run tests",
945 options=ClaudeAgentOptions(
946 setting_sources=["project"], # Only team-shared settings
947 permission_mode="bypassPermissions",
948 ),
949):
950 print(message)
951```
952
953**Aplikasi SDK-only:**
954
955```python theme={null}
956# Define everything programmatically.
957# Pass [] to opt out of filesystem setting sources.
958async for message in query(
959 prompt="Review this PR",
960 options=ClaudeAgentOptions(
961 setting_sources=[],
962 agents={...},
963 mcp_servers={...},
964 allowed_tools=["Read", "Grep", "Glob"],
965 ),
966):
967 print(message)
968```
969
970**Memuat instruksi proyek CLAUDE.md:**
971
972```python theme={null}
973# Load project settings to include CLAUDE.md files
974async for message in query(
975 prompt="Add a new feature following project conventions",
976 options=ClaudeAgentOptions(
977 system_prompt={
978 "type": "preset",
979 "preset": "claude_code", # Use Claude Code's system prompt
980 },
981 setting_sources=["project"], # Loads CLAUDE.md from project
982 allowed_tools=["Read", "Write", "Edit"],
983 ),
984):
985 print(message)
986```
987
988#### Preseden pengaturan
989
990Ketika beberapa sumber dimuat, pengaturan digabungkan dengan preseden ini (tertinggi ke terendah):
991
9921. Pengaturan lokal (`.claude/settings.local.json`)
9932. Pengaturan proyek (`.claude/settings.json`)
9943. Pengaturan pengguna (`~/.claude/settings.json`)
995
996Opsi programatis seperti `agents` dan `allowed_tools` mengganti pengaturan filesystem pengguna, proyek, dan lokal. Pengaturan kebijakan terkelola mengambil prioritas atas opsi programatis.
997
998### `AgentDefinition`
999
1000Konfigurasi untuk subagent yang didefinisikan secara programatis.
1001
1002```python theme={null}
1003@dataclass
1004class AgentDefinition:
1005 description: str
1006 prompt: str
1007 tools: list[str] | None = None
1008 disallowedTools: list[str] | None = None
1009 model: str | None = None
1010 skills: list[str] | None = None
1011 memory: Literal["user", "project", "local"] | None = None
1012 mcpServers: list[str | dict[str, Any]] | None = None
1013 initialPrompt: str | None = None
1014 maxTurns: int | None = None
1015 background: bool | None = None
1016 effort: Literal["low", "medium", "high", "max"] | int | None = None
1017 permissionMode: PermissionMode | None = None
1018```
1019
1020| Field | Diperlukan | Deskripsi |
1021| :---------------- | :--------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1022| `description` | Ya | Deskripsi bahasa alami tentang kapan menggunakan agent ini |
1023| `prompt` | Ya | System prompt agent |
1024| `tools` | Tidak | Array nama tool yang diizinkan. Jika dihilangkan, mewarisi semua tools |
1025| `disallowedTools` | Tidak | Array nama tool untuk dihapus dari set tool agent |
1026| `model` | Tidak | Penggantian model untuk agent ini. Menerima alias seperti `"sonnet"`, `"opus"`, `"haiku"`, atau `"inherit"`, atau ID model lengkap. Jika dihilangkan, menggunakan model utama |
1027| `skills` | Tidak | Daftar nama skill yang tersedia untuk agent ini |
1028| `memory` | Tidak | Sumber memori untuk agent ini: `"user"`, `"project"`, atau `"local"` |
1029| `mcpServers` | Tidak | Server MCP yang tersedia untuk agent ini. Setiap entri adalah nama server atau dict `{name: config}` inline |
1030| `initialPrompt` | Tidak | Auto-submitted sebagai putaran pengguna pertama ketika agent ini berjalan sebagai agent thread utama |
1031| `maxTurns` | Tidak | Jumlah maksimal putaran agentic sebelum agent berhenti |
1032| `background` | Tidak | Jalankan agent ini sebagai tugas latar belakang non-blocking ketika dipanggil |
1033| `effort` | Tidak | Tingkat usaha reasoning untuk agent ini. Menerima tingkat bernama atau integer |
1034| `permissionMode` | Tidak | Mode izin untuk eksekusi tool dalam agent ini. Lihat [`PermissionMode`](#permission-mode) |
1035
1036<Note>
1037 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.
1038</Note>
1039
1040### `PermissionMode`
1041
1042Mode izin untuk mengontrol eksekusi tool.
1043
1044```python theme={null}
1045PermissionMode = Literal[
1046 "default", # Standard permission behavior
1047 "acceptEdits", # Auto-accept file edits
1048 "plan", # Planning mode - no execution
1049 "dontAsk", # Deny anything not pre-approved instead of prompting
1050 "bypassPermissions", # Bypass all permission checks (use with caution)
1051]
1052```
1053
1054### `CanUseTool`
1055
1056Type alias untuk fungsi callback izin tool.
1057
1058```python theme={null}
1059CanUseTool = Callable[
1060 [str, dict[str, Any], ToolPermissionContext], Awaitable[PermissionResult]
1061]
1062```
1063
1064Callback menerima:
1065
1066* `tool_name`: Nama tool yang sedang dipanggil
1067* `input_data`: Parameter input tool
1068* `context`: `ToolPermissionContext` dengan informasi tambahan
1069
1070Mengembalikan `PermissionResult` (baik `PermissionResultAllow` atau `PermissionResultDeny`).
1071
1072### `ToolPermissionContext`
1073
1074Informasi konteks yang diteruskan ke callback izin tool.
1075
1076```python theme={null}
1077@dataclass
1078class ToolPermissionContext:
1079 signal: Any | None = None # Future: abort signal support
1080 suggestions: list[PermissionUpdate] = field(default_factory=list)
1081```
1082
1083| Field | Tipe | Deskripsi |
1084| :------------ | :----------------------- | :---------------------------------------------------- |
1085| `signal` | `Any \| None` | Dicadangkan untuk dukungan sinyal abort di masa depan |
1086| `suggestions` | `list[PermissionUpdate]` | Saran pembaruan izin dari CLI |
1087
1088### `PermissionResult`
1089
1090Tipe union untuk hasil callback izin.
1091
1092```python theme={null}
1093PermissionResult = PermissionResultAllow | PermissionResultDeny
1094```
1095
1096### `PermissionResultAllow`
1097
1098Hasil yang menunjukkan panggilan tool harus diizinkan.
1099
1100```python theme={null}
1101@dataclass
1102class PermissionResultAllow:
1103 behavior: Literal["allow"] = "allow"
1104 updated_input: dict[str, Any] | None = None
1105 updated_permissions: list[PermissionUpdate] | None = None
1106```
1107
1108| Field | Tipe | Default | Deskripsi |
1109| :-------------------- | :------------------------------- | :-------- | :----------------------------------------------------- |
1110| `behavior` | `Literal["allow"]` | `"allow"` | Harus "allow" |
1111| `updated_input` | `dict[str, Any] \| None` | `None` | Input yang dimodifikasi untuk digunakan alih-alih asli |
1112| `updated_permissions` | `list[PermissionUpdate] \| None` | `None` | Pembaruan izin untuk diterapkan |
1113
1114### `PermissionResultDeny`
1115
1116Hasil yang menunjukkan panggilan tool harus ditolak.
1117
1118```python theme={null}
1119@dataclass
1120class PermissionResultDeny:
1121 behavior: Literal["deny"] = "deny"
1122 message: str = ""
1123 interrupt: bool = False
1124```
1125
1126| Field | Tipe | Default | Deskripsi |
1127| :---------- | :---------------- | :------- | :------------------------------------------ |
1128| `behavior` | `Literal["deny"]` | `"deny"` | Harus "deny" |
1129| `message` | `str` | `""` | Pesan yang menjelaskan mengapa tool ditolak |
1130| `interrupt` | `bool` | `False` | Apakah akan mengganggu eksekusi saat ini |
1131
1132### `PermissionUpdate`
1133
1134Konfigurasi untuk memperbarui izin secara programatis.
1135
1136```python theme={null}
1137@dataclass
1138class PermissionUpdate:
1139 type: Literal[
1140 "addRules",
1141 "replaceRules",
1142 "removeRules",
1143 "setMode",
1144 "addDirectories",
1145 "removeDirectories",
1146 ]
1147 rules: list[PermissionRuleValue] | None = None
1148 behavior: Literal["allow", "deny", "ask"] | None = None
1149 mode: PermissionMode | None = None
1150 directories: list[str] | None = None
1151 destination: (
1152 Literal["userSettings", "projectSettings", "localSettings", "session"] | None
1153 ) = None
1154```
1155
1156| Field | Tipe | Deskripsi |
1157| :------------ | :---------------------------------------- | :------------------------------------------- |
1158| `type` | `Literal[...]` | Jenis operasi pembaruan izin |
1159| `rules` | `list[PermissionRuleValue] \| None` | Aturan untuk operasi add/replace/remove |
1160| `behavior` | `Literal["allow", "deny", "ask"] \| None` | Perilaku untuk operasi berbasis aturan |
1161| `mode` | `PermissionMode \| None` | Mode untuk operasi setMode |
1162| `directories` | `list[str] \| None` | Direktori untuk operasi add/remove direktori |
1163| `destination` | `Literal[...] \| None` | Di mana menerapkan pembaruan izin |
1164
1165### `PermissionRuleValue`
1166
1167Aturan untuk ditambahkan, diganti, atau dihapus dalam pembaruan izin.
1168
1169```python theme={null}
1170@dataclass
1171class PermissionRuleValue:
1172 tool_name: str
1173 rule_content: str | None = None
1174```
1175
1176### `ToolsPreset`
1177
1178Konfigurasi preset tools untuk menggunakan set tool default Claude Code.
1179
1180```python theme={null}
1181class ToolsPreset(TypedDict):
1182 type: Literal["preset"]
1183 preset: Literal["claude_code"]
1184```
1185
1186### `ThinkingConfig`
1187
1188Mengontrol perilaku extended thinking. Union dari tiga konfigurasi:
1189
1190```python theme={null}
1191class ThinkingConfigAdaptive(TypedDict):
1192 type: Literal["adaptive"]
1193
1194
1195class ThinkingConfigEnabled(TypedDict):
1196 type: Literal["enabled"]
1197 budget_tokens: int
1198
1199
1200class ThinkingConfigDisabled(TypedDict):
1201 type: Literal["disabled"]
1202
1203
1204ThinkingConfig = ThinkingConfigAdaptive | ThinkingConfigEnabled | ThinkingConfigDisabled
1205```
1206
1207| Varian | Field | Deskripsi |
1208| :--------- | :---------------------- | :---------------------------------------------------- |
1209| `adaptive` | `type` | Claude secara adaptif memutuskan kapan harus berpikir |
1210| `enabled` | `type`, `budget_tokens` | Aktifkan thinking dengan budget token tertentu |
1211| `disabled` | `type` | Nonaktifkan thinking |
1212
1213Karena 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`:
1214
1215```python theme={null}
1216from claude_agent_sdk import ClaudeAgentOptions, ThinkingConfigEnabled
1217
1218# Option 1: dict literal (recommended, no import needed)
1219options = ClaudeAgentOptions(thinking={"type": "enabled", "budget_tokens": 20000})
1220
1221# Option 2: constructor-style (returns a plain dict)
1222config = ThinkingConfigEnabled(type="enabled", budget_tokens=20000)
1223print(config["budget_tokens"]) # 20000
1224# config.budget_tokens would raise AttributeError
1225```
1226
1227### `SdkBeta`
1228
1229Tipe literal untuk fitur beta SDK.
1230
1231```python theme={null}
1232SdkBeta = Literal["context-1m-2025-08-07"]
1233```
1234
1235Gunakan dengan field `betas` dalam `ClaudeAgentOptions` untuk mengaktifkan fitur beta.
1236
1237<Warning>
1238 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](https://platform.claude.com/docs/en/about-claude/models/overview), yang mencakup konteks 1M pada harga standar tanpa header beta yang diperlukan.
1239</Warning>
1240
1241### `McpSdkServerConfig`
1242
1243Konfigurasi untuk server MCP SDK yang dibuat dengan `create_sdk_mcp_server()`.
1244
1245```python theme={null}
1246class McpSdkServerConfig(TypedDict):
1247 type: Literal["sdk"]
1248 name: str
1249 instance: Any # MCP Server instance
1250```
1251
1252### `McpServerConfig`
1253
1254Tipe union untuk konfigurasi server MCP.
1255
1256```python theme={null}
1257McpServerConfig = (
1258 McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfig
1259)
1260```
1261
1262#### `McpStdioServerConfig`
1263
1264```python theme={null}
1265class McpStdioServerConfig(TypedDict):
1266 type: NotRequired[Literal["stdio"]] # Optional for backwards compatibility
1267 command: str
1268 args: NotRequired[list[str]]
1269 env: NotRequired[dict[str, str]]
1270```
1271
1272#### `McpSSEServerConfig`
1273
1274```python theme={null}
1275class McpSSEServerConfig(TypedDict):
1276 type: Literal["sse"]
1277 url: str
1278 headers: NotRequired[dict[str, str]]
1279```
1280
1281#### `McpHttpServerConfig`
1282
1283```python theme={null}
1284class McpHttpServerConfig(TypedDict):
1285 type: Literal["http"]
1286 url: str
1287 headers: NotRequired[dict[str, str]]
1288```
1289
1290### `McpServerStatusConfig`
1291
1292Konfigurasi server MCP seperti yang dilaporkan oleh [`get_mcp_status()`](#methods). Ini adalah union dari semua varian transport [`McpServerConfig`](#mcp-server-config) ditambah varian output-only `claudeai-proxy` untuk server yang di-proxy melalui claude.ai.
1293
1294```python theme={null}
1295McpServerStatusConfig = (
1296 McpStdioServerConfig
1297 | McpSSEServerConfig
1298 | McpHttpServerConfig
1299 | McpSdkServerConfigStatus
1300 | McpClaudeAIProxyServerConfig
1301)
1302```
1303
1304`McpSdkServerConfigStatus` adalah bentuk yang dapat diserialisasi dari [`McpSdkServerConfig`](#mcp-sdk-server-config) dengan hanya field `type` (`"sdk"`) dan `name` (`str`); `instance` dalam proses dihilangkan. `McpClaudeAIProxyServerConfig` memiliki field `type` (`"claudeai-proxy"`), `url` (`str`), dan `id` (`str`).
1305
1306### `McpStatusResponse`
1307
1308Respons dari [`ClaudeSDKClient.get_mcp_status()`](#methods). Membungkus daftar status server di bawah kunci `mcpServers`.
1309
1310```python theme={null}
1311class McpStatusResponse(TypedDict):
1312 mcpServers: list[McpServerStatus]
1313```
1314
1315### `McpServerStatus`
1316
1317Status server MCP yang terhubung, terdapat dalam [`McpStatusResponse`](#mcp-status-response).
1318
1319```python theme={null}
1320class McpServerStatus(TypedDict):
1321 name: str
1322 status: McpServerConnectionStatus # "connected" | "failed" | "needs-auth" | "pending" | "disabled"
1323 serverInfo: NotRequired[McpServerInfo]
1324 error: NotRequired[str]
1325 config: NotRequired[McpServerStatusConfig]
1326 scope: NotRequired[str]
1327 tools: NotRequired[list[McpToolInfo]]
1328```
1329
1330| Field | Tipe | Deskripsi |
1331| :----------- | :-------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1332| `name` | `str` | Nama server |
1333| `status` | `str` | Salah satu dari `"connected"`, `"failed"`, `"needs-auth"`, `"pending"`, atau `"disabled"` |
1334| `serverInfo` | `dict` (opsional) | Nama dan versi server (`{"name": str, "version": str}`) |
1335| `error` | `str` (opsional) | Pesan error jika server gagal terhubung |
1336| `config` | [`McpServerStatusConfig`](#mcp-server-status-config) (opsional) | Konfigurasi server. Bentuk yang sama seperti [`McpServerConfig`](#mcp-server-config) (stdio, SSE, HTTP, atau SDK), ditambah varian `claudeai-proxy` untuk server yang terhubung melalui claude.ai |
1337| `scope` | `str` (opsional) | Scope konfigurasi |
1338| `tools` | `list` (opsional) | Tools yang disediakan oleh server ini, masing-masing dengan field `name`, `description`, dan `annotations` |
1339
1340### `SdkPluginConfig`
1341
1342Konfigurasi untuk memuat plugins dalam SDK.
1343
1344```python theme={null}
1345class SdkPluginConfig(TypedDict):
1346 type: Literal["local"]
1347 path: str
1348```
1349
1350| Field | Tipe | Deskripsi |
1351| :----- | :----------------- | :----------------------------------------------------------- |
1352| `type` | `Literal["local"]` | Harus `"local"` (hanya plugins lokal yang saat ini didukung) |
1353| `path` | `str` | Jalur absolut atau relatif ke direktori plugin |
1354
1355**Contoh:**
1356
1357```python theme={null}
1358plugins = [
1359 {"type": "local", "path": "./my-plugin"},
1360 {"type": "local", "path": "/absolute/path/to/plugin"},
1361]
1362```
1363
1364Untuk informasi lengkap tentang membuat dan menggunakan plugins, lihat [Plugins](/id/agent-sdk/plugins).
1365
1366## Tipe Pesan
1367
1368### `Message`
1369
1370Tipe union dari semua pesan yang mungkin.
1371
1372```python theme={null}
1373Message = (
1374 UserMessage
1375 | AssistantMessage
1376 | SystemMessage
1377 | ResultMessage
1378 | StreamEvent
1379 | RateLimitEvent
1380)
1381```
1382
1383### `UserMessage`
1384
1385Pesan input pengguna.
1386
1387```python theme={null}
1388@dataclass
1389class UserMessage:
1390 content: str | list[ContentBlock]
1391 uuid: str | None = None
1392 parent_tool_use_id: str | None = None
1393 tool_use_result: dict[str, Any] | None = None
1394```
1395
1396| Field | Tipe | Deskripsi |
1397| :------------------- | :-------------------------- | :---------------------------------------------------------- |
1398| `content` | `str \| list[ContentBlock]` | Konten pesan sebagai teks atau blok konten |
1399| `uuid` | `str \| None` | Pengenal pesan unik |
1400| `parent_tool_use_id` | `str \| None` | ID penggunaan tool jika pesan ini adalah respons hasil tool |
1401| `tool_use_result` | `dict[str, Any] \| None` | Data hasil tool jika berlaku |
1402
1403### `AssistantMessage`
1404
1405Pesan respons asisten dengan blok konten.
1406
1407```python theme={null}
1408@dataclass
1409class AssistantMessage:
1410 content: list[ContentBlock]
1411 model: str
1412 parent_tool_use_id: str | None = None
1413 error: AssistantMessageError | None = None
1414 usage: dict[str, Any] | None = None
1415 message_id: str | None = None
1416```
1417
1418| Field | Tipe | Deskripsi |
1419| :------------------- | :------------------------------------------------------------- | :-------------------------------------------------------------------------------------------- |
1420| `content` | `list[ContentBlock]` | Daftar blok konten dalam respons |
1421| `model` | `str` | Model yang menghasilkan respons |
1422| `parent_tool_use_id` | `str \| None` | ID penggunaan tool jika ini adalah respons bersarang |
1423| `error` | [`AssistantMessageError`](#assistant-message-error) ` \| None` | Tipe error jika respons mengalami error |
1424| `usage` | `dict[str, Any] \| None` | Penggunaan token per-pesan (kunci yang sama seperti [`ResultMessage.usage`](#result-message)) |
1425| `message_id` | `str \| None` | ID pesan API. Beberapa pesan dari satu putaran berbagi ID yang sama |
1426
1427### `AssistantMessageError`
1428
1429Tipe error yang mungkin untuk pesan asisten.
1430
1431```python theme={null}
1432AssistantMessageError = Literal[
1433 "authentication_failed",
1434 "billing_error",
1435 "rate_limit",
1436 "invalid_request",
1437 "server_error",
1438 "max_output_tokens",
1439 "unknown",
1440]
1441```
1442
1443### `SystemMessage`
1444
1445Pesan sistem dengan metadata.
1446
1447```python theme={null}
1448@dataclass
1449class SystemMessage:
1450 subtype: str
1451 data: dict[str, Any]
1452```
1453
1454### `ResultMessage`
1455
1456Pesan hasil akhir dengan informasi biaya dan penggunaan.
1457
1458```python theme={null}
1459@dataclass
1460class ResultMessage:
1461 subtype: str
1462 duration_ms: int
1463 duration_api_ms: int
1464 is_error: bool
1465 num_turns: int
1466 session_id: str
1467 total_cost_usd: float | None = None
1468 usage: dict[str, Any] | None = None
1469 result: str | None = None
1470 stop_reason: str | None = None
1471 structured_output: Any = None
1472 model_usage: dict[str, Any] | None = None
1473```
1474
1475Dict `usage` berisi kunci berikut ketika ada:
1476
1477| Kunci | Tipe | Deskripsi |
1478| ----------------------------- | ----- | ---------------------------------------------------- |
1479| `input_tokens` | `int` | Total token input yang dikonsumsi. |
1480| `output_tokens` | `int` | Total token output yang dihasilkan. |
1481| `cache_creation_input_tokens` | `int` | Token yang digunakan untuk membuat entri cache baru. |
1482| `cache_read_input_tokens` | `int` | Token yang dibaca dari entri cache yang ada. |
1483
1484Dict `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`](/id/agent-sdk/typescript#model-usage) TypeScript:
1485
1486| Kunci | Tipe | Deskripsi |
1487| -------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1488| `inputTokens` | `int` | Token input untuk model ini. |
1489| `outputTokens` | `int` | Token output untuk model ini. |
1490| `cacheReadInputTokens` | `int` | Token baca cache untuk model ini. |
1491| `cacheCreationInputTokens` | `int` | Token pembuatan cache untuk model ini. |
1492| `webSearchRequests` | `int` | Permintaan pencarian web yang dibuat oleh model ini. |
1493| `costUSD` | `float` | Biaya yang diperkirakan dalam USD untuk model ini, dihitung sisi klien. Lihat [Track cost and usage](/id/agent-sdk/cost-tracking) untuk peringatan penagihan. |
1494| `contextWindow` | `int` | Ukuran jendela konteks untuk model ini. |
1495| `maxOutputTokens` | `int` | Batas token output maksimal untuk model ini. |
1496
1497### `StreamEvent`
1498
1499Event 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`.
1500
1501```python theme={null}
1502@dataclass
1503class StreamEvent:
1504 uuid: str
1505 session_id: str
1506 event: dict[str, Any] # The raw Claude API stream event
1507 parent_tool_use_id: str | None = None
1508```
1509
1510| Field | Tipe | Deskripsi |
1511| :------------------- | :--------------- | :---------------------------------------------------- |
1512| `uuid` | `str` | Pengenal unik untuk event ini |
1513| `session_id` | `str` | Pengenal sesi |
1514| `event` | `dict[str, Any]` | Data event stream Claude API mentah |
1515| `parent_tool_use_id` | `str \| None` | ID penggunaan tool induk jika event ini dari subagent |
1516
1517### `RateLimitEvent`
1518
1519Dipancarkan 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"`.
1520
1521```python theme={null}
1522@dataclass
1523class RateLimitEvent:
1524 rate_limit_info: RateLimitInfo
1525 uuid: str
1526 session_id: str
1527```
1528
1529| Field | Tipe | Deskripsi |
1530| :---------------- | :---------------------------------- | :------------------------- |
1531| `rate_limit_info` | [`RateLimitInfo`](#rate-limit-info) | Status rate limit saat ini |
1532| `uuid` | `str` | Pengenal event unik |
1533| `session_id` | `str` | Pengenal sesi |
1534
1535### `RateLimitInfo`
1536
1537Status rate limit yang dibawa oleh [`RateLimitEvent`](#rate-limit-event).
1538
1539```python theme={null}
1540RateLimitStatus = Literal["allowed", "allowed_warning", "rejected"]
1541RateLimitType = Literal[
1542 "five_hour", "seven_day", "seven_day_opus", "seven_day_sonnet", "overage"
1543]
1544
1545
1546@dataclass
1547class RateLimitInfo:
1548 status: RateLimitStatus
1549 resets_at: int | None = None
1550 rate_limit_type: RateLimitType | None = None
1551 utilization: float | None = None
1552 overage_status: RateLimitStatus | None = None
1553 overage_resets_at: int | None = None
1554 overage_disabled_reason: str | None = None
1555 raw: dict[str, Any] = field(default_factory=dict)
1556```
1557
1558| Field | Tipe | Deskripsi |
1559| :------------------------ | :------------------------ | :------------------------------------------------------------------------------------------------ |
1560| `status` | `RateLimitStatus` | Status saat ini. `"allowed_warning"` berarti mendekati batas; `"rejected"` berarti batas tercapai |
1561| `resets_at` | `int \| None` | Timestamp Unix ketika jendela rate limit direset |
1562| `rate_limit_type` | `RateLimitType \| None` | Jendela rate limit mana yang berlaku |
1563| `utilization` | `float \| None` | Fraksi rate limit yang dikonsumsi (0.0 hingga 1.0) |
1564| `overage_status` | `RateLimitStatus \| None` | Status penggunaan overage pay-as-you-go, jika berlaku |
1565| `overage_resets_at` | `int \| None` | Timestamp Unix ketika jendela overage direset |
1566| `overage_disabled_reason` | `str \| None` | Mengapa overage tidak tersedia, jika status adalah `"rejected"` |
1567| `raw` | `dict[str, Any]` | Dict mentah lengkap dari CLI, termasuk field yang tidak dimodelkan di atas |
1568
1569### `TaskStartedMessage`
1570
1571Dipancarkan 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`.
1572
1573```python theme={null}
1574@dataclass
1575class TaskStartedMessage(SystemMessage):
1576 task_id: str
1577 description: str
1578 uuid: str
1579 session_id: str
1580 tool_use_id: str | None = None
1581 task_type: str | None = None
1582```
1583
1584| Field | Tipe | Deskripsi |
1585| :------------ | :------------ | :------------------------------------------------------------------------------------------------------------------------------ |
1586| `task_id` | `str` | Pengenal unik untuk tugas |
1587| `description` | `str` | Deskripsi tugas |
1588| `uuid` | `str` | Pengenal pesan unik |
1589| `session_id` | `str` | Pengenal sesi |
1590| `tool_use_id` | `str \| None` | ID penggunaan tool yang terkait |
1591| `task_type` | `str \| None` | Jenis tugas latar belakang: `"local_bash"` untuk Bash dan Monitor watches di background, `"local_agent"`, atau `"remote_agent"` |
1592
1593### `TaskUsage`
1594
1595Data token dan timing untuk tugas latar belakang.
1596
1597```python theme={null}
1598class TaskUsage(TypedDict):
1599 total_tokens: int
1600 tool_uses: int
1601 duration_ms: int
1602```
1603
1604### `TaskProgressMessage`
1605
1606Dipancarkan secara berkala dengan pembaruan kemajuan untuk tugas latar belakang yang sedang berjalan.
1607
1608```python theme={null}
1609@dataclass
1610class TaskProgressMessage(SystemMessage):
1611 task_id: str
1612 description: str
1613 usage: TaskUsage
1614 uuid: str
1615 session_id: str
1616 tool_use_id: str | None = None
1617 last_tool_name: str | None = None
1618```
1619
1620| Field | Tipe | Deskripsi |
1621| :--------------- | :------------ | :------------------------------------------ |
1622| `task_id` | `str` | Pengenal unik untuk tugas |
1623| `description` | `str` | Deskripsi status saat ini |
1624| `usage` | `TaskUsage` | Penggunaan token untuk tugas ini sejauh ini |
1625| `uuid` | `str` | Pengenal pesan unik |
1626| `session_id` | `str` | Pengenal sesi |
1627| `tool_use_id` | `str \| None` | ID penggunaan tool yang terkait |
1628| `last_tool_name` | `str \| None` | Nama tool terakhir yang digunakan tugas |
1629
1630### `TaskNotificationMessage`
1631
1632Dipancarkan ketika tugas latar belakang selesai, gagal, atau dihentikan. Tugas latar belakang termasuk perintah Bash `run_in_background`, Monitor watches, dan subagent latar belakang.
1633
1634```python theme={null}
1635@dataclass
1636class TaskNotificationMessage(SystemMessage):
1637 task_id: str
1638 status: TaskNotificationStatus # "completed" | "failed" | "stopped"
1639 output_file: str
1640 summary: str
1641 uuid: str
1642 session_id: str
1643 tool_use_id: str | None = None
1644 usage: TaskUsage | None = None
1645```
1646
1647| Field | Tipe | Deskripsi |
1648| :------------ | :----------------------- | :---------------------------------------------------------- |
1649| `task_id` | `str` | Pengenal unik untuk tugas |
1650| `status` | `TaskNotificationStatus` | Salah satu dari `"completed"`, `"failed"`, atau `"stopped"` |
1651| `output_file` | `str` | Jalur ke file output tugas |
1652| `summary` | `str` | Ringkasan hasil tugas |
1653| `uuid` | `str` | Pengenal pesan unik |
1654| `session_id` | `str` | Pengenal sesi |
1655| `tool_use_id` | `str \| None` | ID penggunaan tool yang terkait |
1656| `usage` | `TaskUsage \| None` | Penggunaan token akhir untuk tugas |
1657
1658## Tipe Blok Konten
1659
1660### `ContentBlock`
1661
1662Tipe union dari semua blok konten.
1663
1664```python theme={null}
1665ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock
1666```
1667
1668### `TextBlock`
1669
1670Blok konten teks.
1671
1672```python theme={null}
1673@dataclass
1674class TextBlock:
1675 text: str
1676```
1677
1678### `ThinkingBlock`
1679
1680Blok konten thinking (untuk model dengan kemampuan thinking).
1681
1682```python theme={null}
1683@dataclass
1684class ThinkingBlock:
1685 thinking: str
1686 signature: str
1687```
1688
1689### `ToolUseBlock`
1690
1691Blok permintaan penggunaan tool.
1692
1693```python theme={null}
1694@dataclass
1695class ToolUseBlock:
1696 id: str
1697 name: str
1698 input: dict[str, Any]
1699```
1700
1701### `ToolResultBlock`
1702
1703Blok hasil eksekusi tool.
1704
1705```python theme={null}
1706@dataclass
1707class ToolResultBlock:
1708 tool_use_id: str
1709 content: str | list[dict[str, Any]] | None = None
1710 is_error: bool | None = None
1711```
1712
1713## Tipe Error
1714
1715### `ClaudeSDKError`
1716
1717Kelas exception dasar untuk semua error SDK.
1718
1719```python theme={null}
1720class ClaudeSDKError(Exception):
1721 """Base error for Claude SDK."""
1722```
1723
1724### `CLINotFoundError`
1725
1726Diangkat ketika Claude Code CLI tidak diinstal atau tidak ditemukan.
1727
1728```python theme={null}
1729class CLINotFoundError(CLIConnectionError):
1730 def __init__(
1731 self, message: str = "Claude Code not found", cli_path: str | None = None
1732 ):
1733 """
1734 Args:
1735 message: Error message (default: "Claude Code not found")
1736 cli_path: Optional path to the CLI that was not found
1737 """
1738```
1739
1740### `CLIConnectionError`
1741
1742Diangkat ketika koneksi ke Claude Code gagal.
1743
1744```python theme={null}
1745class CLIConnectionError(ClaudeSDKError):
1746 """Failed to connect to Claude Code."""
1747```
1748
1749### `ProcessError`
1750
1751Diangkat ketika proses Claude Code gagal.
1752
1753```python theme={null}
1754class ProcessError(ClaudeSDKError):
1755 def __init__(
1756 self, message: str, exit_code: int | None = None, stderr: str | None = None
1757 ):
1758 self.exit_code = exit_code
1759 self.stderr = stderr
1760```
1761
1762### `CLIJSONDecodeError`
1763
1764Diangkat ketika parsing JSON gagal.
1765
1766```python theme={null}
1767class CLIJSONDecodeError(ClaudeSDKError):
1768 def __init__(self, line: str, original_error: Exception):
1769 """
1770 Args:
1771 line: The line that failed to parse
1772 original_error: The original JSON decode exception
1773 """
1774 self.line = line
1775 self.original_error = original_error
1776```
1777
1778## Tipe Hook
1779
1780Untuk panduan komprehensif tentang menggunakan hooks dengan contoh dan pola umum, lihat [Hooks guide](/id/agent-sdk/hooks).
1781
1782### `HookEvent`
1783
1784Tipe event hook yang didukung.
1785
1786```python theme={null}
1787HookEvent = Literal[
1788 "PreToolUse", # Called before tool execution
1789 "PostToolUse", # Called after tool execution
1790 "PostToolUseFailure", # Called when a tool execution fails
1791 "UserPromptSubmit", # Called when user submits a prompt
1792 "Stop", # Called when stopping execution
1793 "SubagentStop", # Called when a subagent stops
1794 "PreCompact", # Called before message compaction
1795 "Notification", # Called for notification events
1796 "SubagentStart", # Called when a subagent starts
1797 "PermissionRequest", # Called when a permission decision is needed
1798]
1799```
1800
1801<Note>
1802 SDK TypeScript mendukung event hook tambahan yang belum tersedia di Python: `SessionStart`, `SessionEnd`, `Setup`, `TeammateIdle`, `TaskCompleted`, `ConfigChange`, `WorktreeCreate`, `WorktreeRemove`, dan `PostToolBatch`.
1803</Note>
1804
1805### `HookCallback`
1806
1807Definisi tipe untuk fungsi callback hook.
1808
1809```python theme={null}
1810HookCallback = Callable[[HookInput, str | None, HookContext], Awaitable[HookJSONOutput]]
1811```
1812
1813Parameter:
1814
1815* `input`: Input hook yang kuat dengan union yang dibedakan berdasarkan `hook_event_name` (lihat [`HookInput`](#hook-input))
1816* `tool_use_id`: Pengenal penggunaan tool opsional (untuk hook terkait tool)
1817* `context`: Konteks hook dengan informasi tambahan
1818
1819Mengembalikan [`HookJSONOutput`](#hook-json-output) yang mungkin berisi:
1820
1821* `decision`: `"block"` untuk memblokir tindakan
1822* `systemMessage`: Pesan sistem untuk ditambahkan ke transkrip
1823* `hookSpecificOutput`: Data output spesifik hook
1824
1825### `HookContext`
1826
1827Informasi konteks yang diteruskan ke callback hook.
1828
1829```python theme={null}
1830class HookContext(TypedDict):
1831 signal: Any | None # Future: abort signal support
1832```
1833
1834### `HookMatcher`
1835
1836Konfigurasi untuk mencocokkan hooks ke event atau tools tertentu.
1837
1838```python theme={null}
1839@dataclass
1840class HookMatcher:
1841 matcher: str | None = (
1842 None # Tool name or pattern to match (e.g., "Bash", "Write|Edit")
1843 )
1844 hooks: list[HookCallback] = field(
1845 default_factory=list
1846 ) # List of callbacks to execute
1847 timeout: float | None = (
1848 None # Timeout in seconds for all hooks in this matcher (default: 60)
1849 )
1850```
1851
1852### `HookInput`
1853
1854Tipe union dari semua tipe input hook. Tipe aktual bergantung pada field `hook_event_name`.
1855
1856```python theme={null}
1857HookInput = (
1858 PreToolUseHookInput
1859 | PostToolUseHookInput
1860 | PostToolUseFailureHookInput
1861 | UserPromptSubmitHookInput
1862 | StopHookInput
1863 | SubagentStopHookInput
1864 | PreCompactHookInput
1865 | NotificationHookInput
1866 | SubagentStartHookInput
1867 | PermissionRequestHookInput
1868)
1869```
1870
1871### `BaseHookInput`
1872
1873Field dasar yang ada di semua tipe input hook.
1874
1875```python theme={null}
1876class BaseHookInput(TypedDict):
1877 session_id: str
1878 transcript_path: str
1879 cwd: str
1880 permission_mode: NotRequired[str]
1881```
1882
1883| Field | Tipe | Deskripsi |
1884| :---------------- | :--------------- | :--------------------------- |
1885| `session_id` | `str` | Pengenal sesi saat ini |
1886| `transcript_path` | `str` | Jalur ke file transkrip sesi |
1887| `cwd` | `str` | Direktori kerja saat ini |
1888| `permission_mode` | `str` (opsional) | Mode izin saat ini |
1889
1890### `PreToolUseHookInput`
1891
1892Data input untuk event hook `PreToolUse`.
1893
1894```python theme={null}
1895class PreToolUseHookInput(BaseHookInput):
1896 hook_event_name: Literal["PreToolUse"]
1897 tool_name: str
1898 tool_input: dict[str, Any]
1899 tool_use_id: str
1900 agent_id: NotRequired[str]
1901 agent_type: NotRequired[str]
1902```
1903
1904| Field | Tipe | Deskripsi |
1905| :---------------- | :---------------------- | :----------------------------------------------------------- |
1906| `hook_event_name` | `Literal["PreToolUse"]` | Selalu "PreToolUse" |
1907| `tool_name` | `str` | Nama tool yang akan dieksekusi |
1908| `tool_input` | `dict[str, Any]` | Parameter input untuk tool |
1909| `tool_use_id` | `str` | Pengenal unik untuk penggunaan tool ini |
1910| `agent_id` | `str` (opsional) | Pengenal subagent, ada ketika hook menyala di dalam subagent |
1911| `agent_type` | `str` (opsional) | Tipe subagent, ada ketika hook menyala di dalam subagent |
1912
1913### `PostToolUseHookInput`
1914
1915Data input untuk event hook `PostToolUse`.
1916
1917```python theme={null}
1918class PostToolUseHookInput(BaseHookInput):
1919 hook_event_name: Literal["PostToolUse"]
1920 tool_name: str
1921 tool_input: dict[str, Any]
1922 tool_response: Any
1923 tool_use_id: str
1924 agent_id: NotRequired[str]
1925 agent_type: NotRequired[str]
1926```
1927
1928| Field | Tipe | Deskripsi |
1929| :---------------- | :----------------------- | :----------------------------------------------------------- |
1930| `hook_event_name` | `Literal["PostToolUse"]` | Selalu "PostToolUse" |
1931| `tool_name` | `str` | Nama tool yang dieksekusi |
1932| `tool_input` | `dict[str, Any]` | Parameter input yang digunakan |
1933| `tool_response` | `Any` | Respons dari eksekusi tool |
1934| `tool_use_id` | `str` | Pengenal unik untuk penggunaan tool ini |
1935| `agent_id` | `str` (opsional) | Pengenal subagent, ada ketika hook menyala di dalam subagent |
1936| `agent_type` | `str` (opsional) | Tipe subagent, ada ketika hook menyala di dalam subagent |
1937
1938### `PostToolUseFailureHookInput`
1939
1940Data input untuk event hook `PostToolUseFailure`. Dipanggil ketika eksekusi tool gagal.
1941
1942```python theme={null}
1943class PostToolUseFailureHookInput(BaseHookInput):
1944 hook_event_name: Literal["PostToolUseFailure"]
1945 tool_name: str
1946 tool_input: dict[str, Any]
1947 tool_use_id: str
1948 error: str
1949 is_interrupt: NotRequired[bool]
1950 agent_id: NotRequired[str]
1951 agent_type: NotRequired[str]
1952```
1953
1954| Field | Tipe | Deskripsi |
1955| :---------------- | :------------------------------ | :----------------------------------------------------------- |
1956| `hook_event_name` | `Literal["PostToolUseFailure"]` | Selalu "PostToolUseFailure" |
1957| `tool_name` | `str` | Nama tool yang gagal |
1958| `tool_input` | `dict[str, Any]` | Parameter input yang digunakan |
1959| `tool_use_id` | `str` | Pengenal unik untuk penggunaan tool ini |
1960| `error` | `str` | Pesan error dari eksekusi yang gagal |
1961| `is_interrupt` | `bool` (opsional) | Apakah kegagalan disebabkan oleh interrupt |
1962| `agent_id` | `str` (opsional) | Pengenal subagent, ada ketika hook menyala di dalam subagent |
1963| `agent_type` | `str` (opsional) | Tipe subagent, ada ketika hook menyala di dalam subagent |
1964
1965### `UserPromptSubmitHookInput`
1966
1967Data input untuk event hook `UserPromptSubmit`.
1968
1969```python theme={null}
1970class UserPromptSubmitHookInput(BaseHookInput):
1971 hook_event_name: Literal["UserPromptSubmit"]
1972 prompt: str
1973```
1974
1975| Field | Tipe | Deskripsi |
1976| :---------------- | :---------------------------- | :------------------------------ |
1977| `hook_event_name` | `Literal["UserPromptSubmit"]` | Selalu "UserPromptSubmit" |
1978| `prompt` | `str` | Prompt yang dikirimkan pengguna |
1979
1980### `StopHookInput`
1981
1982Data input untuk event hook `Stop`.
1983
1984```python theme={null}
1985class StopHookInput(BaseHookInput):
1986 hook_event_name: Literal["Stop"]
1987 stop_hook_active: bool
1988```
1989
1990| Field | Tipe | Deskripsi |
1991| :----------------- | :---------------- | :--------------------- |
1992| `hook_event_name` | `Literal["Stop"]` | Selalu "Stop" |
1993| `stop_hook_active` | `bool` | Apakah stop hook aktif |
1994
1995### `SubagentStopHookInput`
1996
1997Data input untuk event hook `SubagentStop`.
1998
1999```python theme={null}
2000class SubagentStopHookInput(BaseHookInput):
2001 hook_event_name: Literal["SubagentStop"]
2002 stop_hook_active: bool
2003 agent_id: str
2004 agent_transcript_path: str
2005 agent_type: str
2006```
2007
2008| Field | Tipe | Deskripsi |
2009| :---------------------- | :------------------------ | :------------------------------- |
2010| `hook_event_name` | `Literal["SubagentStop"]` | Selalu "SubagentStop" |
2011| `stop_hook_active` | `bool` | Apakah stop hook aktif |
2012| `agent_id` | `str` | Pengenal unik untuk subagent |
2013| `agent_transcript_path` | `str` | Jalur ke file transkrip subagent |
2014| `agent_type` | `str` | Tipe subagent |
2015
2016### `PreCompactHookInput`
2017
2018Data input untuk event hook `PreCompact`.
2019
2020```python theme={null}
2021class PreCompactHookInput(BaseHookInput):
2022 hook_event_name: Literal["PreCompact"]
2023 trigger: Literal["manual", "auto"]
2024 custom_instructions: str | None
2025```
2026
2027| Field | Tipe | Deskripsi |
2028| :-------------------- | :-------------------------- | :------------------------------- |
2029| `hook_event_name` | `Literal["PreCompact"]` | Selalu "PreCompact" |
2030| `trigger` | `Literal["manual", "auto"]` | Apa yang memicu pemadatan |
2031| `custom_instructions` | `str \| None` | Instruksi kustom untuk pemadatan |
2032
2033### `NotificationHookInput`
2034
2035Data input untuk event hook `Notification`.
2036
2037```python theme={null}
2038class NotificationHookInput(BaseHookInput):
2039 hook_event_name: Literal["Notification"]
2040 message: str
2041 title: NotRequired[str]
2042 notification_type: str
2043```
2044
2045| Field | Tipe | Deskripsi |
2046| :------------------ | :------------------------ | :---------------------- |
2047| `hook_event_name` | `Literal["Notification"]` | Selalu "Notification" |
2048| `message` | `str` | Konten pesan notifikasi |
2049| `title` | `str` (opsional) | Judul notifikasi |
2050| `notification_type` | `str` | Tipe notifikasi |
2051
2052### `SubagentStartHookInput`
2053
2054Data input untuk event hook `SubagentStart`.
2055
2056```python theme={null}
2057class SubagentStartHookInput(BaseHookInput):
2058 hook_event_name: Literal["SubagentStart"]
2059 agent_id: str
2060 agent_type: str
2061```
2062
2063| Field | Tipe | Deskripsi |
2064| :---------------- | :------------------------- | :--------------------------- |
2065| `hook_event_name` | `Literal["SubagentStart"]` | Selalu "SubagentStart" |
2066| `agent_id` | `str` | Pengenal unik untuk subagent |
2067| `agent_type` | `str` | Tipe subagent |
2068
2069### `PermissionRequestHookInput`
2070
2071Data input untuk event hook `PermissionRequest`. Memungkinkan hooks untuk menangani keputusan izin secara programatis.
2072
2073```python theme={null}
2074class PermissionRequestHookInput(BaseHookInput):
2075 hook_event_name: Literal["PermissionRequest"]
2076 tool_name: str
2077 tool_input: dict[str, Any]
2078 permission_suggestions: NotRequired[list[Any]]
2079```
2080
2081| Field | Tipe | Deskripsi |
2082| :----------------------- | :----------------------------- | :---------------------------- |
2083| `hook_event_name` | `Literal["PermissionRequest"]` | Selalu "PermissionRequest" |
2084| `tool_name` | `str` | Nama tool yang meminta izin |
2085| `tool_input` | `dict[str, Any]` | Parameter input untuk tool |
2086| `permission_suggestions` | `list[Any]` (opsional) | Saran pembaruan izin dari CLI |
2087
2088### `HookJSONOutput`
2089
2090Tipe union untuk nilai pengembalian callback hook.
2091
2092```python theme={null}
2093HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutput
2094```
2095
2096#### `SyncHookJSONOutput`
2097
2098Output hook sinkron dengan field kontrol dan keputusan.
2099
2100```python theme={null}
2101class SyncHookJSONOutput(TypedDict):
2102 # Control fields
2103 continue_: NotRequired[bool] # Whether to proceed (default: True)
2104 suppressOutput: NotRequired[bool] # Hide stdout from transcript
2105 stopReason: NotRequired[str] # Message when continue is False
2106
2107 # Decision fields
2108 decision: NotRequired[Literal["block"]]
2109 systemMessage: NotRequired[str] # Warning message for user
2110 reason: NotRequired[str] # Feedback for Claude
2111
2112 # Hook-specific output
2113 hookSpecificOutput: NotRequired[HookSpecificOutput]
2114```
2115
2116<Note>
2117 Gunakan `continue_` (dengan underscore) dalam kode Python. Ini secara otomatis dikonversi ke `continue` ketika dikirim ke CLI.
2118</Note>
2119
2120#### `HookSpecificOutput`
2121
2122`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](/id/agent-sdk/hooks#outputs).
2123
2124Union yang dibedakan dari tipe output spesifik event. Field `hookEventName` menentukan field mana yang valid.
2125
2126```python theme={null}
2127class PreToolUseHookSpecificOutput(TypedDict):
2128 hookEventName: Literal["PreToolUse"]
2129 permissionDecision: NotRequired[Literal["allow", "deny", "ask"]]
2130 permissionDecisionReason: NotRequired[str]
2131 updatedInput: NotRequired[dict[str, Any]]
2132 additionalContext: NotRequired[str]
2133
2134
2135class PostToolUseHookSpecificOutput(TypedDict):
2136 hookEventName: Literal["PostToolUse"]
2137 additionalContext: NotRequired[str]
2138 updatedMCPToolOutput: NotRequired[Any]
2139
2140
2141class PostToolUseFailureHookSpecificOutput(TypedDict):
2142 hookEventName: Literal["PostToolUseFailure"]
2143 additionalContext: NotRequired[str]
2144
2145
2146class UserPromptSubmitHookSpecificOutput(TypedDict):
2147 hookEventName: Literal["UserPromptSubmit"]
2148 additionalContext: NotRequired[str]
2149
2150
2151class NotificationHookSpecificOutput(TypedDict):
2152 hookEventName: Literal["Notification"]
2153 additionalContext: NotRequired[str]
2154
2155
2156class SubagentStartHookSpecificOutput(TypedDict):
2157 hookEventName: Literal["SubagentStart"]
2158 additionalContext: NotRequired[str]
2159
2160
2161class PermissionRequestHookSpecificOutput(TypedDict):
2162 hookEventName: Literal["PermissionRequest"]
2163 decision: dict[str, Any]
2164
2165
2166HookSpecificOutput = (
2167 PreToolUseHookSpecificOutput
2168 | PostToolUseHookSpecificOutput
2169 | PostToolUseFailureHookSpecificOutput
2170 | UserPromptSubmitHookSpecificOutput
2171 | NotificationHookSpecificOutput
2172 | SubagentStartHookSpecificOutput
2173 | PermissionRequestHookSpecificOutput
2174)
2175```
2176
2177#### `AsyncHookJSONOutput`
2178
2179Output hook async yang menunda eksekusi hook.
2180
2181```python theme={null}
2182class AsyncHookJSONOutput(TypedDict):
2183 async_: Literal[True] # Set to True to defer execution
2184 asyncTimeout: NotRequired[int] # Timeout in milliseconds
2185```
2186
2187<Note>
2188 Gunakan `async_` (dengan underscore) dalam kode Python. Ini secara otomatis dikonversi ke `async` ketika dikirim ke CLI.
2189</Note>
2190
2191### Contoh Penggunaan Hook
2192
2193Contoh 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.
2194
2195```python theme={null}
2196from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher, HookContext
2197from typing import Any
2198
2199
2200async def validate_bash_command(
2201 input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
2202) -> dict[str, Any]:
2203 """Validate and potentially block dangerous bash commands."""
2204 if input_data["tool_name"] == "Bash":
2205 command = input_data["tool_input"].get("command", "")
2206 if "rm -rf /" in command:
2207 return {
2208 "hookSpecificOutput": {
2209 "hookEventName": "PreToolUse",
2210 "permissionDecision": "deny",
2211 "permissionDecisionReason": "Dangerous command blocked",
2212 }
2213 }
2214 return {}
2215
2216
2217async def log_tool_use(
2218 input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
2219) -> dict[str, Any]:
2220 """Log all tool usage for auditing."""
2221 print(f"Tool used: {input_data.get('tool_name')}")
2222 return {}
2223
2224
2225options = ClaudeAgentOptions(
2226 hooks={
2227 "PreToolUse": [
2228 HookMatcher(
2229 matcher="Bash", hooks=[validate_bash_command], timeout=120
2230 ), # 2 min for validation
2231 HookMatcher(
2232 hooks=[log_tool_use]
2233 ), # Applies to all tools (default 60s timeout)
2234 ],
2235 "PostToolUse": [HookMatcher(hooks=[log_tool_use])],
2236 }
2237)
2238
2239async for message in query(prompt="Analyze this codebase", options=options):
2240 print(message)
2241```
2242
2243## Tipe Input/Output Tool
2244
2245Dokumentasi 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.
2246
2247### Agent
2248
2249**Nama tool:** `Agent` (sebelumnya `Task`, yang masih diterima sebagai alias)
2250
2251**Input:**
2252
2253```python theme={null}
2254{
2255 "description": str, # A short (3-5 word) description of the task
2256 "prompt": str, # The task for the agent to perform
2257 "subagent_type": str, # The type of specialized agent to use
2258}
2259```
2260
2261**Output:**
2262
2263```python theme={null}
2264{
2265 "result": str, # Final result from the subagent
2266 "usage": dict | None, # Token usage statistics
2267 "total_cost_usd": float | None, # Estimated total cost in USD
2268 "duration_ms": int | None, # Execution duration in milliseconds
2269}
2270```
2271
2272### AskUserQuestion
2273
2274**Nama tool:** `AskUserQuestion`
2275
2276Mengajukan pertanyaan klarifikasi kepada pengguna selama eksekusi. Lihat [Handle approvals and user input](/id/agent-sdk/user-input#handle-clarifying-questions) untuk detail penggunaan.
2277
2278**Input:**
2279
2280```python theme={null}
2281{
2282 "questions": [ # Questions to ask the user (1-4 questions)
2283 {
2284 "question": str, # The complete question to ask the user
2285 "header": str, # Very short label displayed as a chip/tag (max 12 chars)
2286 "options": [ # The available choices (2-4 options)
2287 {
2288 "label": str, # Display text for this option (1-5 words)
2289 "description": str, # Explanation of what this option means
2290 }
2291 ],
2292 "multiSelect": bool, # Set to true to allow multiple selections
2293 }
2294 ],
2295 "answers": dict | None, # User answers populated by the permission system
2296}
2297```
2298
2299**Output:**
2300
2301```python theme={null}
2302{
2303 "questions": [ # The questions that were asked
2304 {
2305 "question": str,
2306 "header": str,
2307 "options": [{"label": str, "description": str}],
2308 "multiSelect": bool,
2309 }
2310 ],
2311 "answers": dict[str, str], # Maps question text to answer string
2312 # Multi-select answers are comma-separated
2313}
2314```
2315
2316### Bash
2317
2318**Nama tool:** `Bash`
2319
2320**Input:**
2321
2322```python theme={null}
2323{
2324 "command": str, # The command to execute
2325 "timeout": int | None, # Optional timeout in milliseconds (max 600000)
2326 "description": str | None, # Clear, concise description (5-10 words)
2327 "run_in_background": bool | None, # Set to true to run in background
2328}
2329```
2330
2331**Output:**
2332
2333```python theme={null}
2334{
2335 "output": str, # Combined stdout and stderr output
2336 "exitCode": int, # Exit code of the command
2337 "killed": bool | None, # Whether command was killed due to timeout
2338 "shellId": str | None, # Shell ID for background processes
2339}
2340```
2341
2342### Monitor
2343
2344**Nama tool:** `Monitor`
2345
2346Menjalankan 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](/id/tools-reference#monitor-tool) untuk perilaku dan ketersediaan penyedia.
2347
2348**Input:**
2349
2350```python theme={null}
2351{
2352 "command": str, # Shell script; each stdout line is an event, exit ends the watch
2353 "description": str, # Short description shown in notifications
2354 "timeout_ms": int | None, # Kill after this deadline (default 300000, max 3600000)
2355 "persistent": bool | None, # Run for the lifetime of the session; stop with TaskStop
2356}
2357```
2358
2359**Output:**
2360
2361```python theme={null}
2362{
2363 "taskId": str, # ID of the background monitor task
2364 "timeoutMs": int, # Timeout deadline in milliseconds
2365 "persistent": bool | None, # True when running until TaskStop or session end
2366}
2367```
2368
2369### Edit
2370
2371**Nama tool:** `Edit`
2372
2373**Input:**
2374
2375```python theme={null}
2376{
2377 "file_path": str, # The absolute path to the file to modify
2378 "old_string": str, # The text to replace
2379 "new_string": str, # The text to replace it with
2380 "replace_all": bool | None, # Replace all occurrences (default False)
2381}
2382```
2383
2384**Output:**
2385
2386```python theme={null}
2387{
2388 "message": str, # Confirmation message
2389 "replacements": int, # Number of replacements made
2390 "file_path": str, # File path that was edited
2391}
2392```
2393
2394### Read
2395
2396**Nama tool:** `Read`
2397
2398**Input:**
2399
2400```python theme={null}
2401{
2402 "file_path": str, # The absolute path to the file to read
2403 "offset": int | None, # The line number to start reading from
2404 "limit": int | None, # The number of lines to read
2405}
2406```
2407
2408**Output (File teks):**
2409
2410```python theme={null}
2411{
2412 "content": str, # File contents with line numbers
2413 "total_lines": int, # Total number of lines in file
2414 "lines_returned": int, # Lines actually returned
2415}
2416```
2417
2418**Output (Gambar):**
2419
2420```python theme={null}
2421{
2422 "image": str, # Base64 encoded image data
2423 "mime_type": str, # Image MIME type
2424 "file_size": int, # File size in bytes
2425}
2426```
2427
2428### Write
2429
2430**Nama tool:** `Write`
2431
2432**Input:**
2433
2434```python theme={null}
2435{
2436 "file_path": str, # The absolute path to the file to write
2437 "content": str, # The content to write to the file
2438}
2439```
2440
2441**Output:**
2442
2443```python theme={null}
2444{
2445 "message": str, # Success message
2446 "bytes_written": int, # Number of bytes written
2447 "file_path": str, # File path that was written
2448}
2449```
2450
2451### Glob
2452
2453**Nama tool:** `Glob`
2454
2455**Input:**
2456
2457```python theme={null}
2458{
2459 "pattern": str, # The glob pattern to match files against
2460 "path": str | None, # The directory to search in (defaults to cwd)
2461}
2462```
2463
2464**Output:**
2465
2466```python theme={null}
2467{
2468 "matches": list[str], # Array of matching file paths
2469 "count": int, # Number of matches found
2470 "search_path": str, # Search directory used
2471}
2472```
2473
2474### Grep
2475
2476**Nama tool:** `Grep`
2477
2478**Input:**
2479
2480```python theme={null}
2481{
2482 "pattern": str, # The regular expression pattern
2483 "path": str | None, # File or directory to search in
2484 "glob": str | None, # Glob pattern to filter files
2485 "type": str | None, # File type to search
2486 "output_mode": str | None, # "content", "files_with_matches", or "count"
2487 "-i": bool | None, # Case insensitive search
2488 "-n": bool | None, # Show line numbers
2489 "-B": int | None, # Lines to show before each match
2490 "-A": int | None, # Lines to show after each match
2491 "-C": int | None, # Lines to show before and after
2492 "head_limit": int | None, # Limit output to first N lines/entries
2493 "multiline": bool | None, # Enable multiline mode
2494}
2495```
2496
2497**Output (content mode):**
2498
2499```python theme={null}
2500{
2501 "matches": [
2502 {
2503 "file": str,
2504 "line_number": int | None,
2505 "line": str,
2506 "before_context": list[str] | None,
2507 "after_context": list[str] | None,
2508 }
2509 ],
2510 "total_matches": int,
2511}
2512```
2513
2514**Output (files\_with\_matches mode):**
2515
2516```python theme={null}
2517{
2518 "files": list[str], # Files containing matches
2519 "count": int, # Number of files with matches
2520}
2521```
2522
2523### NotebookEdit
2524
2525**Nama tool:** `NotebookEdit`
2526
2527**Input:**
2528
2529```python theme={null}
2530{
2531 "notebook_path": str, # Absolute path to the Jupyter notebook
2532 "cell_id": str | None, # The ID of the cell to edit
2533 "new_source": str, # The new source for the cell
2534 "cell_type": "code" | "markdown" | None, # The type of the cell
2535 "edit_mode": "replace" | "insert" | "delete" | None, # Edit operation type
2536}
2537```
2538
2539**Output:**
2540
2541```python theme={null}
2542{
2543 "message": str, # Success message
2544 "edit_type": "replaced" | "inserted" | "deleted", # Type of edit performed
2545 "cell_id": str | None, # Cell ID that was affected
2546 "total_cells": int, # Total cells in notebook after edit
2547}
2548```
2549
2550### WebFetch
2551
2552**Nama tool:** `WebFetch`
2553
2554**Input:**
2555
2556```python theme={null}
2557{
2558 "url": str, # The URL to fetch content from
2559 "prompt": str, # The prompt to run on the fetched content
2560}
2561```
2562
2563**Output:**
2564
2565```python theme={null}
2566{
2567 "response": str, # AI model's response to the prompt
2568 "url": str, # URL that was fetched
2569 "final_url": str | None, # Final URL after redirects
2570 "status_code": int | None, # HTTP status code
2571}
2572```
2573
2574### WebSearch
2575
2576**Nama tool:** `WebSearch`
2577
2578**Input:**
2579
2580```python theme={null}
2581{
2582 "query": str, # The search query to use
2583 "allowed_domains": list[str] | None, # Only include results from these domains
2584 "blocked_domains": list[str] | None, # Never include results from these domains
2585}
2586```
2587
2588**Output:**
2589
2590```python theme={null}
2591{
2592 "results": [{"title": str, "url": str, "snippet": str, "metadata": dict | None}],
2593 "total_results": int,
2594 "query": str,
2595}
2596```
2597
2598### TodoWrite
2599
2600**Nama tool:** `TodoWrite`
2601
2602**Input:**
2603
2604```python theme={null}
2605{
2606 "todos": [
2607 {
2608 "content": str, # The task description
2609 "status": "pending" | "in_progress" | "completed", # Task status
2610 "activeForm": str, # Active form of the description
2611 }
2612 ]
2613}
2614```
2615
2616**Output:**
2617
2618```python theme={null}
2619{
2620 "message": str, # Success message
2621 "stats": {"total": int, "pending": int, "in_progress": int, "completed": int},
2622}
2623```
2624
2625### BashOutput
2626
2627**Nama tool:** `BashOutput`
2628
2629**Input:**
2630
2631```python theme={null}
2632{
2633 "bash_id": str, # The ID of the background shell
2634 "filter": str | None, # Optional regex to filter output lines
2635}
2636```
2637
2638**Output:**
2639
2640```python theme={null}
2641{
2642 "output": str, # New output since last check
2643 "status": "running" | "completed" | "failed", # Current shell status
2644 "exitCode": int | None, # Exit code when completed
2645}
2646```
2647
2648### KillBash
2649
2650**Nama tool:** `KillBash`
2651
2652**Input:**
2653
2654```python theme={null}
2655{
2656 "shell_id": str # The ID of the background shell to kill
2657}
2658```
2659
2660**Output:**
2661
2662```python theme={null}
2663{
2664 "message": str, # Success message
2665 "shell_id": str, # ID of the killed shell
2666}
2667```
2668
2669### ExitPlanMode
2670
2671**Nama tool:** `ExitPlanMode`
2672
2673**Input:**
2674
2675```python theme={null}
2676{
2677 "plan": str # The plan to run by the user for approval
2678}
2679```
2680
2681**Output:**
2682
2683```python theme={null}
2684{
2685 "message": str, # Confirmation message
2686 "approved": bool | None, # Whether user approved the plan
2687}
2688```
2689
2690### ListMcpResources
2691
2692**Nama tool:** `ListMcpResources`
2693
2694**Input:**
2695
2696```python theme={null}
2697{
2698 "server": str | None # Optional server name to filter resources by
2699}
2700```
2701
2702**Output:**
2703
2704```python theme={null}
2705{
2706 "resources": [
2707 {
2708 "uri": str,
2709 "name": str,
2710 "description": str | None,
2711 "mimeType": str | None,
2712 "server": str,
2713 }
2714 ],
2715 "total": int,
2716}
2717```
2718
2719### ReadMcpResource
2720
2721**Nama tool:** `ReadMcpResource`
2722
2723**Input:**
2724
2725```python theme={null}
2726{
2727 "server": str, # The MCP server name
2728 "uri": str, # The resource URI to read
2729}
2730```
2731
2732**Output:**
2733
2734```python theme={null}
2735{
2736 "contents": [
2737 {"uri": str, "mimeType": str | None, "text": str | None, "blob": str | None}
2738 ],
2739 "server": str,
2740}
2741```
2742
2743## Fitur Lanjutan dengan ClaudeSDKClient
2744
2745### Membangun Antarmuka Percakapan Berkelanjutan
2746
2747```python theme={null}
2748from claude_agent_sdk import (
2749 ClaudeSDKClient,
2750 ClaudeAgentOptions,
2751 AssistantMessage,
2752 TextBlock,
2753)
2754import asyncio
2755
2756
2757class ConversationSession:
2758 """Maintains a single conversation session with Claude."""
2759
2760 def __init__(self, options: ClaudeAgentOptions | None = None):
2761 self.client = ClaudeSDKClient(options)
2762 self.turn_count = 0
2763
2764 async def start(self):
2765 await self.client.connect()
2766 print("Starting conversation session. Claude will remember context.")
2767 print(
2768 "Commands: 'exit' to quit, 'interrupt' to stop current task, 'new' for new session"
2769 )
2770
2771 while True:
2772 user_input = input(f"\n[Turn {self.turn_count + 1}] You: ")
2773
2774 if user_input.lower() == "exit":
2775 break
2776 elif user_input.lower() == "interrupt":
2777 await self.client.interrupt()
2778 print("Task interrupted!")
2779 continue
2780 elif user_input.lower() == "new":
2781 # Disconnect and reconnect for a fresh session
2782 await self.client.disconnect()
2783 await self.client.connect()
2784 self.turn_count = 0
2785 print("Started new conversation session (previous context cleared)")
2786 continue
2787
2788 # Send message - the session retains all previous messages
2789 await self.client.query(user_input)
2790 self.turn_count += 1
2791
2792 # Process response
2793 print(f"[Turn {self.turn_count}] Claude: ", end="")
2794 async for message in self.client.receive_response():
2795 if isinstance(message, AssistantMessage):
2796 for block in message.content:
2797 if isinstance(block, TextBlock):
2798 print(block.text, end="")
2799 print() # New line after response
2800
2801 await self.client.disconnect()
2802 print(f"Conversation ended after {self.turn_count} turns.")
2803
2804
2805async def main():
2806 options = ClaudeAgentOptions(
2807 allowed_tools=["Read", "Write", "Bash"], permission_mode="acceptEdits"
2808 )
2809 session = ConversationSession(options)
2810 await session.start()
2811
2812
2813# Example conversation:
2814# Turn 1 - You: "Create a file called hello.py"
2815# Turn 1 - Claude: "I'll create a hello.py file for you..."
2816# Turn 2 - You: "What's in that file?"
2817# Turn 2 - Claude: "The hello.py file I just created contains..." (remembers!)
2818# Turn 3 - You: "Add a main function to it"
2819# Turn 3 - Claude: "I'll add a main function to hello.py..." (knows which file!)
2820
2821asyncio.run(main())
2822```
2823
2824### Menggunakan Hooks untuk Modifikasi Perilaku
2825
2826```python theme={null}
2827from claude_agent_sdk import (
2828 ClaudeSDKClient,
2829 ClaudeAgentOptions,
2830 HookMatcher,
2831 HookContext,
2832)
2833import asyncio
2834from typing import Any
2835
2836
2837async def pre_tool_logger(
2838 input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
2839) -> dict[str, Any]:
2840 """Log all tool usage before execution."""
2841 tool_name = input_data.get("tool_name", "unknown")
2842 print(f"[PRE-TOOL] About to use: {tool_name}")
2843
2844 # You can modify or block the tool execution here
2845 if tool_name == "Bash" and "rm -rf" in str(input_data.get("tool_input", {})):
2846 return {
2847 "hookSpecificOutput": {
2848 "hookEventName": "PreToolUse",
2849 "permissionDecision": "deny",
2850 "permissionDecisionReason": "Dangerous command blocked",
2851 }
2852 }
2853 return {}
2854
2855
2856async def post_tool_logger(
2857 input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
2858) -> dict[str, Any]:
2859 """Log results after tool execution."""
2860 tool_name = input_data.get("tool_name", "unknown")
2861 print(f"[POST-TOOL] Completed: {tool_name}")
2862 return {}
2863
2864
2865async def user_prompt_modifier(
2866 input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
2867) -> dict[str, Any]:
2868 """Add context to user prompts."""
2869 original_prompt = input_data.get("prompt", "")
2870
2871 # Add a timestamp as additional context for Claude to see
2872 from datetime import datetime
2873
2874 timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
2875
2876 return {
2877 "hookSpecificOutput": {
2878 "hookEventName": "UserPromptSubmit",
2879 "additionalContext": f"[Submitted at {timestamp}] Original prompt: {original_prompt}",
2880 }
2881 }
2882
2883
2884async def main():
2885 options = ClaudeAgentOptions(
2886 hooks={
2887 "PreToolUse": [
2888 HookMatcher(hooks=[pre_tool_logger]),
2889 HookMatcher(matcher="Bash", hooks=[pre_tool_logger]),
2890 ],
2891 "PostToolUse": [HookMatcher(hooks=[post_tool_logger])],
2892 "UserPromptSubmit": [HookMatcher(hooks=[user_prompt_modifier])],
2893 },
2894 allowed_tools=["Read", "Write", "Bash"],
2895 )
2896
2897 async with ClaudeSDKClient(options=options) as client:
2898 await client.query("List files in current directory")
2899
2900 async for message in client.receive_response():
2901 # Hooks will automatically log tool usage
2902 pass
2903
2904
2905asyncio.run(main())
2906```
2907
2908### Pemantauan Kemajuan Real-time
2909
2910```python theme={null}
2911from claude_agent_sdk import (
2912 ClaudeSDKClient,
2913 ClaudeAgentOptions,
2914 AssistantMessage,
2915 ToolUseBlock,
2916 ToolResultBlock,
2917 TextBlock,
2918)
2919import asyncio
2920
2921
2922async def monitor_progress():
2923 options = ClaudeAgentOptions(
2924 allowed_tools=["Write", "Bash"], permission_mode="acceptEdits"
2925 )
2926
2927 async with ClaudeSDKClient(options=options) as client:
2928 await client.query("Create 5 Python files with different sorting algorithms")
2929
2930 # Monitor progress in real-time
2931 async for message in client.receive_response():
2932 if isinstance(message, AssistantMessage):
2933 for block in message.content:
2934 if isinstance(block, ToolUseBlock):
2935 if block.name == "Write":
2936 file_path = block.input.get("file_path", "")
2937 print(f"Creating: {file_path}")
2938 elif isinstance(block, ToolResultBlock):
2939 print("Completed tool execution")
2940 elif isinstance(block, TextBlock):
2941 print(f"Claude says: {block.text[:100]}...")
2942
2943 print("Task completed!")
2944
2945
2946asyncio.run(monitor_progress())
2947```
2948
2949## Contoh Penggunaan
2950
2951### Operasi file dasar (menggunakan query)
2952
2953```python theme={null}
2954from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ToolUseBlock
2955import asyncio
2956
2957
2958async def create_project():
2959 options = ClaudeAgentOptions(
2960 allowed_tools=["Read", "Write", "Bash"],
2961 permission_mode="acceptEdits",
2962 cwd="/home/user/project",
2963 )
2964
2965 async for message in query(
2966 prompt="Create a Python project structure with setup.py", options=options
2967 ):
2968 if isinstance(message, AssistantMessage):
2969 for block in message.content:
2970 if isinstance(block, ToolUseBlock):
2971 print(f"Using tool: {block.name}")
2972
2973
2974asyncio.run(create_project())
2975```
2976
2977### Penanganan error
2978
2979```python theme={null}
2980from claude_agent_sdk import query, CLINotFoundError, ProcessError, CLIJSONDecodeError
2981
2982try:
2983 async for message in query(prompt="Hello"):
2984 print(message)
2985except CLINotFoundError:
2986 print(
2987 "Claude Code CLI not found. Try reinstalling: pip install --force-reinstall claude-agent-sdk"
2988 )
2989except ProcessError as e:
2990 print(f"Process failed with exit code: {e.exit_code}")
2991except CLIJSONDecodeError as e:
2992 print(f"Failed to parse response: {e}")
2993```
2994
2995### Mode streaming dengan klien
2996
2997```python theme={null}
2998from claude_agent_sdk import ClaudeSDKClient
2999import asyncio
3000
3001
3002async def interactive_session():
3003 async with ClaudeSDKClient() as client:
3004 # Send initial message
3005 await client.query("What's the weather like?")
3006
3007 # Process responses
3008 async for msg in client.receive_response():
3009 print(msg)
3010
3011 # Send follow-up
3012 await client.query("Tell me more about that")
3013
3014 # Process follow-up response
3015 async for msg in client.receive_response():
3016 print(msg)
3017
3018
3019asyncio.run(interactive_session())
3020```
3021
3022### Menggunakan tools kustom dengan ClaudeSDKClient
3023
3024```python theme={null}
3025from claude_agent_sdk import (
3026 ClaudeSDKClient,
3027 ClaudeAgentOptions,
3028 tool,
3029 create_sdk_mcp_server,
3030 AssistantMessage,
3031 TextBlock,
3032)
3033import asyncio
3034from typing import Any
3035
3036
3037# Define custom tools with @tool decorator
3038@tool("calculate", "Perform mathematical calculations", {"expression": str})
3039async def calculate(args: dict[str, Any]) -> dict[str, Any]:
3040 try:
3041 result = eval(args["expression"], {"__builtins__": {}})
3042 return {"content": [{"type": "text", "text": f"Result: {result}"}]}
3043 except Exception as e:
3044 return {
3045 "content": [{"type": "text", "text": f"Error: {str(e)}"}],
3046 "is_error": True,
3047 }
3048
3049
3050@tool("get_time", "Get current time", {})
3051async def get_time(args: dict[str, Any]) -> dict[str, Any]:
3052 from datetime import datetime
3053
3054 current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
3055 return {"content": [{"type": "text", "text": f"Current time: {current_time}"}]}
3056
3057
3058async def main():
3059 # Create SDK MCP server with custom tools
3060 my_server = create_sdk_mcp_server(
3061 name="utilities", version="1.0.0", tools=[calculate, get_time]
3062 )
3063
3064 # Configure options with the server
3065 options = ClaudeAgentOptions(
3066 mcp_servers={"utils": my_server},
3067 allowed_tools=["mcp__utils__calculate", "mcp__utils__get_time"],
3068 )
3069
3070 # Use ClaudeSDKClient for interactive tool usage
3071 async with ClaudeSDKClient(options=options) as client:
3072 await client.query("What's 123 * 456?")
3073
3074 # Process calculation response
3075 async for message in client.receive_response():
3076 if isinstance(message, AssistantMessage):
3077 for block in message.content:
3078 if isinstance(block, TextBlock):
3079 print(f"Calculation: {block.text}")
3080
3081 # Follow up with time query
3082 await client.query("What time is it now?")
3083
3084 async for message in client.receive_response():
3085 if isinstance(message, AssistantMessage):
3086 for block in message.content:
3087 if isinstance(block, TextBlock):
3088 print(f"Time: {block.text}")
3089
3090
3091asyncio.run(main())
3092```
3093
3094## Konfigurasi Sandbox
3095
3096### `SandboxSettings`
3097
3098Konfigurasi untuk perilaku sandbox. Gunakan ini untuk mengaktifkan sandboxing perintah dan mengonfigurasi pembatasan jaringan secara programatis.
3099
3100```python theme={null}
3101class SandboxSettings(TypedDict, total=False):
3102 enabled: bool
3103 autoAllowBashIfSandboxed: bool
3104 excludedCommands: list[str]
3105 allowUnsandboxedCommands: bool
3106 network: SandboxNetworkConfig
3107 ignoreViolations: SandboxIgnoreViolations
3108 enableWeakerNestedSandbox: bool
3109```
3110
3111| Properti | Tipe | Default | Deskripsi |
3112| :-------------------------- | :------------------------------------------------------ | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
3113| `enabled` | `bool` | `False` | Aktifkan mode sandbox untuk eksekusi perintah |
3114| `autoAllowBashIfSandboxed` | `bool` | `True` | Auto-approve perintah bash ketika sandbox diaktifkan |
3115| `excludedCommands` | `list[str]` | `[]` | Perintah yang selalu melewati pembatasan sandbox (misalnya, `["docker"]`). Ini berjalan tanpa sandbox secara otomatis tanpa keterlibatan model |
3116| `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](#permissions-fallback-for-unsandboxed-commands) |
3117| `network` | [`SandboxNetworkConfig`](#sandbox-network-config) | `None` | Konfigurasi sandbox spesifik jaringan |
3118| `ignoreViolations` | [`SandboxIgnoreViolations`](#sandbox-ignore-violations) | `None` | Konfigurasi pelanggaran sandbox mana yang akan diabaikan |
3119| `enableWeakerNestedSandbox` | `bool` | `False` | Aktifkan sandbox bersarang yang lebih lemah untuk kompatibilitas |
3120
3121#### Contoh penggunaan
3122
3123```python theme={null}
3124from claude_agent_sdk import query, ClaudeAgentOptions, SandboxSettings
3125
3126sandbox_settings: SandboxSettings = {
3127 "enabled": True,
3128 "autoAllowBashIfSandboxed": True,
3129 "network": {"allowLocalBinding": True},
3130}
3131
3132async for message in query(
3133 prompt="Build and test my project",
3134 options=ClaudeAgentOptions(sandbox=sandbox_settings),
3135):
3136 print(message)
3137```
3138
3139<Warning>
3140 **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.
3141</Warning>
3142
3143### `SandboxNetworkConfig`
3144
3145Konfigurasi spesifik jaringan untuk mode sandbox.
3146
3147```python theme={null}
3148class SandboxNetworkConfig(TypedDict, total=False):
3149 allowedDomains: list[str]
3150 deniedDomains: list[str]
3151 allowManagedDomainsOnly: bool
3152 allowUnixSockets: list[str]
3153 allowAllUnixSockets: bool
3154 allowLocalBinding: bool
3155 allowMachLookup: list[str]
3156 httpProxyPort: int
3157 socksProxyPort: int
3158```
3159
3160| Properti | Tipe | Default | Deskripsi |
3161| :------------------------ | :---------- | :------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
3162| `allowedDomains` | `list[str]` | `[]` | Nama domain yang dapat diakses oleh proses dalam sandbox |
3163| `deniedDomains` | `list[str]` | `[]` | Nama domain yang tidak dapat diakses oleh proses dalam sandbox. Mengambil prioritas atas `allowedDomains` |
3164| `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 |
3165| `allowUnixSockets` | `list[str]` | `[]` | Jalur Unix socket yang dapat diakses proses (misalnya, Docker socket) |
3166| `allowAllUnixSockets` | `bool` | `False` | Izinkan akses ke semua Unix socket |
3167| `allowLocalBinding` | `bool` | `False` | Izinkan proses untuk mengikat ke port lokal (misalnya, untuk dev server) |
3168| `allowMachLookup` | `list[str]` | `[]` | Hanya macOS: nama layanan XPC/Mach yang diizinkan. Mendukung wildcard di akhir |
3169| `httpProxyPort` | `int` | `None` | Port proxy HTTP untuk permintaan jaringan |
3170| `socksProxyPort` | `int` | `None` | Port proxy SOCKS untuk permintaan jaringan |
3171
3172<Note>
3173 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](https://en.wikipedia.org/wiki/Domain_fronting) dapat berpotensi melewatinya. Lihat [Batasan keamanan sandboxing](/id/sandboxing#security-limitations) untuk detail dan [Penyebaran aman](/id/agent-sdk/secure-deployment#traffic-forwarding) untuk mengonfigurasi proxy yang menghentikan TLS.
3174</Note>
3175
3176### `SandboxIgnoreViolations`
3177
3178Konfigurasi untuk mengabaikan pelanggaran sandbox tertentu.
3179
3180```python theme={null}
3181class SandboxIgnoreViolations(TypedDict, total=False):
3182 file: list[str]
3183 network: list[str]
3184```
3185
3186| Properti | Tipe | Default | Deskripsi |
3187| :-------- | :---------- | :------ | :-------------------------------------------- |
3188| `file` | `list[str]` | `[]` | Pola jalur file untuk mengabaikan pelanggaran |
3189| `network` | `list[str]` | `[]` | Pola jaringan untuk mengabaikan pelanggaran |
3190
3191### Fallback Izin untuk Perintah Tanpa Sandbox
3192
3193Ketika `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.
3194
3195<Note>
3196 **`excludedCommands` vs `allowUnsandboxedCommands`:**
3197
3198 * `excludedCommands`: Daftar statis perintah yang selalu melewati sandbox secara otomatis (misalnya, `["docker"]`). Model tidak memiliki kontrol atas ini.
3199 * `allowUnsandboxedCommands`: Memungkinkan model memutuskan saat runtime apakah akan meminta eksekusi tanpa sandbox dengan mengatur `dangerouslyDisableSandbox: True` dalam input tool.
3200</Note>
3201
3202```python theme={null}
3203from claude_agent_sdk import (
3204 query,
3205 ClaudeAgentOptions,
3206 HookMatcher,
3207 PermissionResultAllow,
3208 PermissionResultDeny,
3209 ToolPermissionContext,
3210)
3211
3212
3213async def can_use_tool(
3214 tool: str, input: dict, context: ToolPermissionContext
3215) -> PermissionResultAllow | PermissionResultDeny:
3216 # Check if the model is requesting to bypass the sandbox
3217 if tool == "Bash" and input.get("dangerouslyDisableSandbox"):
3218 # The model is requesting to run this command outside the sandbox
3219 print(f"Unsandboxed command requested: {input.get('command')}")
3220
3221 if is_command_authorized(input.get("command")):
3222 return PermissionResultAllow()
3223 return PermissionResultDeny(
3224 message="Command not authorized for unsandboxed execution"
3225 )
3226 return PermissionResultAllow()
3227
3228
3229# Required: dummy hook keeps the stream open for can_use_tool
3230async def dummy_hook(input_data, tool_use_id, context):
3231 return {"continue_": True}
3232
3233
3234async def prompt_stream():
3235 yield {
3236 "type": "user",
3237 "message": {"role": "user", "content": "Deploy my application"},
3238 }
3239
3240
3241async def main():
3242 async for message in query(
3243 prompt=prompt_stream(),
3244 options=ClaudeAgentOptions(
3245 sandbox={
3246 "enabled": True,
3247 "allowUnsandboxedCommands": True, # Model can request unsandboxed execution
3248 },
3249 permission_mode="default",
3250 can_use_tool=can_use_tool,
3251 hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]},
3252 ),
3253 ):
3254 print(message)
3255```
3256
3257Pola ini memungkinkan Anda untuk:
3258
3259* **Audit permintaan model**: Catat ketika model meminta eksekusi tanpa sandbox
3260* **Implementasikan allowlist**: Hanya izinkan perintah tertentu untuk berjalan tanpa sandbox
3261* **Tambahkan alur persetujuan**: Memerlukan otorisasi eksplisit untuk operasi istimewa
3262
3263<Warning>
3264 Perintah yang berjalan dengan `dangerouslyDisableSandbox: True` memiliki akses sistem penuh. Pastikan handler `can_use_tool` Anda memvalidasi permintaan ini dengan hati-hati.
3265
3266 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.
3267</Warning>
3268
3269## Lihat juga
3270
3271* [SDK overview](/id/agent-sdk/overview) - Konsep SDK umum
3272* [TypeScript SDK reference](/id/agent-sdk/typescript) - Dokumentasi SDK TypeScript
3273* [CLI reference](/id/cli-reference) - Antarmuka baris perintah
3274* [Common workflows](/id/common-workflows) - Panduan langkah demi langkah