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# Agent SDK 참조 - Python
6
7> Python Agent SDK의 완전한 API 참조로, 모든 함수, 타입 및 클래스를 포함합니다.
8
9## 설치
10
11```bash theme={null}
12pip install claude-agent-sdk
13```
14
15## `query()`와 `ClaudeSDKClient` 중 선택하기
16
17Python SDK는 Claude Code와 상호작용하는 두 가지 방법을 제공합니다.
18
19### 빠른 비교
20
21| 기능 | `query()` | `ClaudeSDKClient` |
22| :------------ | :--------- | :---------------- |
23| **세션** | 매번 새 세션 생성 | 동일한 세션 재사용 |
24| **대화** | 단일 교환 | 동일한 컨텍스트에서 여러 교환 |
25| **연결** | 자동으로 관리됨 | 수동 제어 |
26| **스트리밍 입력** | ✅ 지원됨 | ✅ 지원됨 |
27| **중단** | ❌ 지원 안 함 | ✅ 지원됨 |
28| **Hooks** | ✅ 지원됨 | ✅ 지원됨 |
29| **사용자 정의 도구** | ✅ 지원됨 | ✅ 지원됨 |
30| **대화 계속하기** | ❌ 매번 새 세션 | ✅ 대화 유지 |
31| **사용 사례** | 일회성 작업 | 지속적인 대화 |
32
33### `query()` 사용 시기 (매번 새 세션)
34
35**최적의 경우:**
36
37* 대화 기록이 필요 없는 일회성 질문
38* 이전 교환의 컨텍스트가 필요 없는 독립적인 작업
39* 간단한 자동화 스크립트
40* 매번 새로 시작하고 싶을 때
41
42### `ClaudeSDKClient` 사용 시기 (지속적인 대화)
43
44**최적의 경우:**
45
46* **대화 계속하기** - Claude가 컨텍스트를 기억해야 할 때
47* **후속 질문** - 이전 응답을 기반으로 구축
48* **대화형 애플리케이션** - 채팅 인터페이스, REPL
49* **응답 기반 로직** - 다음 작업이 Claude의 응답에 따라 달라질 때
50* **세션 제어** - 대화 수명 주기를 명시적으로 관리
51
52## 함수
53
54### `query()`
55
56Claude Code와의 각 상호작용을 위해 새 세션을 생성합니다. 메시지가 도착하면 생성하는 비동기 반복자를 반환합니다. `query()`에 대한 각 호출은 이전 상호작용의 메모리 없이 새로 시작합니다.
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#### 매개변수
68
69| 매개변수 | 타입 | 설명 |
70| :---------- | :--------------------------- | :-------------------------------------------------- |
71| `prompt` | `str \| AsyncIterable[dict]` | 문자열 또는 스트리밍 모드용 비동기 반복 가능 객체로서의 입력 프롬프트 |
72| `options` | `ClaudeAgentOptions \| None` | 선택적 구성 객체 (None인 경우 `ClaudeAgentOptions()`로 기본값 설정) |
73| `transport` | `Transport \| None` | CLI 프로세스와 통신하기 위한 선택적 사용자 정의 전송 |
74
75#### 반환값
76
77대화에서 메시지를 생성하는 `AsyncIterator[Message]`를 반환합니다.
78
79#### 예제 - 옵션 포함
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
102타입 안전성을 갖춘 MCP 도구를 정의하기 위한 데코레이터입니다.
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#### 매개변수
114
115| 매개변수 | 타입 | 설명 |
116| :------------- | :----------------------------------------------- | :------------------------------- |
117| `name` | `str` | 도구의 고유 식별자 |
118| `description` | `str` | 도구가 수행하는 작업에 대한 인간이 읽을 수 있는 설명 |
119| `input_schema` | `type \| dict[str, Any]` | 도구의 입력 매개변수를 정의하는 스키마 (아래 참조) |
120| `annotations` | [`ToolAnnotations`](#tool-annotations)` \| None` | 클라이언트에 동작 힌트를 제공하는 선택적 MCP 도구 주석 |
121
122#### 입력 스키마 옵션
123
1241. **간단한 타입 매핑** (권장):
125
126 ```python theme={null}
127 {"text": str, "count": int, "enabled": bool}
128 ```
129
1302. **JSON Schema 형식** (복잡한 검증용):
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#### 반환값
143
144도구 구현을 래핑하고 `SdkMcpTool` 인스턴스를 반환하는 데코레이터 함수입니다.
145
146#### 예제
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
160`mcp.types`에서 다시 내보낸 것입니다 (`from claude_agent_sdk import ToolAnnotations`로도 사용 가능). 모든 필드는 선택적 힌트이며, 클라이언트는 보안 결정을 위해 이에 의존해서는 안 됩니다.
161
162| 필드 | 타입 | 기본값 | 설명 |
163| :---------------- | :------------- | :------ | :---------------------------------------------------------------------------------- |
164| `title` | `str \| None` | `None` | 도구의 인간이 읽을 수 있는 제목 |
165| `readOnlyHint` | `bool \| None` | `False` | `True`인 경우, 도구는 환경을 수정하지 않습니다 |
166| `destructiveHint` | `bool \| None` | `True` | `True`인 경우, 도구는 파괴적인 업데이트를 수행할 수 있습니다 (`readOnlyHint`가 `False`일 때만 의미 있음) |
167| `idempotentHint` | `bool \| None` | `False` | `True`인 경우, 동일한 인수로 반복 호출해도 추가 효과가 없습니다 (`readOnlyHint`가 `False`일 때만 의미 있음) |
168| `openWorldHint` | `bool \| None` | `True` | `True`인 경우, 도구는 외부 엔티티와 상호작용합니다 (예: 웹 검색). `False`인 경우, 도구의 도메인은 폐쇄적입니다 (예: 메모리 도구) |
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
187Python 애플리케이션 내에서 실행되는 인프로세스 MCP 서버를 생성합니다.
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#### 매개변수
198
199| 매개변수 | 타입 | 기본값 | 설명 |
200| :-------- | :------------------------------ | :-------- | :-------------------------- |
201| `name` | `str` | - | 서버의 고유 식별자 |
202| `version` | `str` | `"1.0.0"` | 서버 버전 문자열 |
203| `tools` | `list[SdkMcpTool[Any]] \| None` | `None` | `@tool` 데코레이터로 생성된 도구 함수 목록 |
204
205#### 반환값
206
207`ClaudeAgentOptions.mcp_servers`에 전달할 수 있는 `McpSdkServerConfig` 객체를 반환합니다.
208
209#### 예제
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
240메타데이터가 포함된 과거 세션을 나열합니다. 프로젝트 디렉토리로 필터링하거나 모든 프로젝트의 세션을 나열합니다. 동기식이며 즉시 반환됩니다.
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#### 매개변수
251
252| 매개변수 | 타입 | 기본값 | 설명 |
253| :------------------ | :------------ | :----- | :------------------------------------------------------ |
254| `directory` | `str \| None` | `None` | 세션을 나열할 디렉토리. 생략하면 모든 프로젝트의 세션을 반환합니다 |
255| `limit` | `int \| None` | `None` | 반환할 최대 세션 수 |
256| `include_worktrees` | `bool` | `True` | `directory`가 git 저장소 내에 있을 때, 모든 worktree 경로의 세션을 포함합니다 |
257
258#### 반환 타입: `SDKSessionInfo`
259
260| 속성 | 타입 | 설명 |
261| :-------------- | :------------ | :-------------------------------------------------- |
262| `session_id` | `str` | 고유 세션 식별자 |
263| `summary` | `str` | 표시 제목: 사용자 정의 제목, 자동 생성된 요약 또는 첫 프롬프트 |
264| `last_modified` | `int` | 에포크 이후 마지막 수정 시간 (밀리초) |
265| `file_size` | `int \| None` | 세션 파일 크기 (바이트) (원격 저장소 백엔드의 경우 `None`) |
266| `custom_title` | `str \| None` | 사용자가 설정한 세션 제목 |
267| `first_prompt` | `str \| None` | 세션의 첫 번째 의미 있는 사용자 프롬프트 |
268| `git_branch` | `str \| None` | 세션 끝의 Git 브랜치 |
269| `cwd` | `str \| None` | 세션의 작업 디렉토리 |
270| `tag` | `str \| None` | 사용자가 설정한 세션 태그 ([`tag_session()`](#tag-session) 참조) |
271| `created_at` | `int \| None` | 에포크 이후 세션 생성 시간 (밀리초) |
272
273#### 예제
274
275프로젝트의 10개 최신 세션을 인쇄합니다. 결과는 `last_modified` 내림차순으로 정렬되므로 첫 번째 항목이 가장 최신입니다. `directory`를 생략하면 모든 프로젝트를 검색합니다.
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
286과거 세션에서 메시지를 검색합니다. 동기식이며 즉시 반환됩니다.
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#### 매개변수
298
299| 매개변수 | 타입 | 기본값 | 설명 |
300| :----------- | :------------ | :----- | :--------------------------------- |
301| `session_id` | `str` | 필수 | 메시지를 검색할 세션 ID |
302| `directory` | `str \| None` | `None` | 검색할 프로젝트 디렉토리. 생략하면 모든 프로젝트를 검색합니다 |
303| `limit` | `int \| None` | `None` | 반환할 최대 메시지 수 |
304| `offset` | `int` | `0` | 시작 부분에서 건너뛸 메시지 수 |
305
306#### 반환 타입: `SessionMessage`
307
308| 속성 | 타입 | 설명 |
309| :------------------- | :----------------------------- | :------------ |
310| `type` | `Literal["user", "assistant"]` | 메시지 역할 |
311| `uuid` | `str` | 고유 메시지 식별자 |
312| `session_id` | `str` | 세션 식별자 |
313| `message` | `Any` | 원본 메시지 콘텐츠 |
314| `parent_tool_use_id` | `None` | 향후 사용을 위해 예약됨 |
315
316#### 예제
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
330전체 프로젝트 디렉토리를 스캔하지 않고 ID로 단일 세션의 메타데이터를 읽습니다. 동기식이며 즉시 반환됩니다.
331
332```python theme={null}
333def get_session_info(
334 session_id: str,
335 directory: str | None = None,
336) -> SDKSessionInfo | None
337```
338
339#### 매개변수
340
341| 매개변수 | 타입 | 기본값 | 설명 |
342| :----------- | :------------ | :----- | :------------------------------------- |
343| `session_id` | `str` | 필수 | 조회할 세션의 UUID |
344| `directory` | `str \| None` | `None` | 프로젝트 디렉토리 경로. 생략하면 모든 프로젝트 디렉토리를 검색합니다 |
345
346[`SDKSessionInfo`](#return-type-sdk-session-info)를 반환하거나, 세션을 찾을 수 없으면 `None`을 반환합니다.
347
348#### 예제
349
350프로젝트 디렉토리를 스캔하지 않고 단일 세션의 메타데이터를 조회합니다. 이전 실행에서 세션 ID를 이미 가지고 있을 때 유용합니다.
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
362사용자 정의 제목 항목을 추가하여 세션의 이름을 바꿉니다. 반복 호출은 안전하며, 가장 최신 제목이 우선합니다. 동기식입니다.
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#### 매개변수
373
374| 매개변수 | 타입 | 기본값 | 설명 |
375| :----------- | :------------ | :----- | :------------------------------------- |
376| `session_id` | `str` | 필수 | 이름을 바꿀 세션의 UUID |
377| `title` | `str` | 필수 | 새 제목. 공백을 제거한 후 비어 있지 않아야 합니다 |
378| `directory` | `str \| None` | `None` | 프로젝트 디렉토리 경로. 생략하면 모든 프로젝트 디렉토리를 검색합니다 |
379
380`session_id`가 유효한 UUID가 아니거나 `title`이 비어 있으면 `ValueError`를 발생시킵니다. 세션을 찾을 수 없으면 `FileNotFoundError`를 발생시킵니다.
381
382#### 예제
383
384가장 최신 세션의 이름을 바꿔서 나중에 찾기 쉽게 합니다. 새 제목은 이후 읽기에서 [`SDKSessionInfo.custom_title`](#return-type-sdk-session-info)에 나타납니다.
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
396세션에 태그를 지정합니다. 태그를 지우려면 `None`을 전달합니다. 반복 호출은 안전하며, 가장 최신 태그가 우선합니다. 동기식입니다.
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#### 매개변수
407
408| 매개변수 | 타입 | 기본값 | 설명 |
409| :----------- | :------------ | :----- | :--------------------------------------- |
410| `session_id` | `str` | 필수 | 태그를 지정할 세션의 UUID |
411| `tag` | `str \| None` | 필수 | 태그 문자열 또는 지우려면 `None`. 저장하기 전에 유니코드 정규화됨 |
412| `directory` | `str \| None` | `None` | 프로젝트 디렉토리 경로. 생략하면 모든 프로젝트 디렉토리를 검색합니다 |
413
414`session_id`가 유효한 UUID가 아니거나 `tag`가 정규화 후 비어 있으면 `ValueError`를 발생시킵니다. 세션을 찾을 수 없으면 `FileNotFoundError`를 발생시킵니다.
415
416#### 예제
417
418세션에 태그를 지정한 다음, 나중에 읽을 때 해당 태그로 필터링합니다. 기존 태그를 지우려면 `None`을 전달합니다.
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## 클래스
433
434### `ClaudeSDKClient`
435
436**여러 교환에 걸쳐 대화 세션을 유지합니다.** 이것은 TypeScript SDK의 `query()` 함수가 내부적으로 작동하는 방식의 Python 동등물입니다 - 대화를 계속할 수 있는 클라이언트 객체를 생성합니다.
437
438#### 주요 기능
439
440* **세션 연속성**: 여러 `query()` 호출에 걸쳐 대화 컨텍스트 유지
441* **동일한 대화**: 세션이 이전 메시지를 유지합니다
442* **중단 지원**: 작업 중간에 실행을 중지할 수 있습니다
443* **명시적 수명 주기**: 세션이 시작되고 끝나는 시점을 제어합니다
444* **응답 기반 흐름**: 응답에 반응하고 후속 조치를 보낼 수 있습니다
445* **사용자 정의 도구 및 hooks**: 사용자 정의 도구 (`@tool` 데코레이터로 생성) 및 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#### 메서드
467
468| 메서드 | 설명 |
469| :---------------------------------------- | :----------------------------------------------------------------------------------------------------------- |
470| `__init__(options)` | 선택적 구성으로 클라이언트 초기화 |
471| `connect(prompt)` | 선택적 초기 프롬프트 또는 메시지 스트림으로 Claude에 연결 |
472| `query(prompt, session_id)` | 스트리밍 모드에서 새 요청 전송 |
473| `receive_messages()` | Claude의 모든 메시지를 비동기 반복자로 수신 |
474| `receive_response()` | ResultMessage를 포함하여 메시지 수신 |
475| `interrupt()` | 중단 신호 전송 (스트리밍 모드에서만 작동) |
476| `set_permission_mode(mode)` | 현재 세션의 권한 모드 변경 |
477| `set_model(model)` | 현재 세션의 모델 변경. 기본값으로 재설정하려면 `None` 전달 |
478| `rewind_files(user_message_id)` | 지정된 사용자 메시지의 상태로 파일 복원. `enable_file_checkpointing=True` 필요. [파일 체크포인팅](/ko/agent-sdk/file-checkpointing) 참조 |
479| `get_mcp_status()` | 구성된 모든 MCP 서버의 상태 가져오기. [`McpStatusResponse`](#mcp-status-response) 반환 |
480| `reconnect_mcp_server(server_name)` | 실패했거나 연결이 끊긴 MCP 서버에 다시 연결 시도 |
481| `toggle_mcp_server(server_name, enabled)` | 세션 중간에 MCP 서버 활성화 또는 비활성화. 비활성화하면 도구 제거 |
482| `stop_task(task_id)` | 실행 중인 백그라운드 작업 중지. 상태 `"stopped"`인 [`TaskNotificationMessage`](#task-notification-message)가 메시지 스트림에서 따릅니다 |
483| `get_server_info()` | 세션 ID 및 기능을 포함한 서버 정보 가져오기 |
484| `disconnect()` | Claude에서 연결 해제 |
485
486#### 컨텍스트 관리자 지원
487
488클라이언트는 자동 연결 관리를 위한 비동기 컨텍스트 관리자로 사용할 수 있습니다.
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> **중요:** 메시지를 반복할 때, asyncio 정리 문제를 일으킬 수 있으므로 `break`를 사용하여 조기에 종료하지 마십시오. 대신 반복이 자연스럽게 완료되도록 하거나 플래그를 사용하여 필요한 것을 찾았을 때를 추적하십시오.
498
499#### 예제 - 대화 계속하기
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#### 예제 - 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#### 예제 - 중단 사용
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 **중단 후 버퍼 동작:** `interrupt()`는 중지 신호를 보내지만 메시지 버퍼를 지우지 않습니다. 중단된 작업에서 이미 생성된 메시지 (해당 `ResultMessage` 포함, `subtype="error_during_execution"`)는 스트림에 남아 있습니다. 새 쿼리의 응답을 읽기 전에 `receive_response()`로 이들을 드레인해야 합니다. `interrupt()` 직후에 새 쿼리를 보내고 `receive_response()`를 한 번만 호출하면, 새 쿼리의 응답이 아닌 중단된 작업의 메시지를 받게 됩니다.
625</Note>
626
627#### 예제 - 고급 권한 제어
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## 타입
677
678<Note>
679 **`@dataclass` vs `TypedDict`:** 이 SDK는 두 가지 종류의 타입을 사용합니다. `@dataclass`로 장식된 클래스 (`ResultMessage`, `AgentDefinition`, `TextBlock`)는 런타임에 객체 인스턴스이며 속성 접근을 지원합니다: `msg.result`. `TypedDict`로 정의된 클래스 (`ThinkingConfigEnabled`, `McpStdioServerConfig`, `SyncHookJSONOutput`)는 **런타임에 일반 딕셔너리**이며 키 접근이 필요합니다: `config["budget_tokens"]`, `config.budget_tokens`가 아닙니다. `ClassName(field=value)` 호출 구문은 둘 다에서 작동하지만, dataclass만 속성이 있는 객체를 생성합니다.
680</Note>
681
682### `SdkMcpTool`
683
684`@tool` 데코레이터로 생성된 SDK MCP 도구의 정의입니다.
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| 속성 | 타입 | 설명 |
697| :------------- | :----------------------------------------- | :----------------------------------------------------------------------------------- |
698| `name` | `str` | 도구의 고유 식별자 |
699| `description` | `str` | 인간이 읽을 수 있는 설명 |
700| `input_schema` | `type[T] \| dict[str, Any]` | 입력 검증을 위한 스키마 |
701| `handler` | `Callable[[T], Awaitable[dict[str, Any]]]` | 도구 실행을 처리하는 비동기 함수 |
702| `annotations` | `ToolAnnotations \| None` | 선택적 MCP 도구 주석 (예: `readOnlyHint`, `destructiveHint`, `openWorldHint`). `mcp.types`에서 |
703
704### `Transport`
705
706사용자 정의 전송 구현을 위한 추상 기본 클래스입니다. 이를 사용하여 사용자 정의 채널 (예: 로컬 서브프로세스 대신 원격 연결)을 통해 Claude 프로세스와 통신합니다.
707
708<Warning>
709 이것은 낮은 수준의 내부 API입니다. 인터페이스는 향후 릴리스에서 변경될 수 있습니다. 사용자 정의 구현은 인터페이스 변경에 맞게 업데이트되어야 합니다.
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| 메서드 | 설명 |
739| :---------------- | :------------------------------------ |
740| `connect()` | 전송을 연결하고 통신을 준비합니다 |
741| `write(data)` | 원본 데이터 (JSON + 줄바꿈)를 전송에 씁니다 |
742| `read_messages()` | 구문 분석된 JSON 메시지를 생성하는 비동기 반복자 |
743| `close()` | 연결을 닫고 리소스를 정리합니다 |
744| `is_ready()` | 전송이 송수신할 수 있으면 `True`를 반환합니다 |
745| `end_input()` | 입력 스트림을 닫습니다 (예: 서브프로세스 전송의 stdin 닫기) |
746
747가져오기: `from claude_agent_sdk import Transport`
748
749### `ClaudeAgentOptions`
750
751Claude Code 쿼리를 위한 구성 dataclass입니다.
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| 속성 | 타입 | 기본값 | 설명 |
797| :---------------------------- | :------------------------------------------------------------------------------------- | :---------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
798| `tools` | `list[str] \| ToolsPreset \| None` | `None` | 도구 구성. Claude Code의 기본 도구를 위해 `{"type": "preset", "preset": "claude_code"}` 사용 |
799| `allowed_tools` | `list[str]` | `[]` | 프롬프트 없이 자동 승인할 도구. 이것은 Claude를 이 도구로만 제한하지 않습니다. 나열되지 않은 도구는 `permission_mode` 및 `can_use_tool`로 넘어갑니다. `disallowed_tools`를 사용하여 도구를 차단합니다. [권한](/ko/agent-sdk/permissions#allow-and-deny-rules) 참조 |
800| `system_prompt` | `str \| SystemPromptPreset \| None` | `None` | 시스템 프롬프트 구성. 사용자 정의 프롬프트의 경우 문자열을 전달하거나, Claude Code의 시스템 프롬프트를 위해 `{"type": "preset", "preset": "claude_code"}` 사용. 프리셋을 확장하려면 `"append"` 추가 |
801| `mcp_servers` | `dict[str, McpServerConfig] \| str \| Path` | `{}` | MCP 서버 구성 또는 구성 파일 경로 |
802| `permission_mode` | `PermissionMode \| None` | `None` | 도구 사용을 위한 권한 모드 |
803| `continue_conversation` | `bool` | `False` | 가장 최신 대화 계속하기 |
804| `resume` | `str \| None` | `None` | 재개할 세션 ID |
805| `max_turns` | `int \| None` | `None` | 최대 에이전트 턴 (도구 사용 왕복) |
806| `max_budget_usd` | `float \| None` | `None` | 클라이언트 측 비용 추정이 이 USD 값에 도달하면 쿼리 중지. `total_cost_usd`와 동일한 추정과 비교됨. 정확도 주의 사항은 [비용 및 사용량 추적](/ko/agent-sdk/cost-tracking) 참조 |
807| `disallowed_tools` | `list[str]` | `[]` | 항상 거부할 도구. 거부 규칙이 먼저 확인되고 `allowed_tools` 및 `permission_mode` (including `bypassPermissions`)를 재정의합니다 |
808| `enable_file_checkpointing` | `bool` | `False` | 되감기를 위한 파일 변경 추적 활성화. [파일 체크포인팅](/ko/agent-sdk/file-checkpointing) 참조 |
809| `model` | `str \| None` | `None` | 사용할 Claude 모델 |
810| `fallback_model` | `str \| None` | `None` | 기본 모델이 실패할 경우 사용할 폴백 모델 |
811| `betas` | `list[SdkBeta]` | `[]` | 활성화할 베타 기능. 사용 가능한 옵션은 [`SdkBeta`](#sdk-beta) 참조 |
812| `output_format` | `dict[str, Any] \| None` | `None` | 구조화된 응답을 위한 출력 형식 (예: `{"type": "json_schema", "schema": {...}}`). 자세한 내용은 [구조화된 출력](/ko/agent-sdk/structured-outputs) 참조 |
813| `permission_prompt_tool_name` | `str \| None` | `None` | 권한 프롬프트를 위한 MCP 도구 이름 |
814| `cwd` | `str \| Path \| None` | `None` | 현재 작업 디렉토리 |
815| `cli_path` | `str \| Path \| None` | `None` | Claude Code CLI 실행 파일의 사용자 정의 경로 |
816| `settings` | `str \| None` | `None` | 설정 파일 경로 |
817| `add_dirs` | `list[str \| Path]` | `[]` | Claude가 접근할 수 있는 추가 디렉토리 |
818| `env` | `dict[str, str]` | `{}` | 상속된 프로세스 환경 위에 병합된 환경 변수. 기본 CLI가 읽는 변수는 [환경 변수](/ko/env-vars) 참조 |
819| `extra_args` | `dict[str, str \| None]` | `{}` | CLI에 직접 전달할 추가 CLI 인수 |
820| `max_buffer_size` | `int \| None` | `None` | CLI stdout 버퍼링 시 최대 바이트 |
821| `debug_stderr` | `Any` | `sys.stderr` | *Deprecated* - 디버그 출력을 위한 파일 유사 객체. 대신 `stderr` 콜백 사용 |
822| `stderr` | `Callable[[str], None] \| None` | `None` | CLI의 stderr 출력을 위한 콜백 함수 |
823| `can_use_tool` | [`CanUseTool`](#can-use-tool) ` \| None` | `None` | 도구 권한 콜백 함수. 자세한 내용은 [권한 타입](#can-use-tool) 참조 |
824| `hooks` | `dict[HookEvent, list[HookMatcher]] \| None` | `None` | 이벤트 가로채기를 위한 hook 구성 |
825| `user` | `str \| None` | `None` | 사용자 식별자 |
826| `include_partial_messages` | `bool` | `False` | 부분 메시지 스트리밍 이벤트 포함. 활성화되면 [`StreamEvent`](#stream-event) 메시지가 생성됩니다 |
827| `fork_session` | `bool` | `False` | `resume`으로 재개할 때, 원본 세션을 계속하는 대신 새 세션 ID로 포크합니다 |
828| `agents` | `dict[str, AgentDefinition] \| None` | `None` | 프로그래밍 방식으로 정의된 서브에이전트 |
829| `plugins` | `list[SdkPluginConfig]` | `[]` | 로컬 경로에서 사용자 정의 플러그인 로드. 자세한 내용은 [플러그인](/ko/agent-sdk/plugins) 참조 |
830| `sandbox` | [`SandboxSettings`](#sandbox-settings) ` \| None` | `None` | 프로그래밍 방식으로 샌드박스 동작 구성. 자세한 내용은 [샌드박스 설정](#sandbox-settings) 참조 |
831| `setting_sources` | `list[SettingSource] \| None` | `None` (CLI 기본값: 모든 소스) | 로드할 파일 시스템 설정을 제어합니다. 사용자, 프로젝트 및 로컬 설정을 비활성화하려면 `[]`를 전달합니다. 관리형 정책 설정은 어쨌든 로드됩니다. [Claude Code 기능 사용](/ko/agent-sdk/claude-code-features#what-settingsources-does-not-control)에서 이것이 제어하지 않는 입력 및 비활성화 방법 참조 |
832| `max_thinking_tokens` | `int \| None` | `None` | *Deprecated* - 생각 블록의 최대 토큰. 대신 `thinking` 사용 |
833| `thinking` | [`ThinkingConfig`](#thinking-config) ` \| None` | `None` | 확장된 생각 동작을 제어합니다. `max_thinking_tokens`보다 우선합니다 |
834| `effort` | `Literal["low", "medium", "high", "max"] \| None` | `None` | 생각 깊이를 위한 노력 수준 |
835| `session_store` | [`SessionStore`](/ko/agent-sdk/session-storage#the-session-store-interface) ` \| None` | `None` | 세션 기록을 외부 백엔드로 미러링하여 모든 호스트가 이를 재개할 수 있도록 합니다. [외부 저장소에 세션 유지](/ko/agent-sdk/session-storage) 참조 |
836
837### `OutputFormat`
838
839구조화된 출력 검증을 위한 구성입니다. 이를 `ClaudeAgentOptions`의 `output_format` 필드에 `dict`로 전달합니다.
840
841```python theme={null}
842# output_format에 대한 예상 dict 형태
843{
844 "type": "json_schema",
845 "schema": {...}, # Your JSON Schema definition
846}
847```
848
849| 필드 | 필수 | 설명 |
850| :------- | :- | :------------------------------- |
851| `type` | 예 | 출력 검증을 위해 `"json_schema"`이어야 합니다 |
852| `schema` | 예 | 출력 검증을 위한 JSON Schema 정의 |
853
854### `SystemPromptPreset`
855
856선택적 추가 사항과 함께 Claude Code의 프리셋 시스템 프롬프트를 사용하기 위한 구성입니다.
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| 필드 | 필수 | 설명 |
867| :------------------------- | :-- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
868| `type` | 예 | 프리셋 시스템 프롬프트를 사용하려면 `"preset"`이어야 합니다 |
869| `preset` | 예 | Claude Code의 시스템 프롬프트를 사용하려면 `"claude_code"`이어야 합니다 |
870| `append` | 아니오 | 프리셋 시스템 프롬프트에 추가할 추가 지침 |
871| `exclude_dynamic_sections` | 아니오 | 작업 디렉토리, git 상태 및 메모리 경로와 같은 세션별 컨텍스트를 시스템 프롬프트에서 첫 사용자 메시지로 이동합니다. 사용자 및 머신 간 프롬프트 캐시 재사용을 개선합니다. [시스템 프롬프트 수정](/ko/agent-sdk/modifying-system-prompts#improve-prompt-caching-across-users-and-machines) 참조 |
872
873### `SettingSource`
874
875SDK가 설정을 로드하는 파일 시스템 기반 구성 소스를 제어합니다.
876
877```python theme={null}
878SettingSource = Literal["user", "project", "local"]
879```
880
881| 값 | 설명 | 위치 |
882| :---------- | :---------------------- | :---------------------------- |
883| `"user"` | 전역 사용자 설정 | `~/.claude/settings.json` |
884| `"project"` | 공유 프로젝트 설정 (버전 제어됨) | `.claude/settings.json` |
885| `"local"` | 로컬 프로젝트 설정 (gitignored) | `.claude/settings.local.json` |
886
887#### 기본 동작
888
889`setting_sources`가 생략되거나 `None`일 때, `query()`는 Claude Code CLI와 동일한 파일 시스템 설정을 로드합니다: 사용자, 프로젝트 및 로컬. 관리형 정책 설정은 모든 경우에 로드됩니다. 이 옵션과 관계없이 읽히는 입력 및 비활성화 방법은 [settingSources가 제어하지 않는 것](/ko/agent-sdk/claude-code-features#what-settingsources-does-not-control)을 참조하십시오.
890
891#### setting\_sources를 사용하는 이유
892
893**파일 시스템 설정 비활성화:**
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 Python SDK 0.1.59 이하에서는 빈 목록이 옵션을 생략하는 것과 동일하게 처리되었으므로 `setting_sources=[]`는 파일 시스템 설정을 비활성화하지 않았습니다. 빈 목록이 적용되어야 하는 경우 최신 릴리스로 업그레이드하십시오. TypeScript SDK는 영향을 받지 않습니다.
910</Note>
911
912**모든 파일 시스템 설정을 명시적으로 로드:**
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**특정 설정 소스만 로드:**
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**테스트 및 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**SDK 전용 애플리케이션:**
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**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#### 설정 우선순위
989
990여러 소스가 로드될 때, 설정은 이 우선순위로 병합됩니다 (높음에서 낮음):
991
9921. 로컬 설정 (`.claude/settings.local.json`)
9932. 프로젝트 설정 (`.claude/settings.json`)
9943. 사용자 설정 (`~/.claude/settings.json`)
995
996`agents` 및 `allowed_tools`와 같은 프로그래밍 방식의 옵션은 사용자, 프로젝트 및 로컬 파일 시스템 설정을 재정의합니다. 관리형 정책 설정은 프로그래밍 방식의 옵션보다 우선합니다.
997
998### `AgentDefinition`
999
1000프로그래밍 방식으로 정의된 서브에이전트의 구성입니다.
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| 필드 | 필수 | 설명 |
1021| :---------------- | :-- | :------------------------------------------------------------------------------------------------------ |
1022| `description` | 예 | 이 에이전트를 사용할 시기에 대한 자연어 설명 |
1023| `prompt` | 예 | 에이전트의 시스템 프롬프트 |
1024| `tools` | 아니오 | 허용된 도구 이름의 배열. 생략하면 모든 도구를 상속합니다 |
1025| `disallowedTools` | 아니오 | 에이전트의 도구 세트에서 제거할 도구 이름의 배열 |
1026| `model` | 아니오 | 이 에이전트의 모델 재정의. `"sonnet"`, `"opus"`, `"haiku"`, `"inherit"` 같은 별칭 또는 전체 모델 ID를 허용합니다. 생략하면 주 모델을 사용합니다 |
1027| `skills` | 아니오 | 이 에이전트가 사용할 수 있는 스킬 이름 목록 |
1028| `memory` | 아니오 | 이 에이전트의 메모리 소스: `"user"`, `"project"`, 또는 `"local"` |
1029| `mcpServers` | 아니오 | 이 에이전트가 사용할 수 있는 MCP 서버. 각 항목은 서버 이름 또는 인라인 `{name: config}` dict입니다 |
1030| `initialPrompt` | 아니오 | 이 에이전트가 주 스레드 에이전트로 실행될 때 첫 사용자 턴으로 자동 제출됨 |
1031| `maxTurns` | 아니오 | 에이전트가 중지되기 전의 최대 에이전트 턴 수 |
1032| `background` | 아니오 | 호출될 때 이 에이전트를 비차단 백그라운드 작업으로 실행합니다 |
1033| `effort` | 아니오 | 이 에이전트의 추론 노력 수준. 명명된 수준 또는 정수를 허용합니다 |
1034| `permissionMode` | 아니오 | 이 에이전트 내의 도구 실행을 위한 권한 모드. [`PermissionMode`](#permission-mode) 참조 |
1035
1036<Note>
1037 `AgentDefinition` 필드 이름은 `disallowedTools`, `permissionMode`, `maxTurns`와 같은 camelCase를 사용합니다. 이 이름은 TypeScript SDK와 공유되는 와이어 형식에 직접 매핑됩니다. 이는 `disallowed_tools` 및 `permission_mode`와 같은 동등한 최상위 필드에 Python snake\_case를 사용하는 `ClaudeAgentOptions`와 다릅니다. `AgentDefinition`은 dataclass이므로, snake\_case 키워드를 전달하면 구성 시 `TypeError`를 발생시킵니다.
1038</Note>
1039
1040### `PermissionMode`
1041
1042도구 실행을 제어하기 위한 권한 모드입니다.
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
1056도구 권한 콜백 함수의 타입 별칭입니다.
1057
1058```python theme={null}
1059CanUseTool = Callable[
1060 [str, dict[str, Any], ToolPermissionContext], Awaitable[PermissionResult]
1061]
1062```
1063
1064콜백은 다음을 수신합니다:
1065
1066* `tool_name`: 호출되는 도구의 이름
1067* `input_data`: 도구의 입력 매개변수
1068* `context`: 추가 정보가 있는 `ToolPermissionContext`
1069
1070`PermissionResult` (`PermissionResultAllow` 또는 `PermissionResultDeny`)를 반환합니다.
1071
1072### `ToolPermissionContext`
1073
1074도구 권한 콜백에 전달되는 컨텍스트 정보입니다.
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| 필드 | 타입 | 설명 |
1084| :------------ | :----------------------- | :------------------ |
1085| `signal` | `Any \| None` | 향후 중단 신호 지원을 위해 예약됨 |
1086| `suggestions` | `list[PermissionUpdate]` | CLI의 권한 업데이트 제안 |
1087
1088### `PermissionResult`
1089
1090권한 콜백 결과의 합집합 타입입니다.
1091
1092```python theme={null}
1093PermissionResult = PermissionResultAllow | PermissionResultDeny
1094```
1095
1096### `PermissionResultAllow`
1097
1098도구 호출이 허용되어야 함을 나타내는 결과입니다.
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| 필드 | 타입 | 기본값 | 설명 |
1109| :-------------------- | :------------------------------- | :-------- | :--------------- |
1110| `behavior` | `Literal["allow"]` | `"allow"` | "allow"이어야 합니다 |
1111| `updated_input` | `dict[str, Any] \| None` | `None` | 원본 대신 사용할 수정된 입력 |
1112| `updated_permissions` | `list[PermissionUpdate] \| None` | `None` | 적용할 권한 업데이트 |
1113
1114### `PermissionResultDeny`
1115
1116도구 호출이 거부되어야 함을 나타내는 결과입니다.
1117
1118```python theme={null}
1119@dataclass
1120class PermissionResultDeny:
1121 behavior: Literal["deny"] = "deny"
1122 message: str = ""
1123 interrupt: bool = False
1124```
1125
1126| 필드 | 타입 | 기본값 | 설명 |
1127| :---------- | :---------------- | :------- | :------------------- |
1128| `behavior` | `Literal["deny"]` | `"deny"` | "deny"이어야 합니다 |
1129| `message` | `str` | `""` | 도구가 거부된 이유를 설명하는 메시지 |
1130| `interrupt` | `bool` | `False` | 현재 실행을 중단할지 여부 |
1131
1132### `PermissionUpdate`
1133
1134프로그래밍 방식으로 권한을 업데이트하기 위한 구성입니다.
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| 필드 | 타입 | 설명 |
1157| :------------ | :---------------------------------------- | :--------------------- |
1158| `type` | `Literal[...]` | 권한 업데이트 작업의 타입 |
1159| `rules` | `list[PermissionRuleValue] \| None` | 추가/교체/제거 작업을 위한 규칙 |
1160| `behavior` | `Literal["allow", "deny", "ask"] \| None` | 규칙 기반 작업을 위한 동작 |
1161| `mode` | `PermissionMode \| None` | setMode 작업을 위한 모드 |
1162| `directories` | `list[str] \| None` | 디렉토리 추가/제거 작업을 위한 디렉토리 |
1163| `destination` | `Literal[...] \| None` | 권한 업데이트를 적용할 위치 |
1164
1165### `PermissionRuleValue`
1166
1167권한 업데이트에서 추가, 교체 또는 제거할 규칙입니다.
1168
1169```python theme={null}
1170@dataclass
1171class PermissionRuleValue:
1172 tool_name: str
1173 rule_content: str | None = None
1174```
1175
1176### `ToolsPreset`
1177
1178Claude Code의 기본 도구 세트를 사용하기 위한 프리셋 도구 구성입니다.
1179
1180```python theme={null}
1181class ToolsPreset(TypedDict):
1182 type: Literal["preset"]
1183 preset: Literal["claude_code"]
1184```
1185
1186### `ThinkingConfig`
1187
1188확장된 생각 동작을 제어합니다. 세 가지 구성의 합집합입니다.
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| 변형 | 필드 | 설명 |
1208| :--------- | :---------------------- | :-------------------------- |
1209| `adaptive` | `type` | Claude가 생각할 시기를 적응적으로 결정합니다 |
1210| `enabled` | `type`, `budget_tokens` | 특정 토큰 예산으로 생각 활성화 |
1211| `disabled` | `type` | 생각 비활성화 |
1212
1213이들은 `TypedDict` 클래스이므로 런타임에 일반 dict입니다. dict 리터럴로 구성하거나 클래스를 생성자처럼 호출합니다. 둘 다 `dict`를 생성합니다. `config.budget_tokens`가 아닌 `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
1229SDK 베타 기능의 리터럴 타입입니다.
1230
1231```python theme={null}
1232SdkBeta = Literal["context-1m-2025-08-07"]
1233```
1234
1235`ClaudeAgentOptions`의 `betas` 필드와 함께 사용하여 베타 기능을 활성화합니다.
1236
1237<Warning>
1238 `context-1m-2025-08-07` 베타는 2026년 4월 30일부터 폐기되었습니다. Claude Sonnet 4.5 또는 Sonnet 4와 함께 이 헤더를 전달하면 효과가 없으며, 표준 200k 토큰 컨텍스트 윈도우를 초과하는 요청은 오류를 반환합니다. 1M 토큰 컨텍스트 윈도우를 사용하려면 [Claude Sonnet 4.6, Claude Opus 4.6 또는 Claude Opus 4.7](https://platform.claude.com/docs/en/about-claude/models/overview)로 마이그레이션하십시오. 이들은 베타 헤더 없이 표준 가격으로 1M 컨텍스트를 포함합니다.
1239</Warning>
1240
1241### `McpSdkServerConfig`
1242
1243`create_sdk_mcp_server()`로 생성된 SDK MCP 서버의 구성입니다.
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
1254MCP 서버 구성의 합집합 타입입니다.
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
1292[`get_mcp_status()`](#methods)에서 보고한 MCP 서버의 구성입니다. 이것은 모든 [`McpServerConfig`](#mcp-server-config) 전송 변형의 합집합에 claude.ai를 통해 프록시된 서버를 위한 출력 전용 `claudeai-proxy` 변형을 더한 것입니다.
1293
1294```python theme={null}
1295McpServerStatusConfig = (
1296 McpStdioServerConfig
1297 | McpSSEServerConfig
1298 | McpHttpServerConfig
1299 | McpSdkServerConfigStatus
1300 | McpClaudeAIProxyServerConfig
1301)
1302```
1303
1304`McpSdkServerConfigStatus`는 [`McpSdkServerConfig`](#mcp-sdk-server-config)의 직렬화 가능한 형식이며 `type` (`"sdk"`) 및 `name` (`str`) 필드만 있습니다. 인프로세스 `instance`는 생략됩니다. `McpClaudeAIProxyServerConfig`는 `type` (`"claudeai-proxy"`), `url` (`str`) 및 `id` (`str`) 필드를 가집니다.
1305
1306### `McpStatusResponse`
1307
1308[`ClaudeSDKClient.get_mcp_status()`](#methods)의 응답입니다. 서버 상태 목록을 `mcpServers` 키 아래에 래핑합니다.
1309
1310```python theme={null}
1311class McpStatusResponse(TypedDict):
1312 mcpServers: list[McpServerStatus]
1313```
1314
1315### `McpServerStatus`
1316
1317[`McpStatusResponse`](#mcp-status-response)에 포함된 연결된 MCP 서버의 상태입니다.
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| 필드 | 타입 | 설명 |
1331| :----------- | :---------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------- |
1332| `name` | `str` | 서버 이름 |
1333| `status` | `str` | `"connected"`, `"failed"`, `"needs-auth"`, `"pending"` 또는 `"disabled"` 중 하나 |
1334| `serverInfo` | `dict` (선택사항) | 서버 이름 및 버전 (`{"name": str, "version": str}`) |
1335| `error` | `str` (선택사항) | 서버가 연결에 실패한 경우 오류 메시지 |
1336| `config` | [`McpServerStatusConfig`](#mcp-server-status-config) (선택사항) | 서버 구성. [`McpServerConfig`](#mcp-server-config)와 동일한 형태 (stdio, SSE, HTTP 또는 SDK), 더하기 claude.ai를 통해 연결된 서버를 위한 `claudeai-proxy` 변형 |
1337| `scope` | `str` (선택사항) | 구성 범위 |
1338| `tools` | `list` (선택사항) | 이 서버가 제공하는 도구, 각각 `name`, `description` 및 `annotations` 필드 포함 |
1339
1340### `SdkPluginConfig`
1341
1342SDK에서 플러그인을 로드하기 위한 구성입니다.
1343
1344```python theme={null}
1345class SdkPluginConfig(TypedDict):
1346 type: Literal["local"]
1347 path: str
1348```
1349
1350| 필드 | 타입 | 설명 |
1351| :----- | :----------------- | :--------------------------------- |
1352| `type` | `Literal["local"]` | `"local"`이어야 합니다 (현재 로컬 플러그인만 지원됨) |
1353| `path` | `str` | 플러그인 디렉토리의 절대 또는 상대 경로 |
1354
1355**예제:**
1356
1357```python theme={null}
1358plugins = [
1359 {"type": "local", "path": "./my-plugin"},
1360 {"type": "local", "path": "/absolute/path/to/plugin"},
1361]
1362```
1363
1364플러그인 생성 및 사용에 대한 완전한 정보는 [플러그인](/ko/agent-sdk/plugins)을 참조하십시오.
1365
1366## 메시지 타입
1367
1368### `Message`
1369
1370모든 가능한 메시지의 합집합 타입입니다.
1371
1372```python theme={null}
1373Message = (
1374 UserMessage
1375 | AssistantMessage
1376 | SystemMessage
1377 | ResultMessage
1378 | StreamEvent
1379 | RateLimitEvent
1380)
1381```
1382
1383### `UserMessage`
1384
1385사용자 입력 메시지입니다.
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| 필드 | 타입 | 설명 |
1397| :------------------- | :-------------------------- | :--------------------------- |
1398| `content` | `str \| list[ContentBlock]` | 텍스트 또는 콘텐츠 블록으로서의 메시지 콘텐츠 |
1399| `uuid` | `str \| None` | 고유 메시지 식별자 |
1400| `parent_tool_use_id` | `str \| None` | 이 메시지가 도구 결과 응답인 경우 도구 사용 ID |
1401| `tool_use_result` | `dict[str, Any] \| None` | 해당하는 경우 도구 결과 데이터 |
1402
1403### `AssistantMessage`
1404
1405콘텐츠 블록이 있는 어시스턴트 응답 메시지입니다.
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| 필드 | 타입 | 설명 |
1419| :------------------- | :------------------------------------------------------------- | :------------------------------------------------------------ |
1420| `content` | `list[ContentBlock]` | 응답의 콘텐츠 블록 목록 |
1421| `model` | `str` | 응답을 생성한 모델 |
1422| `parent_tool_use_id` | `str \| None` | 이것이 중첩된 응답인 경우 도구 사용 ID |
1423| `error` | [`AssistantMessageError`](#assistant-message-error) ` \| None` | 응답이 오류를 만난 경우 오류 타입 |
1424| `usage` | `dict[str, Any] \| None` | 메시지별 토큰 사용량 ([`ResultMessage.usage`](#result-message)와 동일한 키) |
1425| `message_id` | `str \| None` | API 메시지 ID. 한 턴의 여러 메시지는 동일한 ID를 공유합니다 |
1426
1427### `AssistantMessageError`
1428
1429어시스턴트 메시지의 가능한 오류 타입입니다.
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
1445메타데이터가 있는 시스템 메시지입니다.
1446
1447```python theme={null}
1448@dataclass
1449class SystemMessage:
1450 subtype: str
1451 data: dict[str, Any]
1452```
1453
1454### `ResultMessage`
1455
1456비용 및 사용량 정보가 있는 최종 결과 메시지입니다.
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
1475`usage` dict는 존재할 때 다음 키를 포함합니다.
1476
1477| 키 | 타입 | 설명 |
1478| ----------------------------- | ----- | ----------------------- |
1479| `input_tokens` | `int` | 소비된 총 입력 토큰. |
1480| `output_tokens` | `int` | 생성된 총 출력 토큰. |
1481| `cache_creation_input_tokens` | `int` | 새 캐시 항목을 생성하는 데 사용된 토큰. |
1482| `cache_read_input_tokens` | `int` | 기존 캐시 항목에서 읽은 토큰. |
1483
1484`model_usage` dict는 모델 이름을 모델별 사용량에 매핑합니다. 내부 dict 키는 camelCase를 사용합니다. 기본 CLI 프로세스에서 수정되지 않은 상태로 전달되므로 TypeScript [`ModelUsage`](/ko/agent-sdk/typescript#model-usage) 타입과 일치합니다.
1485
1486| 키 | 타입 | 설명 |
1487| -------------------------- | ------- | --------------------------------------------------------------------------------------- |
1488| `inputTokens` | `int` | 이 모델의 입력 토큰. |
1489| `outputTokens` | `int` | 이 모델의 출력 토큰. |
1490| `cacheReadInputTokens` | `int` | 이 모델의 캐시 읽기 토큰. |
1491| `cacheCreationInputTokens` | `int` | 이 모델의 캐시 생성 토큰. |
1492| `webSearchRequests` | `int` | 이 모델이 수행한 웹 검색 요청. |
1493| `costUSD` | `float` | 이 모델의 추정 비용 (USD), 클라이언트 측 계산. 청구 주의 사항은 [비용 및 사용량 추적](/ko/agent-sdk/cost-tracking) 참조. |
1494| `contextWindow` | `int` | 이 모델의 컨텍스트 윈도우 크기. |
1495| `maxOutputTokens` | `int` | 이 모델의 최대 출력 토큰 제한. |
1496
1497### `StreamEvent`
1498
1499스트리밍 중 부분 메시지 업데이트를 위한 스트림 이벤트입니다. `ClaudeAgentOptions`에서 `include_partial_messages=True`일 때만 수신됩니다. `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| 필드 | 타입 | 설명 |
1511| :------------------- | :--------------- | :------------------------------- |
1512| `uuid` | `str` | 이 이벤트의 고유 식별자 |
1513| `session_id` | `str` | 세션 식별자 |
1514| `event` | `dict[str, Any]` | 원본 Claude API 스트림 이벤트 데이터 |
1515| `parent_tool_use_id` | `str \| None` | 이 이벤트가 서브에이전트에서 온 경우 부모 도구 사용 ID |
1516
1517### `RateLimitEvent`
1518
1519속도 제한 상태가 변경될 때 발생합니다 (예: `"allowed"`에서 `"allowed_warning"`으로). 이를 사용하여 사용자에게 하드 제한에 도달하기 전에 경고하거나, 상태가 `"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| 필드 | 타입 | 설명 |
1530| :---------------- | :---------------------------------- | :---------- |
1531| `rate_limit_info` | [`RateLimitInfo`](#rate-limit-info) | 현재 속도 제한 상태 |
1532| `uuid` | `str` | 고유 이벤트 식별자 |
1533| `session_id` | `str` | 세션 식별자 |
1534
1535### `RateLimitInfo`
1536
1537[`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| 필드 | 타입 | 설명 |
1559| :------------------------ | :------------------------ | :------------------------------------------------------------------------- |
1560| `status` | `RateLimitStatus` | 현재 상태. `"allowed_warning"`은 제한에 접근 중을 의미합니다. `"rejected"`는 제한에 도달했음을 의미합니다 |
1561| `resets_at` | `int \| None` | 속도 제한 윈도우가 재설정되는 Unix 타임스탬프 |
1562| `rate_limit_type` | `RateLimitType \| None` | 어느 속도 제한 윈도우가 적용되는지 |
1563| `utilization` | `float \| None` | 소비된 속도 제한의 분수 (0.0 \~ 1.0) |
1564| `overage_status` | `RateLimitStatus \| None` | 해당하는 경우 종량제 초과 사용 상태 |
1565| `overage_resets_at` | `int \| None` | 초과 사용 윈도우가 재설정되는 Unix 타임스탬프 |
1566| `overage_disabled_reason` | `str \| None` | 상태가 `"rejected"`인 경우 초과 사용을 사용할 수 없는 이유 |
1567| `raw` | `dict[str, Any]` | 위에서 모델링되지 않은 필드를 포함한 CLI의 전체 원본 dict |
1568
1569### `TaskStartedMessage`
1570
1571백그라운드 작업이 시작될 때 발생합니다. 백그라운드 작업은 주 턴 외부에서 추적되는 모든 것입니다: 백그라운드 Bash 명령, [Monitor](#monitor) 감시, Agent 도구를 통해 생성된 서브에이전트 또는 원격 에이전트. `task_type` 필드가 어느 것인지 알려줍니다. 이 명명은 `Task`-to-`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| 필드 | 타입 | 설명 |
1585| :------------ | :------------ | :-------------------------------------------------------------------------------------------- |
1586| `task_id` | `str` | 작업의 고유 식별자 |
1587| `description` | `str` | 작업의 설명 |
1588| `uuid` | `str` | 고유 메시지 식별자 |
1589| `session_id` | `str` | 세션 식별자 |
1590| `tool_use_id` | `str \| None` | 관련 도구 사용 ID |
1591| `task_type` | `str \| None` | 백그라운드 작업의 종류: 백그라운드 Bash 및 Monitor 감시의 경우 `"local_bash"`, `"local_agent"` 또는 `"remote_agent"` |
1592
1593### `TaskUsage`
1594
1595백그라운드 작업의 토큰 및 타이밍 데이터입니다.
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
1606실행 중인 백그라운드 작업에 대한 진행 상황 업데이트로 주기적으로 발생합니다.
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| 필드 | 타입 | 설명 |
1621| :--------------- | :------------ | :------------------- |
1622| `task_id` | `str` | 작업의 고유 식별자 |
1623| `description` | `str` | 현재 상태 설명 |
1624| `usage` | `TaskUsage` | 지금까지 이 작업의 토큰 사용량 |
1625| `uuid` | `str` | 고유 메시지 식별자 |
1626| `session_id` | `str` | 세션 식별자 |
1627| `tool_use_id` | `str \| None` | 관련 도구 사용 ID |
1628| `last_tool_name` | `str \| None` | 작업이 마지막으로 사용한 도구의 이름 |
1629
1630### `TaskNotificationMessage`
1631
1632백그라운드 작업이 완료, 실패 또는 중지될 때 발생합니다. 백그라운드 작업에는 `run_in_background` Bash 명령, Monitor 감시 및 백그라운드 서브에이전트가 포함됩니다.
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| 필드 | 타입 | 설명 |
1648| :------------ | :----------------------- | :-------------------------------------------- |
1649| `task_id` | `str` | 작업의 고유 식별자 |
1650| `status` | `TaskNotificationStatus` | `"completed"`, `"failed"` 또는 `"stopped"` 중 하나 |
1651| `output_file` | `str` | 작업 출력 파일의 경로 |
1652| `summary` | `str` | 작업 결과의 요약 |
1653| `uuid` | `str` | 고유 메시지 식별자 |
1654| `session_id` | `str` | 세션 식별자 |
1655| `tool_use_id` | `str \| None` | 관련 도구 사용 ID |
1656| `usage` | `TaskUsage \| None` | 작업의 최종 토큰 사용량 |
1657
1658## 콘텐츠 블록 타입
1659
1660### `ContentBlock`
1661
1662모든 콘텐츠 블록의 합집합 타입입니다.
1663
1664```python theme={null}
1665ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock
1666```
1667
1668### `TextBlock`
1669
1670텍스트 콘텐츠 블록입니다.
1671
1672```python theme={null}
1673@dataclass
1674class TextBlock:
1675 text: str
1676```
1677
1678### `ThinkingBlock`
1679
1680생각 콘텐츠 블록입니다 (생각 기능이 있는 모델용).
1681
1682```python theme={null}
1683@dataclass
1684class ThinkingBlock:
1685 thinking: str
1686 signature: str
1687```
1688
1689### `ToolUseBlock`
1690
1691도구 사용 요청 블록입니다.
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
1703도구 실행 결과 블록입니다.
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## 오류 타입
1714
1715### `ClaudeSDKError`
1716
1717모든 SDK 오류의 기본 예외 클래스입니다.
1718
1719```python theme={null}
1720class ClaudeSDKError(Exception):
1721 """Base error for Claude SDK."""
1722```
1723
1724### `CLINotFoundError`
1725
1726Claude Code CLI가 설치되지 않았거나 찾을 수 없을 때 발생합니다.
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
1742Claude Code 연결이 실패할 때 발생합니다.
1743
1744```python theme={null}
1745class CLIConnectionError(ClaudeSDKError):
1746 """Failed to connect to Claude Code."""
1747```
1748
1749### `ProcessError`
1750
1751Claude Code 프로세스가 실패할 때 발생합니다.
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
1764JSON 구문 분석이 실패할 때 발생합니다.
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## Hook 타입
1779
1780hooks 사용에 대한 포괄적인 가이드, 예제 및 일반적인 패턴은 [Hooks 가이드](/ko/agent-sdk/hooks)를 참조하십시오.
1781
1782### `HookEvent`
1783
1784지원되는 hook 이벤트 타입입니다.
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 TypeScript SDK는 Python에서 아직 사용할 수 없는 추가 hook 이벤트를 지원합니다: `SessionStart`, `SessionEnd`, `Setup`, `TeammateIdle`, `TaskCompleted`, `ConfigChange`, `WorktreeCreate`, `WorktreeRemove` 및 `PostToolBatch`.
1803</Note>
1804
1805### `HookCallback`
1806
1807hook 콜백 함수의 타입 정의입니다.
1808
1809```python theme={null}
1810HookCallback = Callable[[HookInput, str | None, HookContext], Awaitable[HookJSONOutput]]
1811```
1812
1813매개변수:
1814
1815* `input`: `hook_event_name`을 기반으로 한 판별된 합집합이 있는 강타입 hook 입력 ([`HookInput`](#hook-input) 참조)
1816* `tool_use_id`: 선택적 도구 사용 식별자 (도구 관련 hooks의 경우)
1817* `context`: 추가 정보가 있는 hook 컨텍스트
1818
1819다음을 포함할 수 있는 [`HookJSONOutput`](#hook-json-output)을 반환합니다.
1820
1821* `decision`: 작업을 차단하려면 `"block"`
1822* `systemMessage`: 기록에 추가할 시스템 메시지
1823* `hookSpecificOutput`: hook 특정 출력 데이터
1824
1825### `HookContext`
1826
1827hook 콜백에 전달되는 컨텍스트 정보입니다.
1828
1829```python theme={null}
1830class HookContext(TypedDict):
1831 signal: Any | None # Future: abort signal support
1832```
1833
1834### `HookMatcher`
1835
1836특정 이벤트 또는 도구에 hooks를 일치시키기 위한 구성입니다.
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
1854모든 hook 입력 타입의 합집합 타입입니다. 실제 타입은 `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
1873모든 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| 필드 | 타입 | 설명 |
1884| :---------------- | :----------- | :----------- |
1885| `session_id` | `str` | 현재 세션 식별자 |
1886| `transcript_path` | `str` | 세션 기록 파일의 경로 |
1887| `cwd` | `str` | 현재 작업 디렉토리 |
1888| `permission_mode` | `str` (선택사항) | 현재 권한 모드 |
1889
1890### `PreToolUseHookInput`
1891
1892`PreToolUse` hook 이벤트의 입력 데이터입니다.
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| 필드 | 타입 | 설명 |
1905| :---------------- | :---------------------- | :------------------------------------ |
1906| `hook_event_name` | `Literal["PreToolUse"]` | 항상 "PreToolUse" |
1907| `tool_name` | `str` | 실행될 도구의 이름 |
1908| `tool_input` | `dict[str, Any]` | 도구의 입력 매개변수 |
1909| `tool_use_id` | `str` | 이 도구 사용의 고유 식별자 |
1910| `agent_id` | `str` (선택사항) | 서브에이전트 식별자, hook이 서브에이전트 내에서 발생할 때 존재 |
1911| `agent_type` | `str` (선택사항) | 서브에이전트 타입, hook이 서브에이전트 내에서 발생할 때 존재 |
1912
1913### `PostToolUseHookInput`
1914
1915`PostToolUse` hook 이벤트의 입력 데이터입니다.
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| 필드 | 타입 | 설명 |
1929| :---------------- | :----------------------- | :------------------------------------ |
1930| `hook_event_name` | `Literal["PostToolUse"]` | 항상 "PostToolUse" |
1931| `tool_name` | `str` | 실행된 도구의 이름 |
1932| `tool_input` | `dict[str, Any]` | 사용된 입력 매개변수 |
1933| `tool_response` | `Any` | 도구 실행의 응답 |
1934| `tool_use_id` | `str` | 이 도구 사용의 고유 식별자 |
1935| `agent_id` | `str` (선택사항) | 서브에이전트 식별자, hook이 서브에이전트 내에서 발생할 때 존재 |
1936| `agent_type` | `str` (선택사항) | 서브에이전트 타입, hook이 서브에이전트 내에서 발생할 때 존재 |
1937
1938### `PostToolUseFailureHookInput`
1939
1940`PostToolUseFailure` hook 이벤트의 입력 데이터입니다. 도구 실행이 실패할 때 호출됩니다.
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| 필드 | 타입 | 설명 |
1955| :---------------- | :------------------------------ | :------------------------------------ |
1956| `hook_event_name` | `Literal["PostToolUseFailure"]` | 항상 "PostToolUseFailure" |
1957| `tool_name` | `str` | 실패한 도구의 이름 |
1958| `tool_input` | `dict[str, Any]` | 사용된 입력 매개변수 |
1959| `tool_use_id` | `str` | 이 도구 사용의 고유 식별자 |
1960| `error` | `str` | 실패한 실행의 오류 메시지 |
1961| `is_interrupt` | `bool` (선택사항) | 실패가 중단으로 인한 것인지 여부 |
1962| `agent_id` | `str` (선택사항) | 서브에이전트 식별자, hook이 서브에이전트 내에서 발생할 때 존재 |
1963| `agent_type` | `str` (선택사항) | 서브에이전트 타입, hook이 서브에이전트 내에서 발생할 때 존재 |
1964
1965### `UserPromptSubmitHookInput`
1966
1967`UserPromptSubmit` hook 이벤트의 입력 데이터입니다.
1968
1969```python theme={null}
1970class UserPromptSubmitHookInput(BaseHookInput):
1971 hook_event_name: Literal["UserPromptSubmit"]
1972 prompt: str
1973```
1974
1975| 필드 | 타입 | 설명 |
1976| :---------------- | :---------------------------- | :-------------------- |
1977| `hook_event_name` | `Literal["UserPromptSubmit"]` | 항상 "UserPromptSubmit" |
1978| `prompt` | `str` | 사용자가 제출한 프롬프트 |
1979
1980### `StopHookInput`
1981
1982`Stop` hook 이벤트의 입력 데이터입니다.
1983
1984```python theme={null}
1985class StopHookInput(BaseHookInput):
1986 hook_event_name: Literal["Stop"]
1987 stop_hook_active: bool
1988```
1989
1990| 필드 | 타입 | 설명 |
1991| :----------------- | :---------------- | :---------------------- |
1992| `hook_event_name` | `Literal["Stop"]` | 항상 "Stop" |
1993| `stop_hook_active` | `bool` | stop hook이 활성화되어 있는지 여부 |
1994
1995### `SubagentStopHookInput`
1996
1997`SubagentStop` hook 이벤트의 입력 데이터입니다.
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| 필드 | 타입 | 설명 |
2009| :---------------------- | :------------------------ | :---------------------- |
2010| `hook_event_name` | `Literal["SubagentStop"]` | 항상 "SubagentStop" |
2011| `stop_hook_active` | `bool` | stop hook이 활성화되어 있는지 여부 |
2012| `agent_id` | `str` | 서브에이전트의 고유 식별자 |
2013| `agent_transcript_path` | `str` | 서브에이전트의 기록 파일 경로 |
2014| `agent_type` | `str` | 서브에이전트의 타입 |
2015
2016### `PreCompactHookInput`
2017
2018`PreCompact` hook 이벤트의 입력 데이터입니다.
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| 필드 | 타입 | 설명 |
2028| :-------------------- | :-------------------------- | :--------------- |
2029| `hook_event_name` | `Literal["PreCompact"]` | 항상 "PreCompact" |
2030| `trigger` | `Literal["manual", "auto"]` | 압축을 트리거한 것 |
2031| `custom_instructions` | `str \| None` | 압축을 위한 사용자 정의 지침 |
2032
2033### `NotificationHookInput`
2034
2035`Notification` hook 이벤트의 입력 데이터입니다.
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| 필드 | 타입 | 설명 |
2046| :------------------ | :------------------------ | :---------------- |
2047| `hook_event_name` | `Literal["Notification"]` | 항상 "Notification" |
2048| `message` | `str` | 알림 메시지 콘텐츠 |
2049| `title` | `str` (선택사항) | 알림 제목 |
2050| `notification_type` | `str` | 알림의 타입 |
2051
2052### `SubagentStartHookInput`
2053
2054`SubagentStart` hook 이벤트의 입력 데이터입니다.
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| 필드 | 타입 | 설명 |
2064| :---------------- | :------------------------- | :----------------- |
2065| `hook_event_name` | `Literal["SubagentStart"]` | 항상 "SubagentStart" |
2066| `agent_id` | `str` | 서브에이전트의 고유 식별자 |
2067| `agent_type` | `str` | 서브에이전트의 타입 |
2068
2069### `PermissionRequestHookInput`
2070
2071`PermissionRequest` hook 이벤트의 입력 데이터입니다. hooks가 프로그래밍 방식으로 권한 결정을 처리할 수 있습니다.
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| 필드 | 타입 | 설명 |
2082| :----------------------- | :----------------------------- | :--------------------- |
2083| `hook_event_name` | `Literal["PermissionRequest"]` | 항상 "PermissionRequest" |
2084| `tool_name` | `str` | 권한을 요청하는 도구의 이름 |
2085| `tool_input` | `dict[str, Any]` | 도구의 입력 매개변수 |
2086| `permission_suggestions` | `list[Any]` (선택사항) | CLI의 제안된 권한 업데이트 |
2087
2088### `HookJSONOutput`
2089
2090hook 콜백 반환 값의 합집합 타입입니다.
2091
2092```python theme={null}
2093HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutput
2094```
2095
2096#### `SyncHookJSONOutput`
2097
2098제어 및 결정 필드가 있는 동기식 hook 출력입니다.
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 Python 코드에서 `continue_` (언더스코어 포함)를 사용합니다. CLI로 전송할 때 자동으로 `continue`로 변환됩니다.
2118</Note>
2119
2120#### `HookSpecificOutput`
2121
2122hook 이벤트 이름과 이벤트 특정 필드를 포함하는 `TypedDict`입니다. 형태는 `hookEventName` 값에 따라 달라집니다. hook 이벤트별 사용 가능한 필드에 대한 전체 세부 정보는 [hooks로 실행 제어](/ko/agent-sdk/hooks#outputs)를 참조하십시오.
2123
2124이벤트 특정 출력 타입의 판별된 합집합입니다. `hookEventName` 필드가 어느 필드가 유효한지 결정합니다.
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
2179hook 실행을 연기하는 비동기 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 Python 코드에서 `async_` (언더스코어 포함)를 사용합니다. CLI로 전송할 때 자동으로 `async`로 변환됩니다.
2189</Note>
2190
2191### Hook 사용 예제
2192
2193이 예제는 두 개의 hooks를 등록합니다: `rm -rf /`와 같은 위험한 bash 명령을 차단하는 하나, 감사를 위해 모든 도구 사용을 기록하는 다른 하나. 보안 hook은 `matcher`를 통해 Bash 명령에서만 실행되고, 로깅 hook은 모든 도구에서 실행됩니다.
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## 도구 입력/출력 타입
2244
2245모든 기본 Claude Code 도구의 입력/출력 스키마 문서입니다. Python SDK는 이들을 타입으로 내보내지 않지만, 메시지의 도구 입력 및 출력 구조를 나타냅니다.
2246
2247### Agent
2248
2249**도구 이름:** `Agent` (이전 `Task`, 여전히 별칭으로 허용됨)
2250
2251**입력:**
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**출력:**
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**도구 이름:** `AskUserQuestion`
2275
2276실행 중에 사용자에게 명확히 하는 질문을 합니다. 사용 세부 정보는 [승인 및 사용자 입력 처리](/ko/agent-sdk/user-input#handle-clarifying-questions)를 참조하십시오.
2277
2278**입력:**
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**출력:**
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**도구 이름:** `Bash`
2319
2320**입력:**
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**출력:**
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**도구 이름:** `Monitor`
2345
2346백그라운드 스크립트를 실행하고 각 stdout 줄을 Claude에 이벤트로 전달하여 폴링 없이 반응할 수 있도록 합니다. Monitor는 Bash와 동일한 권한 규칙을 따릅니다. 동작 및 제공자 가용성은 [Monitor 도구 참조](/ko/tools-reference#monitor-tool)를 참조하십시오.
2347
2348**입력:**
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**출력:**
2360
2361```python theme={null}
2362{
2363 "taskId": str, # ID of the background monitor task
2364 "timeoutMs": int, # Timeout deadline in milliseconds (0 when persistent)
2365 "persistent": bool | None, # True when running until TaskStop or session end
2366}
2367```
2368
2369### Edit
2370
2371**도구 이름:** `Edit`
2372
2373**입력:**
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**출력:**
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**도구 이름:** `Read`
2397
2398**입력:**
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**출력 (텍스트 파일):**
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**출력 (이미지):**
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**도구 이름:** `Write`
2431
2432**입력:**
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**출력:**
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**도구 이름:** `Glob`
2454
2455**입력:**
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**출력:**
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**도구 이름:** `Grep`
2477
2478**입력:**
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**출력 (content 모드):**
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**출력 (files\_with\_matches 모드):**
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**도구 이름:** `NotebookEdit`
2526
2527**입력:**
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**출력:**
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**도구 이름:** `WebFetch`
2553
2554**입력:**
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**출력:**
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**도구 이름:** `WebSearch`
2577
2578**입력:**
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**출력:**
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**도구 이름:** `TodoWrite`
2601
2602**입력:**
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**출력:**
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**도구 이름:** `BashOutput`
2628
2629**입력:**
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**출력:**
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**도구 이름:** `KillBash`
2651
2652**입력:**
2653
2654```python theme={null}
2655{
2656 "shell_id": str # The ID of the background shell to kill
2657}
2658```
2659
2660**출력:**
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**도구 이름:** `ExitPlanMode`
2672
2673**입력:**
2674
2675```python theme={null}
2676{
2677 "plan": str # The plan to run by the user for approval
2678}
2679```
2680
2681**출력:**
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**도구 이름:** `ListMcpResources`
2693
2694**입력:**
2695
2696```python theme={null}
2697{
2698 "server": str | None # Optional server name to filter resources by
2699}
2700```
2701
2702**출력:**
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**도구 이름:** `ReadMcpResource`
2722
2723**입력:**
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**출력:**
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## ClaudeSDKClient를 사용한 고급 기능
2744
2745### 지속적인 대화 인터페이스 구축
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### 동작 수정을 위해 Hooks 사용
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### 실시간 진행 상황 모니터링
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## 예제 사용
2950
2951### 기본 파일 작업 (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### 오류 처리
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### 클라이언트를 사용한 스트리밍 모드
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### 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## 샌드박스 구성
3095
3096### `SandboxSettings`
3097
3098샌드박스 동작을 위한 구성입니다. 이를 사용하여 명령 샌드박싱을 활성화하고 프로그래밍 방식으로 네트워크 제한을 구성합니다.
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| 속성 | 타입 | 기본값 | 설명 |
3112| :-------------------------- | :------------------------------------------------------ | :------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
3113| `enabled` | `bool` | `False` | 명령 실행을 위한 샌드박스 모드 활성화 |
3114| `autoAllowBashIfSandboxed` | `bool` | `True` | 샌드박스가 활성화되면 bash 명령 자동 승인 |
3115| `excludedCommands` | `list[str]` | `[]` | 항상 샌드박스 제한을 우회하는 명령 (예: `["docker"]`). 이들은 모델 개입 없이 자동으로 샌드박스되지 않은 상태로 실행됩니다 |
3116| `allowUnsandboxedCommands` | `bool` | `True` | 모델이 샌드박스 외부에서 명령 실행을 요청하도록 허용합니다. `True`일 때, 모델은 도구 입력에서 `dangerouslyDisableSandbox`를 설정할 수 있으며, 이는 [권한 시스템](#permissions-fallback-for-unsandboxed-commands)으로 폴백됩니다 |
3117| `network` | [`SandboxNetworkConfig`](#sandbox-network-config) | `None` | 네트워크 특정 샌드박스 구성 |
3118| `ignoreViolations` | [`SandboxIgnoreViolations`](#sandbox-ignore-violations) | `None` | 무시할 샌드박스 위반을 구성합니다 |
3119| `enableWeakerNestedSandbox` | `bool` | `False` | 호환성을 위해 더 약한 중첩 샌드박스 활성화 |
3120
3121#### 사용 예제
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 **Unix 소켓 보안**: `allowUnixSockets` 옵션은 강력한 시스템 서비스에 대한 접근을 부여할 수 있습니다. 예를 들어, `/var/run/docker.sock`을 허용하면 Docker API를 통해 샌드박스 격리를 우회하여 전체 호스트 시스템 접근을 효과적으로 부여합니다. 엄격히 필요한 Unix 소켓만 허용하고 각각의 보안 영향을 이해하십시오.
3141</Warning>
3142
3143### `SandboxNetworkConfig`
3144
3145샌드박스 모드를 위한 네트워크 특정 구성입니다.
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| 속성 | 타입 | 기본값 | 설명 |
3161| :------------------------ | :---------- | :------ | :------------------------------------------------------------------------------------------- |
3162| `allowedDomains` | `list[str]` | `[]` | 샌드박스된 프로세스가 접근할 수 있는 도메인 이름 |
3163| `deniedDomains` | `list[str]` | `[]` | 샌드박스된 프로세스가 접근할 수 없는 도메인 이름입니다. `allowedDomains`보다 우선합니다 |
3164| `allowManagedDomainsOnly` | `bool` | `False` | 관리되는 설정만: 관리되는 설정에서 설정되면, 관리되지 않는 설정 소스의 `allowedDomains`를 무시합니다. SDK 옵션을 통해 설정할 때는 효과가 없습니다 |
3165| `allowUnixSockets` | `list[str]` | `[]` | 프로세스가 접근할 수 있는 Unix 소켓 경로 (예: Docker 소켓) |
3166| `allowAllUnixSockets` | `bool` | `False` | 모든 Unix 소켓에 대한 접근 허용 |
3167| `allowLocalBinding` | `bool` | `False` | 프로세스가 로컬 포트에 바인딩하도록 허용 (예: 개발 서버용) |
3168| `allowMachLookup` | `list[str]` | `[]` | macOS만 해당: 허용할 XPC/Mach 서비스 이름입니다. 후행 와일드카드를 지원합니다 |
3169| `httpProxyPort` | `int` | `None` | 네트워크 요청을 위한 HTTP 프록시 포트 |
3170| `socksProxyPort` | `int` | `None` | 네트워크 요청을 위한 SOCKS 프록시 포트 |
3171
3172<Note>
3173 기본 제공 샌드박스 프록시는 요청된 호스트명을 기반으로 네트워크 허용 목록을 적용하며 TLS 트래픽을 종료하거나 검사하지 않으므로, [도메인 프론팅](https://en.wikipedia.org/wiki/Domain_fronting)과 같은 기술이 이를 우회할 수 있습니다. 자세한 내용은 [샌드박싱 보안 제한 사항](/ko/sandboxing#security-limitations)을 참조하고, TLS 종료 프록시 구성은 [안전한 배포](/ko/agent-sdk/secure-deployment#traffic-forwarding)를 참조하십시오.
3174</Note>
3175
3176### `SandboxIgnoreViolations`
3177
3178특정 샌드박스 위반을 무시하기 위한 구성입니다.
3179
3180```python theme={null}
3181class SandboxIgnoreViolations(TypedDict, total=False):
3182 file: list[str]
3183 network: list[str]
3184```
3185
3186| 속성 | 타입 | 기본값 | 설명 |
3187| :-------- | :---------- | :--- | :--------------- |
3188| `file` | `list[str]` | `[]` | 위반을 무시할 파일 경로 패턴 |
3189| `network` | `list[str]` | `[]` | 위반을 무시할 네트워크 패턴 |
3190
3191### 샌드박스되지 않은 명령을 위한 권한 폴백
3192
3193`allowUnsandboxedCommands`가 활성화되면, 모델은 도구 입력에서 `dangerouslyDisableSandbox: True`를 설정하여 샌드박스 외부에서 명령 실행을 요청할 수 있습니다. 이러한 요청은 기존 권한 시스템으로 폴백되므로, `can_use_tool` 핸들러가 호출되어 사용자 정의 인증 로직을 구현할 수 있습니다.
3194
3195<Note>
3196 **`excludedCommands` vs `allowUnsandboxedCommands`:**
3197
3198 * `excludedCommands`: 항상 자동으로 샌드박스를 우회하는 명령의 정적 목록 (예: `["docker"]`). 모델이 이를 제어할 수 없습니다.
3199 * `allowUnsandboxedCommands`: 모델이 도구 입력에서 `dangerouslyDisableSandbox: True`를 설정하여 런타임에 샌드박스되지 않은 실행을 요청하도록 합니다.
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
3257이 패턴을 사용하면 다음을 수행할 수 있습니다.
3258
3259* **모델 요청 감사**: 모델이 샌드박스되지 않은 실행을 요청할 때 로깅
3260* **허용 목록 구현**: 특정 명령만 샌드박스되지 않은 상태로 실행하도록 허용
3261* **승인 워크플로우 추가**: 권한 있는 작업에 대한 명시적 인증 필요
3262
3263<Warning>
3264 `dangerouslyDisableSandbox: True`로 실행되는 명령은 전체 시스템 접근 권한이 있습니다. `can_use_tool` 핸들러가 이러한 요청을 신중하게 검증하는지 확인하십시오.
3265
3266 `permission_mode`가 `bypassPermissions`로 설정되고 `allow_unsandboxed_commands`가 활성화되면, 모델은 승인 프롬프트 없이 샌드박스 외부에서 명령을 자동으로 실행할 수 있습니다. 이 조합은 모델이 샌드박스 격리를 조용히 탈출할 수 있도록 효과적으로 허용합니다.
3267</Warning>
3268
3269## 참고 항목
3270
3271* [SDK 개요](/ko/agent-sdk/overview) - 일반 SDK 개념
3272* [TypeScript SDK 참조](/ko/agent-sdk/typescript) - TypeScript SDK 문서
3273* [CLI 참조](/ko/cli-reference) - 명령줄 인터페이스
3274* [일반적인 워크플로우](/ko/common-workflows) - 단계별 가이드