Tham chiếu API đầy đủ cho Python Agent SDK, gồm mọi function, type, và class.
Cài đặt
Phần tiêu đề “Cài đặt”Cài package vào một virtual environment. Trên các bản cài Debian, Ubuntu, và Homebrew Python gần đây, chạy pip install thẳng vào system Python sẽ lỗi với error: externally-managed-environment.
python3 -m venv .venvsource .venv/bin/activatepip install claude-agent-sdkĐể biết cách dùng uv, Windows PowerShell, và thiết lập API key, xem phần Setup trong Agent SDK quickstart.
Chọn giữa query() và ClaudeSDKClient
Phần tiêu đề “Chọn giữa query() và ClaudeSDKClient”Python SDK cung cấp hai cách để tương tác với Claude Code:
So sánh nhanh
Phần tiêu đề “So sánh nhanh”| Feature | query() | ClaudeSDKClient |
|---|---|---|
| Session | Tạo session mới mặc định | Dùng lại cùng session |
| Hội thoại | Một lượt trao đổi | Nhiều lượt trao đổi trong cùng context |
| Kết nối | Quản lý tự động | Kiểm soát thủ công |
| Streaming Input | ✅ Hỗ trợ | ✅ Hỗ trợ |
| Interrupts | ❌ Không hỗ trợ | ✅ Hỗ trợ |
| Hooks | ✅ Hỗ trợ | ✅ Hỗ trợ |
| Custom Tools | ✅ Hỗ trợ | ✅ Hỗ trợ |
| Continue Chat | Thủ công qua continue_conversation hoặc resume | ✅ Tự động |
| Use Case | Tác vụ một lần | Hội thoại liên tục |
Khi nào dùng query() (tác vụ một lần)
Phần tiêu đề “Khi nào dùng query() (tác vụ một lần)”Phù hợp cho:
- Câu hỏi một lần không cần lịch sử hội thoại
- Tác vụ độc lập không cần context từ lượt trao đổi trước
- Script automation đơn giản
- Khi bạn muốn bắt đầu mới hoàn toàn mỗi lần
Khi nào dùng ClaudeSDKClient (hội thoại liên tục)
Phần tiêu đề “Khi nào dùng ClaudeSDKClient (hội thoại liên tục)”Phù hợp cho:
- Tiếp tục hội thoại - Khi bạn cần Claude nhớ context
- Câu hỏi follow-up - Xây dựng dựa trên phản hồi trước
- Ứng dụng tương tác - Giao diện chat, REPL
- Logic dựa trên phản hồi - Khi hành động tiếp theo phụ thuộc vào phản hồi của Claude
- Kiểm soát session - Quản lý vòng đời hội thoại tường minh
Functions
Phần tiêu đề “Functions”query()
Phần tiêu đề “query()”Tạo một session mới cho mỗi lần tương tác với Claude Code theo mặc định. Trả về một async iterator yield ra message khi chúng đến. Mỗi lần gọi query() bắt đầu mới hoàn toàn, không nhớ tương tác trước đó trừ khi bạn truyền continue_conversation=True hoặc resume trong ClaudeAgentOptions. Xem thêm Sessions.
async def query( *, prompt: str | AsyncIterable[dict[str, Any]], options: ClaudeAgentOptions | None = None, transport: Transport | None = None) -> AsyncIterator[Message]Parameters
Phần tiêu đề “Parameters”| Parameter | Type | Description |
|---|---|---|
prompt | str | AsyncIterable[dict] | Prompt đầu vào dưới dạng string hoặc async iterable cho streaming mode |
options | ClaudeAgentOptions | None | Đối tượng cấu hình tuỳ chọn (mặc định ClaudeAgentOptions() nếu None) |
transport | Transport | None | Transport tuỳ biến tuỳ chọn để giao tiếp với process CLI |
Returns
Phần tiêu đề “Returns”Trả về một AsyncIterator[Message] yield ra các message từ hội thoại.
Ví dụ - Với options
Phần tiêu đề “Ví dụ - Với options”import asynciofrom claude_agent_sdk import query, ClaudeAgentOptions
async def main(): options = ClaudeAgentOptions( system_prompt="You are an expert Python developer", permission_mode="acceptEdits", )
async for message in query(prompt="Create a Python web server", options=options): print(message)
asyncio.run(main())tool()
Phần tiêu đề “tool()”Decorator để định nghĩa MCP tool với type safety.
def tool( name: str, description: str, input_schema: type | dict[str, Any], annotations: ToolAnnotations | None = None) -> Callable[[Callable[[Any], Awaitable[dict[str, Any]]]], SdkMcpTool[Any]]Parameters
Phần tiêu đề “Parameters”| Parameter | Type | Description |
|---|---|---|
name | str | Định danh duy nhất cho tool |
description | str | Mô tả dễ đọc về việc tool đó làm gì |
input_schema | type | dict[str, Any] | Schema định nghĩa tham số đầu vào của tool (xem bên dưới) |
annotations | ToolAnnotations | None | Annotation MCP tool tuỳ chọn, cung cấp gợi ý hành vi cho client |
Tuỳ chọn input schema
Phần tiêu đề “Tuỳ chọn input schema”-
Ánh xạ type đơn giản (khuyến nghị):
{"text": str, "count": int, "enabled": bool} -
Định dạng JSON Schema (để validate phức tạp hơn):
{"type": "object","properties": {"text": {"type": "string"},"count": {"type": "integer", "minimum": 0},},"required": ["text"],}
Returns
Phần tiêu đề “Returns”Một hàm decorator bọc phần triển khai tool và trả về một instance SdkMcpTool.
Ví dụ
Phần tiêu đề “Ví dụ”from claude_agent_sdk import toolfrom typing import Any
@tool("greet", "Greet a user", {"name": str})async def greet(args: dict[str, Any]) -> dict[str, Any]: return {"content": [{"type": "text", "text": f"Hello, {args['name']}!"}]}ToolAnnotations
Phần tiêu đề “ToolAnnotations”Re-export từ mcp.types (cũng khả dụng qua from claude_agent_sdk import ToolAnnotations). Mọi field đều là gợi ý tuỳ chọn; client không nên dựa vào chúng cho quyết định bảo mật.
| Field | Type | Default | Description |
|---|---|---|---|
title | str | None | None | Tiêu đề dễ đọc cho tool |
readOnlyHint | bool | None | False | Nếu True, tool không thay đổi môi trường của nó |
destructiveHint | bool | None | True | Nếu True, tool có thể thực hiện thay đổi phá huỷ (chỉ có ý nghĩa khi readOnlyHint là False) |
idempotentHint | bool | None | False | Nếu True, gọi lặp lại với cùng tham số không có thêm tác dụng (chỉ có ý nghĩa khi readOnlyHint là False) |
openWorldHint | bool | None | True | Nếu True, tool tương tác với thực thể bên ngoài (ví dụ, web search). Nếu False, domain của tool khép kín (ví dụ, một memory tool) |
from claude_agent_sdk import tool, ToolAnnotationsfrom typing import Any
@tool( "search", "Search the web", {"query": str}, annotations=ToolAnnotations(readOnlyHint=True, openWorldHint=True),)async def search(args: dict[str, Any]) -> dict[str, Any]: return {"content": [{"type": "text", "text": f"Results for: {args['query']}"}]}create_sdk_mcp_server()
Phần tiêu đề “create_sdk_mcp_server()”Tạo một MCP server chạy in-process bên trong ứng dụng Python của bạn.
def create_sdk_mcp_server( name: str, version: str = "1.0.0", tools: list[SdkMcpTool[Any]] | None = None) -> McpSdkServerConfigParameters
Phần tiêu đề “Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
name | str | - | Định danh duy nhất cho server |
version | str | "1.0.0" | Chuỗi phiên bản server |
tools | list[SdkMcpTool[Any]] | None | None | Danh sách tool function tạo bằng decorator @tool |
Returns
Phần tiêu đề “Returns”Trả về một đối tượng McpSdkServerConfig có thể truyền vào ClaudeAgentOptions.mcp_servers.
Ví dụ
Phần tiêu đề “Ví dụ”from claude_agent_sdk import tool, create_sdk_mcp_server, ClaudeAgentOptions
@tool("add", "Add two numbers", {"a": float, "b": float})async def add(args): return {"content": [{"type": "text", "text": f"Sum: {args['a'] + args['b']}"}]}
@tool("multiply", "Multiply two numbers", {"a": float, "b": float})async def multiply(args): return {"content": [{"type": "text", "text": f"Product: {args['a'] * args['b']}"}]}
calculator = create_sdk_mcp_server( name="calculator", version="2.0.0", tools=[add, multiply], # Pass decorated functions)
# Use with Claudeoptions = ClaudeAgentOptions( mcp_servers={"calc": calculator}, allowed_tools=["mcp__calc__add", "mcp__calc__multiply"],)list_sessions()
Phần tiêu đề “list_sessions()”Liệt kê session đã qua kèm metadata. Lọc theo thư mục project hoặc liệt kê session trên toàn bộ project. Đồng bộ; trả về ngay lập tức.
def list_sessions( directory: str | None = None, limit: int | None = None, offset: int = 0, include_worktrees: bool = True) -> list[SDKSessionInfo]Parameters
Phần tiêu đề “Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
directory | str | None | None | Thư mục để liệt kê session. Khi bỏ trống, trả về session trên toàn bộ project |
limit | int | None | None | Số session tối đa trả về |
offset | int | 0 | Số session bỏ qua từ đầu kết quả đã sắp xếp. Dùng cùng limit để phân trang |
include_worktrees | bool | True | Khi directory nằm trong một git repository, gồm cả session từ mọi worktree path |
Return type: SDKSessionInfo
Phần tiêu đề “Return type: SDKSessionInfo”| Property | Type | Description |
|---|---|---|
session_id | str | Định danh session duy nhất |
summary | str | Tiêu đề hiển thị: tiêu đề tuỳ chỉnh, tóm tắt tự sinh, hoặc prompt đầu tiên |
last_modified | int | Thời điểm sửa đổi cuối, tính bằng milliseconds từ epoch |
file_size | int | None | Kích thước file session, tính bằng byte (None với backend lưu trữ từ xa) |
custom_title | str | None | Tiêu đề session do người dùng đặt |
first_prompt | str | None | Prompt người dùng có ý nghĩa đầu tiên trong session |
git_branch | str | None | Git branch tại thời điểm kết thúc session |
cwd | str | None | Thư mục làm việc của session |
tag | str | None | Tag session do người dùng đặt (xem tag_session()) |
created_at | int | None | Thời điểm tạo session, tính bằng milliseconds từ epoch |
Ví dụ
Phần tiêu đề “Ví dụ”In ra 10 session gần nhất của một project. Kết quả được sắp theo last_modified giảm dần, nên phần tử đầu tiên là mới nhất. Bỏ directory để tìm trên toàn bộ project.
from claude_agent_sdk import list_sessions
for session in list_sessions(directory="/path/to/project", limit=10): print(f"{session.summary} ({session.session_id})")get_session_messages()
Phần tiêu đề “get_session_messages()”Lấy message từ một session đã qua. Đồng bộ; trả về ngay lập tức.
def get_session_messages( session_id: str, directory: str | None = None, limit: int | None = None, offset: int = 0) -> list[SessionMessage]Parameters
Phần tiêu đề “Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
session_id | str | required | Session ID cần lấy message |
directory | str | None | None | Thư mục project để tìm. Khi bỏ trống, tìm trên toàn bộ project |
limit | int | None | None | Số message tối đa trả về |
offset | int | 0 | Số message bỏ qua từ đầu |
Return type: SessionMessage
Phần tiêu đề “Return type: SessionMessage”| Property | Type | Description |
|---|---|---|
type | Literal["user", "assistant"] | Vai trò message |
uuid | str | Định danh message duy nhất |
session_id | str | Định danh session |
message | Any | Nội dung message thô |
parent_tool_use_id | None | Dự phòng cho tương lai |
Ví dụ
Phần tiêu đề “Ví dụ”from claude_agent_sdk import list_sessions, get_session_messages
sessions = list_sessions(limit=1)if sessions: messages = get_session_messages(sessions[0].session_id) for msg in messages: print(f"[{msg.type}] {msg.uuid}")get_session_info()
Phần tiêu đề “get_session_info()”Đọc metadata của một session theo ID mà không quét toàn bộ thư mục project. Đồng bộ; trả về ngay lập tức.
def get_session_info( session_id: str, directory: str | None = None,) -> SDKSessionInfo | NoneParameters
Phần tiêu đề “Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
session_id | str | required | UUID của session cần tra cứu |
directory | str | None | None | Đường dẫn thư mục project. Khi bỏ trống, tìm trên mọi thư mục project |
Trả về SDKSessionInfo, hoặc None nếu không tìm thấy session.
Ví dụ
Phần tiêu đề “Ví dụ”Tra cứu metadata của một session mà không quét thư mục project. Hữu ích khi bạn đã có session ID từ lần chạy trước.
from claude_agent_sdk import get_session_info
info = get_session_info("550e8400-e29b-41d4-a716-446655440000")if info: print(f"{info.summary} (branch: {info.git_branch}, tag: {info.tag})")rename_session()
Phần tiêu đề “rename_session()”Đổi tên session bằng cách thêm một entry custom-title. Gọi lặp lại vẫn an toàn; tiêu đề gần nhất sẽ thắng. Đồng bộ.
def rename_session( session_id: str, title: str, directory: str | None = None,) -> NoneParameters
Phần tiêu đề “Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
session_id | str | required | UUID của session cần đổi tên |
title | str | required | Tiêu đề mới. Phải khác rỗng sau khi strip whitespace |
directory | str | None | None | Đường dẫn thư mục project. Khi bỏ trống, tìm trên mọi thư mục project |
Raise ValueError nếu session_id không phải UUID hợp lệ hoặc title rỗng; FileNotFoundError nếu không tìm thấy session.
Ví dụ
Phần tiêu đề “Ví dụ”Đổi tên session gần nhất để dễ tìm lại sau này. Tiêu đề mới xuất hiện trong SDKSessionInfo.custom_title ở những lần đọc sau.
from claude_agent_sdk import list_sessions, rename_session
sessions = list_sessions(directory="/path/to/project", limit=1)if sessions: rename_session(sessions[0].session_id, "Refactor auth module")tag_session()
Phần tiêu đề “tag_session()”Gắn tag cho một session. Truyền None để xoá tag. Gọi lặp lại vẫn an toàn; tag gần nhất sẽ thắng. Đồng bộ.
def tag_session( session_id: str, tag: str | None, directory: str | None = None,) -> NoneParameters
Phần tiêu đề “Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
session_id | str | required | UUID của session cần gắn tag |
tag | str | None | required | Chuỗi tag, hoặc None để xoá. Được unicode-sanitize trước khi lưu |
directory | str | None | None | Đường dẫn thư mục project. Khi bỏ trống, tìm trên mọi thư mục project |
Raise ValueError nếu session_id không phải UUID hợp lệ hoặc tag rỗng sau khi sanitize; FileNotFoundError nếu không tìm thấy session.
Ví dụ
Phần tiêu đề “Ví dụ”Gắn tag cho một session, sau đó lọc theo tag đó ở lần đọc sau. Truyền None để xoá tag đã có.
from claude_agent_sdk import list_sessions, tag_session
# Tag the most recent sessionsessions = list_sessions(directory="/path/to/project", limit=1)if sessions: tag_session(sessions[0].session_id, "needs-review")
# Later: find all sessions with that tagfor session in list_sessions(directory="/path/to/project"): if session.tag == "needs-review": print(session.summary)Classes
Phần tiêu đề “Classes”ClaudeSDKClient
Phần tiêu đề “ClaudeSDKClient”Duy trì một session hội thoại xuyên nhiều lượt trao đổi. Đây là phần tương đương phía Python với cách function query() của TypeScript SDK hoạt động nội bộ - nó tạo một đối tượng client có thể tiếp tục hội thoại.
Tính năng chính
Phần tiêu đề “Tính năng chính”- Session liên tục: Duy trì context hội thoại xuyên nhiều lần gọi
query() - Cùng hội thoại: Session giữ lại message trước đó
- Hỗ trợ interrupt: Có thể dừng thực thi giữa chừng
- Vòng đời tường minh: Bạn kiểm soát khi nào session bắt đầu và kết thúc
- Luồng dựa trên phản hồi: Có thể phản ứng với phản hồi và gửi follow-up
- Custom tools và hooks: Hỗ trợ custom tools (tạo bằng decorator
@tool) và hooks
class ClaudeSDKClient: def __init__(self, options: ClaudeAgentOptions | None = None, transport: Transport | None = None) async def connect(self, prompt: str | AsyncIterable[dict] | None = None) -> None async def query(self, prompt: str | AsyncIterable[dict], session_id: str = "default") -> None async def receive_messages(self) -> AsyncIterator[Message] async def receive_response(self) -> AsyncIterator[Message] async def interrupt(self) -> None async def set_permission_mode(self, mode: str) -> None async def set_model(self, model: str | None = None) -> None async def rewind_files(self, user_message_id: str) -> None async def get_mcp_status(self) -> McpStatusResponse async def reconnect_mcp_server(self, server_name: str) -> None async def toggle_mcp_server(self, server_name: str, enabled: bool) -> None async def stop_task(self, task_id: str) -> None async def get_server_info(self) -> dict[str, Any] | None async def disconnect(self) -> NoneMethods
Phần tiêu đề “Methods”| Method | Description |
|---|---|
__init__(options) | Khởi tạo client với cấu hình tuỳ chọn |
connect(prompt) | Kết nối tới Claude với một prompt khởi tạo tuỳ chọn hoặc message stream |
query(prompt, session_id) | Gửi một request mới ở streaming mode |
receive_messages() | Nhận toàn bộ message từ Claude dưới dạng async iterator |
receive_response() | Nhận message cho tới và bao gồm một ResultMessage |
interrupt() | Gửi tín hiệu interrupt (chỉ hoạt động ở streaming mode) |
set_permission_mode(mode) | Đổi permission mode cho session hiện tại |
set_model(model) | Đổi model cho session hiện tại. Truyền None để reset về mặc định |
rewind_files(user_message_id) | Khôi phục file về trạng thái tại user message chỉ định. Cần enable_file_checkpointing=True. Xem File checkpointing |
get_mcp_status() | Lấy trạng thái của mọi MCP server đã cấu hình. Trả về McpStatusResponse |
reconnect_mcp_server(server_name) | Thử kết nối lại một MCP server đã lỗi hoặc bị ngắt kết nối |
toggle_mcp_server(server_name, enabled) | Bật hoặc tắt một MCP server giữa session. Tắt sẽ gỡ tool của nó |
stop_task(task_id) | Dừng một background task đang chạy. Một TaskNotificationMessage với status "stopped" sẽ theo sau trong message stream |
get_server_info() | Lấy thông tin server gồm session ID và capabilities |
disconnect() | Ngắt kết nối khỏi Claude |
Hỗ trợ Context Manager
Phần tiêu đề “Hỗ trợ Context Manager”Client có thể dùng như một async context manager để tự động quản lý kết nối:
import asynciofrom claude_agent_sdk import ClaudeSDKClient
async def main(): async with ClaudeSDKClient() as client: await client.query("Hello Claude") async for message in client.receive_response(): print(message)
asyncio.run(main())Quan trọng: Khi lặp qua message, tránh dùng
breakđể thoát sớm vì có thể gây lỗi cleanup asyncio. Thay vào đó, để vòng lặp hoàn tất tự nhiên hoặc dùng flag để đánh dấu khi bạn đã tìm thấy thứ cần tìm.
Ví dụ - Tiếp tục một hội thoại
Phần tiêu đề “Ví dụ - Tiếp tục một hội thoại”import asynciofrom claude_agent_sdk import ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage
async def main(): async with ClaudeSDKClient() as client: # First question await client.query("What's the capital of France?")
# Process response async for message in client.receive_response(): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, TextBlock): print(f"Claude: {block.text}")
# Follow-up question - the session retains the previous context await client.query("What's the population of that city?")
async for message in client.receive_response(): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, TextBlock): print(f"Claude: {block.text}")
# Another follow-up - still in the same conversation await client.query("What are some famous landmarks there?")
async for message in client.receive_response(): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, TextBlock): print(f"Claude: {block.text}")
asyncio.run(main())Ví dụ - Streaming input với ClaudeSDKClient
Phần tiêu đề “Ví dụ - Streaming input với ClaudeSDKClient”import asynciofrom claude_agent_sdk import ClaudeSDKClient
async def message_stream(): """Generate messages dynamically.""" yield { "type": "user", "message": {"role": "user", "content": "Analyze the following data:"}, } await asyncio.sleep(0.5) yield { "type": "user", "message": {"role": "user", "content": "Temperature: 25°C, Humidity: 60%"}, } await asyncio.sleep(0.5) yield { "type": "user", "message": {"role": "user", "content": "What patterns do you see?"}, }
async def main(): async with ClaudeSDKClient() as client: # Stream input to Claude await client.query(message_stream())
# Process response async for message in client.receive_response(): print(message)
# Follow-up in same session await client.query("Should we be concerned about these readings?")
async for message in client.receive_response(): print(message)
asyncio.run(main())Ví dụ - Dùng interrupt
Phần tiêu đề “Ví dụ - Dùng interrupt”import asynciofrom claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, ResultMessage
async def interruptible_task(): options = ClaudeAgentOptions(allowed_tools=["Bash"], permission_mode="acceptEdits")
async with ClaudeSDKClient(options=options) as client: # Start a long-running task await client.query("Count from 1 to 100 slowly, using the bash sleep command")
# Let it run for a bit await asyncio.sleep(2)
# Interrupt the task await client.interrupt() print("Task interrupted!")
# Drain the interrupted task's messages (including its ResultMessage) async for message in client.receive_response(): if isinstance(message, ResultMessage): print(f"Interrupted task: terminal_reason={message.terminal_reason!r}") # terminal_reason is "aborted_streaming" or "aborted_tools" # for interrupted turns
# Send a new command await client.query("Just say hello instead")
# Now receive the new response async for message in client.receive_response(): if isinstance(message, ResultMessage) and message.subtype == "success": print(f"New result: {message.result}")
asyncio.run(interruptible_task())Ví dụ - Kiểm soát permission nâng cao
Phần tiêu đề “Ví dụ - Kiểm soát permission nâng cao”import asynciofrom claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptionsfrom claude_agent_sdk.types import ( PermissionResultAllow, PermissionResultDeny, ToolPermissionContext,)
async def custom_permission_handler( tool_name: str, input_data: dict, context: ToolPermissionContext) -> PermissionResultAllow | PermissionResultDeny: """Custom logic for tool permissions."""
# Block writes to system directories if tool_name == "Write" and input_data.get("file_path", "").startswith("/system/"): return PermissionResultDeny( message="System directory write not allowed", interrupt=True )
# Redirect sensitive file operations if tool_name in ["Write", "Edit"] and "config" in input_data.get("file_path", ""): safe_path = f"./sandbox/{input_data['file_path']}" return PermissionResultAllow( updated_input={**input_data, "file_path": safe_path} )
# Allow everything else return PermissionResultAllow(updated_input=input_data)
async def main(): # Don't also list the gated tools in allowed_tools: allow rules approve calls before can_use_tool runs options = ClaudeAgentOptions(can_use_tool=custom_permission_handler)
async with ClaudeSDKClient(options=options) as client: await client.query("Update the system config file")
async for message in client.receive_response(): # Will use sandbox path instead print(message)
asyncio.run(main())Types
Phần tiêu đề “Types”SdkMcpTool
Phần tiêu đề “SdkMcpTool”Định nghĩa cho một SDK MCP tool tạo bằng decorator @tool.
@dataclassclass SdkMcpTool(Generic[T]): name: str description: str input_schema: type[T] | dict[str, Any] handler: Callable[[T], Awaitable[dict[str, Any]]] annotations: ToolAnnotations | None = None| Property | Type | Description |
|---|---|---|
name | str | Định danh duy nhất cho tool |
description | str | Mô tả dễ đọc |
input_schema | type[T] | dict[str, Any] | Schema để validate input |
handler | Callable[[T], Awaitable[dict[str, Any]]] | Hàm async xử lý thực thi tool |
annotations | ToolAnnotations | None | Annotation MCP tool tuỳ chọn (ví dụ, readOnlyHint, destructiveHint, openWorldHint). Từ mcp.types |
Transport
Phần tiêu đề “Transport”Abstract base class cho triển khai transport tuỳ biến. Dùng để giao tiếp với process Claude qua một kênh tuỳ biến (ví dụ, một kết nối từ xa thay vì subprocess cục bộ).
from abc import ABC, abstractmethodfrom collections.abc import AsyncIteratorfrom typing import Any
class Transport(ABC): @abstractmethod async def connect(self) -> None: ...
@abstractmethod async def write(self, data: str) -> None: ...
@abstractmethod def read_messages(self) -> AsyncIterator[dict[str, Any]]: ...
@abstractmethod async def close(self) -> None: ...
@abstractmethod def is_ready(self) -> bool: ...
@abstractmethod async def end_input(self) -> None: ...| Method | Description |
|---|---|
connect() | Kết nối transport và chuẩn bị giao tiếp |
write(data) | Ghi dữ liệu thô (JSON + newline) vào transport |
read_messages() | Async iterator yield ra message JSON đã parse |
close() | Đóng kết nối và dọn dẹp tài nguyên |
is_ready() | Trả về True nếu transport có thể gửi và nhận |
end_input() | Đóng input stream (ví dụ, đóng stdin cho transport subprocess) |
Import: from claude_agent_sdk import Transport
ClaudeAgentOptions
Phần tiêu đề “ClaudeAgentOptions”Dataclass cấu hình cho query Claude Code.
@dataclassclass ClaudeAgentOptions: tools: list[str] | ToolsPreset | None = None allowed_tools: list[str] = field(default_factory=list) system_prompt: str | SystemPromptPreset | SystemPromptFile | None = None mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict) strict_mcp_config: bool = False permission_mode: PermissionMode | None = None continue_conversation: bool = False resume: str | None = None session_id: str | None = None max_turns: int | None = None max_budget_usd: float | None = None disallowed_tools: list[str] = field(default_factory=list) model: str | None = None fallback_model: str | None = None betas: list[SdkBeta] = field(default_factory=list) output_format: dict[str, Any] | None = None permission_prompt_tool_name: str | None = None cwd: str | Path | None = None cli_path: str | Path | None = None settings: str | None = None add_dirs: list[str | Path] = field(default_factory=list) env: dict[str, str] = field(default_factory=dict) extra_args: dict[str, str | None] = field(default_factory=dict) max_buffer_size: int | None = None debug_stderr: Any = sys.stderr # Deprecated stderr: Callable[[str], None] | None = None can_use_tool: CanUseTool | None = None hooks: dict[HookEvent, list[HookMatcher]] | None = None user: str | None = None include_partial_messages: bool = False include_hook_events: bool = False fork_session: bool = False agents: dict[str, AgentDefinition] | None = None setting_sources: list[SettingSource] | None = None skills: list[str] | Literal["all"] | None = None sandbox: SandboxSettings | None = None plugins: list[SdkPluginConfig] = field(default_factory=list) max_thinking_tokens: int | None = None # Deprecated: use thinking instead thinking: ThinkingConfig | None = None effort: EffortLevel | None = None enable_file_checkpointing: bool = False session_store: SessionStore | None = None session_store_flush: SessionStoreFlushMode = "batched" load_timeout_ms: int = 60_000 task_budget: TaskBudget | None = None| Property | Type | Default | Description |
|---|---|---|---|
tools | list[str] | ToolsPreset | None | None | Cấu hình tool. Dùng {"type": "preset", "preset": "claude_code"} cho bộ tool mặc định của Claude Code |
allowed_tools | list[str] | [] | Tool tự động chấp thuận không cần hỏi. Không giới hạn Claude chỉ dùng các tool này; tool chưa liệt kê sẽ rơi xuống permission_mode và can_use_tool. Dùng disallowed_tools để chặn tool. Xem Permissions |
system_prompt | str | SystemPromptPreset | SystemPromptFile | None | None | Cấu hình system prompt. Truyền một chuỗi cho prompt tuỳ chỉnh, {"type": "preset", "preset": "claude_code"} cho system prompt của Claude Code kèm "append" tuỳ chọn, hoặc {"type": "file", "path": "..."} để nạp prompt lớn từ đĩa. Xem SystemPromptPreset và SystemPromptFile |
mcp_servers | dict[str, McpServerConfig] | str | Path | {} | Cấu hình MCP server hoặc đường dẫn tới file config |
strict_mcp_config | bool | False | Khi True, chỉ dùng server truyền trong mcp_servers và bỏ qua .mcp.json của project, user settings, MCP server do plugin cung cấp, và claude.ai connectors. Ánh xạ tới cờ CLI --strict-mcp-config |
permission_mode | PermissionMode | None | None | Permission mode cho việc dùng tool |
continue_conversation | bool | False | Tiếp tục hội thoại gần nhất |
resume | str | None | None | Session ID cần resume |
session_id | str | None | None | Dùng một session ID cụ thể thay vì tự sinh. Phải là UUID hợp lệ. Không thể kết hợp với continue_conversation hoặc resume trừ khi fork_session cũng được đặt |
max_turns | int | None | None | Số turn agentic tối đa (vòng round-trip dùng tool) |
max_budget_usd | float | None | None | Dừng query khi ước tính chi phí phía client đạt giá trị USD này. So sánh với cùng ước tính như total_cost_usd; xem Track cost and usage để biết các lưu ý về độ chính xác |
disallowed_tools | list[str] | [] | Tool bị từ chối. Một tên trần như "Bash" loại bỏ tool khỏi context của Claude. Một rule có phạm vi như "Bash(rm *)" vẫn giữ tool khả dụng nhưng từ chối các lời gọi khớp ở mọi permission mode, kể cả bypassPermissions. Xem Permissions |
enable_file_checkpointing | bool | False | Bật theo dõi thay đổi file để rewind. Xem File checkpointing |
model | str | None | None | Alias model Claude hoặc tên model đầy đủ. Xem các giá trị chấp nhận và ID theo provider |
fallback_model | str | None | None | Model dự phòng dùng khi model chính lỗi |
betas | list[SdkBeta] | [] | Beta feature cần bật. Xem SdkBeta để biết các lựa chọn khả dụng |
output_format | dict[str, Any] | None | None | Định dạng output cho phản hồi có cấu trúc (ví dụ, {"type": "json_schema", "schema": {...}}). Xem Structured outputs để biết chi tiết |
permission_prompt_tool_name | str | None | None | Tên MCP tool cho permission prompt |
cwd | str | Path | None | None | Thư mục làm việc hiện tại |
cli_path | str | Path | None | None | Đường dẫn tuỳ chỉnh tới file thực thi Claude Code CLI |
settings | str | None | None | Đường dẫn tới file settings |
add_dirs | list[str | Path] | [] | Thư mục bổ sung Claude được phép truy cập |
env | dict[str, str] | {} | Biến môi trường được merge chồng lên môi trường process kế thừa. Xem Environment variables cho các biến CLI đọc, và phần “Xử lý phản hồi API chậm hoặc treo” bên dưới cho các biến liên quan đến timeout |
extra_args | dict[str, str | None] | {} | Tham số CLI bổ sung truyền thẳng cho CLI |
max_buffer_size | int | None | None | Số byte tối đa khi buffer stdout của CLI |
debug_stderr | Any | sys.stderr | Deprecated - Đối tượng file-like cho debug output. Dùng callback stderr thay thế |
stderr | Callable[[str], None] | None | None | Hàm callback cho stderr output từ CLI |
can_use_tool | CanUseTool | None | None | Callback permission cho tool, chỉ được gọi khi luồng permission rơi xuống một prompt. Không được gọi cho lời gọi đã tự động chấp thuận bởi allowed_tools, allow rule, hoặc permission_mode. AskUserQuestion, connector tool tổ chức bạn đặt thành ask, và MCP tool đánh dấu requiresUserInteraction vẫn tới được callback dù bạn đã cho phép; ở dontAsk mode những trường hợp này bị từ chối thay vì gọi callback. Xem CanUseTool để biết chi tiết |
hooks | dict[HookEvent, list[HookMatcher]] | None | None | Cấu hình hook để chặn (intercept) event |
user | str | None | None | Định danh người dùng |
include_partial_messages | bool | False | Gồm cả event streaming message một phần. Khi bật, message StreamEvent sẽ được yield |
include_hook_events | bool | False | Gồm cả event vòng đời hook trong message stream dưới dạng đối tượng HookEventMessage |
fork_session | bool | False | Khi resume bằng resume, fork sang một session ID mới thay vì tiếp tục session gốc |
agents | dict[str, AgentDefinition] | None | None | Subagent định nghĩa bằng code |
plugins | list[SdkPluginConfig] | [] | Nạp plugin tuỳ chỉnh từ đường dẫn cục bộ. Xem Plugins để biết chi tiết |
sandbox | SandboxSettings | None | None | Cấu hình hành vi sandbox bằng code. Xem Sandbox settings để biết chi tiết |
setting_sources | list[SettingSource] | None | None (mặc định CLI: mọi source) | Kiểm soát nguồn settings filesystem nào được nạp. Truyền [] để tắt user, project, và local settings. Policy do endpoint quản lý luôn được nạp bất kể; server-managed settings được lấy khi session xác thực bằng credential tổ chức trên một cấu hình đủ điều kiện. Xem Use Claude Code features |
skills | list[str] | Literal["all"] | None | None | Skill khả dụng cho session. Truyền "all" để bật mọi skill phát hiện được, hoặc một danh sách tên skill. Khi đặt, SDK tự thêm Skill tool vào allowed_tools. Nếu bạn cũng truyền tools, hãy gồm "Skill" trong danh sách đó. Xem Skills |
max_thinking_tokens | int | None | None | Deprecated - Số token tối đa cho thinking block. Dùng thinking thay thế |
thinking | ThinkingConfig | None | None | Kiểm soát hành vi extended thinking. Ưu tiên hơn max_thinking_tokens |
effort | EffortLevel | None | None | Mức effort cho độ sâu thinking. Xem adjust the effort level |
session_store | SessionStore | None | None | Mirror transcript session sang backend bên ngoài để bất kỳ host nào cũng resume được. Xem Persist sessions to external storage |
session_store_flush | Literal["batched", "eager"] | "batched" | Khi nào flush entry transcript đã mirror sang session_store. "batched" flush một lần mỗi turn hoặc khi buffer đầy; "eager" kích hoạt flush nền sau mỗi frame. Bị bỏ qua khi session_store là None |
load_timeout_ms | int | 60000 | Timeout cho mỗi lần gọi session_store.load() và list_subkeys() trong lúc materialize resume, tính bằng milliseconds |
task_budget | TaskBudget | None | None | Task budget phía API tính bằng token. Gửi dưới dạng output_config.task_budget kèm beta header task-budgets-2026-03-13. Truyền {"total": <int>}. |
Xử lý phản hồi API chậm hoặc treo
Phần tiêu đề “Xử lý phản hồi API chậm hoặc treo”Process con CLI đọc một số biến môi trường kiểm soát timeout API và phát hiện treo (stall). Truyền chúng qua ClaudeAgentOptions.env:
from claude_agent_sdk import ClaudeAgentOptions
options = ClaudeAgentOptions( env={ "API_TIMEOUT_MS": "120000", "CLAUDE_CODE_MAX_RETRIES": "2", "CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS": "120000", },)API_TIMEOUT_MS: timeout mỗi request trên client Anthropic, tính bằng milliseconds. Mặc định600000. Áp dụng cho vòng lặp chính và mọi subagent.CLAUDE_CODE_MAX_RETRIES: số lần retry API tối đa. Mặc định10, giới hạn trần15. Mỗi lần retry có riêng khoảngAPI_TIMEOUT_MS, nên thời gian chờ tệ nhất khoảngAPI_TIMEOUT_MS × (CLAUDE_CODE_MAX_RETRIES + 1)cộng backoff. Với các lần chạy không giám sát cần chờ qua sự cố dài hơn, đặtCLAUDE_CODE_RETRY_WATCHDOG=1: nó retry lỗi capacity vô hạn, và kể từ Claude Code v2.1.199 nâng mặc định cho các lỗi tạm thời khác lên300và bỏ giới hạn trần của biến này.CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS: watchdog phát hiện treo cho subagent chạy bằngrun_in_background. Mặc định600000. Reset mỗi khi có stream event; khi treo nó abort subagent, đánh dấu task lỗi, và trả lỗi về parent kèm kết quả một phần nếu có. Không áp dụng cho subagent đồng bộ.CLAUDE_ENABLE_STREAM_WATCHDOGcùngCLAUDE_STREAM_IDLE_TIMEOUT_MS: abort request khi header đã đến nhưng response body ngừng stream. Watchdog bật mặc định cho mọi provider; đặtCLAUDE_ENABLE_STREAM_WATCHDOG=0để tắt.CLAUDE_STREAM_IDLE_TIMEOUT_MSmặc định300000và bị clamp về mức tối thiểu đó. Sau khi abort, Claude Code retry request tối đa một lần, và chỉ khi Claude chưa bắt đầu một khối text hoặc tool call trong phản hồi; một khi Claude đã hoàn tất một khối text hoặc tool call, Claude Code giữ lại output đã hoàn tất, thêm một thông báo phản hồi có thể chưa đầy đủ thay vì retry, và vẫn chạy bất kỳ tool call nào đã hoàn tất.
OutputFormat
Phần tiêu đề “OutputFormat”Cấu hình để validate structured output. Truyền cái này dưới dạng dict cho field output_format trên ClaudeAgentOptions:
# Expected dict shape for output_format{ "type": "json_schema", "schema": {...}, # Your JSON Schema definition}| Field | Required | Description |
|---|---|---|
type | Yes | Phải là "json_schema" để validate theo JSON Schema |
schema | Yes | Định nghĩa JSON Schema để validate output |
SystemPromptPreset
Phần tiêu đề “SystemPromptPreset”Cấu hình để dùng preset system prompt của Claude Code kèm bổ sung tuỳ chọn.
class SystemPromptPreset(TypedDict): type: Literal["preset"] preset: Literal["claude_code"] append: NotRequired[str] exclude_dynamic_sections: NotRequired[bool]| Field | Required | Description |
|---|---|---|
type | Yes | Phải là "preset" để dùng preset system prompt |
preset | Yes | Phải là "claude_code" để dùng system prompt của Claude Code |
append | No | Hướng dẫn bổ sung nối thêm vào preset system prompt |
exclude_dynamic_sections | No | Chuyển context riêng theo session như thư mục làm việc, cờ git-repo, và đường dẫn auto-memory ra khỏi system prompt vào user message đầu tiên. Cải thiện việc tái sử dụng prompt cache xuyên user và máy. Xem Modify system prompts |
SystemPromptFile
Phần tiêu đề “SystemPromptFile”Cấu hình để nạp system prompt tuỳ chỉnh từ file thay vì truyền dưới dạng string. SDK ánh xạ cái này tới cờ CLI --system-prompt-file. Dùng dạng file khi prompt lớn: SDK truyền chuỗi system_prompt trên argv của process con CLI, chịu giới hạn độ dài dòng lệnh của OS trước khi SDK gửi bất kỳ request API nào. Trên Linux, một argument dài hơn khoảng 128 KB sẽ lỗi ngay khi spawn process với Argument list too long. Trên Windows, toàn bộ dòng lệnh bị giới hạn khoảng 32 KB, nên dạng string sẽ lỗi ở ngưỡng thấp hơn.
class SystemPromptFile(TypedDict): type: Literal["file"] path: str| Field | Required | Description |
|---|---|---|
type | Yes | Phải là "file" để nạp prompt từ đĩa |
path | Yes | Đường dẫn tới file chứa system prompt |
SettingSource
Phần tiêu đề “SettingSource”Kiểm soát nguồn cấu hình dựa trên filesystem nào SDK nạp settings từ đó.
SettingSource = Literal["user", "project", "local"]| Value | Description | Location |
|---|---|---|
"user" | Settings người dùng toàn cục | ~/.claude/settings.json |
"project" | Settings project dùng chung (được version control) | .claude/settings.json |
"local" | Settings project cục bộ, bị gitignore khi Claude Code lưu một setting vào đó | .claude/settings.local.json |
Hành vi mặc định
Phần tiêu đề “Hành vi mặc định”Khi setting_sources bị bỏ trống hoặc None, query() nạp cùng bộ settings filesystem như CLI Claude Code: user, project, và local. Policy do endpoint quản lý luôn được nạp trong mọi trường hợp; server-managed settings được lấy khi session xác thực bằng credential tổ chức trên một cấu hình đủ điều kiện. Xem “What settingSources does not control” để biết các input được đọc bất kể option này, và cách tắt chúng.
Vì sao dùng setting_sources
Phần tiêu đề “Vì sao dùng setting_sources”Tắt settings filesystem:
# Do not load user, project, or local settings from diskimport asynciofrom claude_agent_sdk import query, ClaudeAgentOptions
async def main(): async for message in query( prompt="Analyze this code", options=ClaudeAgentOptions( setting_sources=[] ), ): print(message)
asyncio.run(main())Nạp toàn bộ settings filesystem tường minh:
import asynciofrom claude_agent_sdk import query, ClaudeAgentOptions
async def main(): async for message in query( prompt="Analyze this code", options=ClaudeAgentOptions( setting_sources=["user", "project", "local"] ), ): print(message)
asyncio.run(main())Chỉ nạp một số setting source cụ thể:
# Load only project settings, ignore user and localimport asynciofrom claude_agent_sdk import query, ClaudeAgentOptions
async def main(): async for message in query( prompt="Run CI checks", options=ClaudeAgentOptions( setting_sources=["project"] # Only .claude/settings.json ), ): print(message)
asyncio.run(main())Môi trường testing và CI:
# Ensure consistent behavior in CI by excluding local settingsimport asynciofrom claude_agent_sdk import query, ClaudeAgentOptions
async def main(): async for message in query( prompt="Run tests", options=ClaudeAgentOptions( setting_sources=["project"], # Only team-shared settings permission_mode="bypassPermissions", ), ): print(message)
asyncio.run(main())Ứng dụng chỉ dùng SDK:
# Define everything programmatically.# Pass [] to opt out of filesystem setting sources.import asynciofrom claude_agent_sdk import AgentDefinition, ClaudeAgentOptions, query
async def main(): async for message in query( prompt="Review this PR", options=ClaudeAgentOptions( setting_sources=[], agents={ "code-reviewer": AgentDefinition( description="Reviews code changes", prompt="You are a code reviewer. Report issues in the diff.", ), }, allowed_tools=["Read", "Grep", "Glob"], ), ): print(message)
asyncio.run(main())Nạp hướng dẫn project CLAUDE.md:
# Load project settings to include CLAUDE.md filesimport asynciofrom claude_agent_sdk import query, ClaudeAgentOptions
async def main(): async for message in query( prompt="Add a new feature following project conventions", options=ClaudeAgentOptions( system_prompt={ "type": "preset", "preset": "claude_code", # Use Claude Code's system prompt }, setting_sources=["project"], # Loads CLAUDE.md from project allowed_tools=["Read", "Write", "Edit"], ), ): print(message)
asyncio.run(main())Thứ tự ưu tiên settings
Phần tiêu đề “Thứ tự ưu tiên settings”Khi nhiều source được nạp, settings được merge theo thứ tự ưu tiên này (cao nhất đến thấp nhất):
- Local settings (
.claude/settings.local.json) - Project settings (
.claude/settings.json) - User settings (
~/.claude/settings.json)
Các option lập trình như agents và allowed_tools ghi đè settings filesystem user, project, và local. Managed policy settings có ưu tiên cao hơn các option lập trình.
AgentDefinition
Phần tiêu đề “AgentDefinition”Cấu hình cho một subagent định nghĩa bằng code.
@dataclassclass AgentDefinition: description: str prompt: str tools: list[str] | None = None disallowedTools: list[str] | None = None model: str | None = None skills: list[str] | None = None memory: Literal["user", "project", "local"] | None = None mcpServers: list[str | dict[str, Any]] | None = None initialPrompt: str | None = None maxTurns: int | None = None background: bool | None = None effort: EffortLevel | int | None = None permissionMode: PermissionMode | None = None| Field | Required | Description |
|---|---|---|
description | Yes | Mô tả bằng ngôn ngữ tự nhiên về khi nào dùng agent này |
prompt | Yes | System prompt của agent |
tools | No | Mảng tên tool được phép. Nếu bỏ trống, kế thừa mọi tool khả dụng cho subagent |
disallowedTools | No | Mảng tên tool bị gỡ khỏi bộ tool của agent. Pattern cấp MCP server cũng được chấp nhận: mcp__server hoặc mcp__server__* gỡ mọi tool từ server đó, và mcp__* gỡ mọi MCP tool từ mọi server |
model | No | Ghi đè model cho agent này. Chấp nhận alias như "sonnet", "opus", "haiku", hoặc "inherit", hoặc một model ID đầy đủ. Nếu bỏ trống, dùng model chính |
skills | No | Danh sách tên skill nạp trước vào context của agent khi khởi động. Skill chưa liệt kê vẫn gọi được qua Skill tool |
memory | No | Nguồn memory cho agent này: "user", "project", hoặc "local" |
mcpServers | No | MCP server khả dụng cho agent này. Mỗi entry là tên server hoặc một dict inline {name: config} |
initialPrompt | No | Tự động gửi làm user turn đầu tiên khi agent này chạy vai trò main thread agent |
maxTurns | No | Số turn agentic tối đa trước khi agent dừng |
background | No | Chạy agent này như một background task không chặn khi được gọi |
effort | No | Mức reasoning effort cho agent này. Chấp nhận một level đặt tên hoặc số nguyên. Xem EffortLevel |
permissionMode | No | Permission mode cho việc thực thi tool trong agent này. Xem PermissionMode |
PermissionMode
Phần tiêu đề “PermissionMode”Permission mode để kiểm soát việc thực thi tool.
PermissionMode = Literal[ "default", # Standard permission behavior "acceptEdits", # Auto-accept file edits "plan", # Planning mode - explore without editing "dontAsk", # Deny anything not pre-approved instead of prompting "bypassPermissions", # Bypass permission checks; explicit ask rules still prompt (use with caution) "auto", # Model classifier approves or denies permission prompts]EffortLevel
Phần tiêu đề “EffortLevel”Mức effort để định hướng độ sâu thinking.
EffortLevel = Literal[ "low", # Minimal thinking, fastest responses "medium", # Moderate thinking "high", # Deep reasoning "xhigh", # Extended reasoning; falls back to "high" on models that don't support it "max", # Maximum effort]CanUseTool
Phần tiêu đề “CanUseTool”Type alias cho hàm callback permission tool.
CanUseTool = Callable[ [str, dict[str, Any], ToolPermissionContext], Awaitable[PermissionResult]]Callback nhận:
tool_name: Tên tool đang được gọiinput_data: Tham số đầu vào của toolcontext: MộtToolPermissionContextkèm thông tin bổ sung
Trả về một PermissionResult (hoặc PermissionResultAllow hoặc PermissionResultDeny).
Callback là bản thay thế phía SDK cho permission prompt tương tác: nó chỉ được gọi khi luồng đánh giá permission dẫn tới một prompt. Lời gọi tool đã được chấp thuận bởi một entry allowed_tools, một allow rule trong settings, hoặc permission mode, như acceptEdits hoặc bypassPermissions, không bao giờ gọi nó. Để chặn (gate) mọi lời gọi tool, dùng một PreToolUse hook thay thế.
AskUserQuestion, MCP tool đánh dấu requiresUserInteraction, và connector tool tổ chức bạn đặt thành ask vẫn tới được callback ngay cả khi một allow rule khớp. Ở dontAsk mode những lời gọi này bị từ chối thay vì gọi callback.
ToolPermissionContext
Phần tiêu đề “ToolPermissionContext”Thông tin context truyền cho callback permission của tool.
@dataclassclass ToolPermissionContext: signal: Any | None = None # Future: abort signal support suggestions: list[PermissionUpdate] = field(default_factory=list) tool_use_id: str | None = None agent_id: str | None = None blocked_path: str | None = None decision_reason: str | None = None title: str | None = None display_name: str | None = None description: str | None = None| Field | Type | Description |
|---|---|---|
signal | Any | None | Dự phòng cho hỗ trợ abort signal trong tương lai |
suggestions | list[PermissionUpdate] | Gợi ý cập nhật permission từ CLI. Bash prompt gồm một gợi ý với destination localSettings, nên trả về nó trong updated_permissions sẽ ghi rule vào .claude/settings.local.json và duy trì qua các session. |
tool_use_id | str | None | Định danh của lời gọi tool cụ thể mà prompt này dành cho. Luôn có mặt khi truyền tới can_use_tool |
agent_id | str | None | Sub-agent ID khi lời gọi bắt nguồn từ một subagent; None cho main agent |
blocked_path | str | None | Đường dẫn file gây ra yêu cầu permission, nếu áp dụng. Ví dụ, khi một lệnh Bash cố truy cập đường dẫn ngoài thư mục được phép |
decision_reason | str | None | Lý do yêu cầu permission này được kích hoạt. Chuyển tiếp từ permissionDecisionReason của một PreToolUse hook khi hook trả về "ask" |
title | str | None | Câu prompt permission đầy đủ, ví dụ Claude wants to read foo.txt. Dùng làm text prompt chính khi có mặt |
display_name | str | None | Cụm danh từ ngắn cho hành động tool, ví dụ Read file, phù hợp cho nhãn nút |
description | str | None | Phụ đề dễ đọc cho UI permission |
PermissionResult
Phần tiêu đề “PermissionResult”Union type cho kết quả callback permission.
PermissionResult = PermissionResultAllow | PermissionResultDenyPermissionResultAllow
Phần tiêu đề “PermissionResultAllow”Kết quả cho biết lời gọi tool nên được cho phép.
@dataclassclass PermissionResultAllow: behavior: Literal["allow"] = "allow" updated_input: dict[str, Any] | None = None updated_permissions: list[PermissionUpdate] | None = None| Field | Type | Default | Description |
|---|---|---|---|
behavior | Literal["allow"] | "allow" | Phải là “allow” |
updated_input | dict[str, Any] | None | None | Input đã sửa dùng thay cho input gốc |
updated_permissions | list[PermissionUpdate] | None | None | Các cập nhật permission cần áp dụng |
PermissionResultDeny
Phần tiêu đề “PermissionResultDeny”Kết quả cho biết lời gọi tool nên bị từ chối.
@dataclassclass PermissionResultDeny: behavior: Literal["deny"] = "deny" message: str = "" interrupt: bool = False| Field | Type | Default | Description |
|---|---|---|---|
behavior | Literal["deny"] | "deny" | Phải là “deny” |
message | str | "" | Thông báo giải thích vì sao tool bị từ chối |
interrupt | bool | False | Có interrupt lần thực thi hiện tại hay không |
PermissionUpdate
Phần tiêu đề “PermissionUpdate”Cấu hình để cập nhật permission bằng code.
@dataclassclass PermissionUpdate: type: Literal[ "addRules", "replaceRules", "removeRules", "setMode", "addDirectories", "removeDirectories", ] rules: list[PermissionRuleValue] | None = None behavior: Literal["allow", "deny", "ask"] | None = None mode: PermissionMode | None = None directories: list[str] | None = None destination: ( Literal["userSettings", "projectSettings", "localSettings", "session"] | None ) = None| Field | Type | Description |
|---|---|---|
type | Literal[...] | Loại thao tác cập nhật permission |
rules | list[PermissionRuleValue] | None | Rule cho thao tác add/replace/remove |
behavior | Literal["allow", "deny", "ask"] | None | Hành vi cho thao tác dựa trên rule |
mode | PermissionMode | None | Mode cho thao tác setMode |
directories | list[str] | None | Thư mục cho thao tác add/remove directory |
destination | Literal[...] | None | Nơi áp dụng cập nhật permission |
PermissionRuleValue
Phần tiêu đề “PermissionRuleValue”Một rule để add, replace, hoặc remove trong một cập nhật permission.
@dataclassclass PermissionRuleValue: tool_name: str rule_content: str | None = NoneToolsPreset
Phần tiêu đề “ToolsPreset”Cấu hình preset tools để dùng bộ tool mặc định của Claude Code.
class ToolsPreset(TypedDict): type: Literal["preset"] preset: Literal["claude_code"]ThinkingConfig
Phần tiêu đề “ThinkingConfig”Kiểm soát hành vi extended thinking. Một union của ba cấu hình:
ThinkingDisplay = Literal["summarized", "omitted"]
class ThinkingConfigAdaptive(TypedDict): type: Literal["adaptive"] display: NotRequired[ThinkingDisplay]
class ThinkingConfigEnabled(TypedDict): type: Literal["enabled"] budget_tokens: int display: NotRequired[ThinkingDisplay]
class ThinkingConfigDisabled(TypedDict): type: Literal["disabled"]
ThinkingConfig = ThinkingConfigAdaptive | ThinkingConfigEnabled | ThinkingConfigDisabled| Variant | Fields | Description |
|---|---|---|
adaptive | type, display | Claude tự quyết định khi nào cần thinking |
enabled | type, budget_tokens, display | Bật thinking với một budget token cụ thể |
disabled | type | Tắt thinking |
Field tuỳ chọn display kiểm soát việc thinking text được trả về "summarized" hay "omitted". Trên Claude Opus 4.7 trở lên, mặc định của API là "omitted", nên đặt "summarized" để nhận nội dung thinking trong output ThinkingBlock. Claude Code không gửi display tới Amazon Bedrock hoặc Google Cloud’s Agent Platform, nên trên các provider đó Opus 4.7 trở lên trả về ThinkingBlock rỗng ngay cả khi bạn đặt display thành "summarized".
Vì đây là các class TypedDict, chúng là plain dict khi chạy. Bạn có thể tạo chúng dưới dạng dict literal hoặc gọi class như một constructor; cả hai đều tạo ra một dict. Truy cập field bằng config["budget_tokens"], không phải config.budget_tokens:
from claude_agent_sdk import ClaudeAgentOptions, ThinkingConfigEnabled
# Option 1: dict literal (recommended, no import needed)options = ClaudeAgentOptions(thinking={"type": "enabled", "budget_tokens": 20000})
# Option 2: constructor-style (returns a plain dict)config = ThinkingConfigEnabled(type="enabled", budget_tokens=20000)print(config["budget_tokens"]) # 20000# config.budget_tokens would raise AttributeErrorTaskBudget
Phần tiêu đề “TaskBudget”Task budget phía API tính bằng token, dùng với field task_budget trong ClaudeAgentOptions.
class TaskBudget(TypedDict): total: int| Field | Type | Description |
|---|---|---|
total | int | Tổng token budget cho task |
Vì đây là TypedDict, truyền nó dưới dạng plain dict, ví dụ ClaudeAgentOptions(task_budget={"total": 50000}).
SdkBeta
Phần tiêu đề “SdkBeta”Literal type cho beta feature của SDK.
SdkBeta = Literal["context-1m-2025-08-07"]Dùng với field betas trong ClaudeAgentOptions để bật beta feature.
McpSdkServerConfig
Phần tiêu đề “McpSdkServerConfig”Cấu hình cho SDK MCP server tạo bằng create_sdk_mcp_server().
class McpSdkServerConfig(TypedDict): type: Literal["sdk"] name: str instance: Any # MCP Server instanceMcpServerConfig
Phần tiêu đề “McpServerConfig”Union type cho cấu hình MCP server.
McpServerConfig = ( McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfig)McpStdioServerConfig
Phần tiêu đề “McpStdioServerConfig”class McpStdioServerConfig(TypedDict): type: NotRequired[Literal["stdio"]] # Optional for backwards compatibility command: str args: NotRequired[list[str]] env: NotRequired[dict[str, str]]McpSSEServerConfig
Phần tiêu đề “McpSSEServerConfig”class McpSSEServerConfig(TypedDict): type: Literal["sse"] url: str headers: NotRequired[dict[str, str]]McpHttpServerConfig
Phần tiêu đề “McpHttpServerConfig”class McpHttpServerConfig(TypedDict): type: Literal["http"] url: str headers: NotRequired[dict[str, str]]McpServerStatusConfig
Phần tiêu đề “McpServerStatusConfig”Cấu hình của một MCP server như được báo cáo bởi get_mcp_status(). Đây là hợp của mọi biến thể transport của McpServerConfig cộng thêm biến thể chỉ dành cho output claudeai-proxy cho server được proxy qua claude.ai.
McpServerStatusConfig = ( McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfigStatus | McpClaudeAIProxyServerConfig)McpSdkServerConfigStatus là dạng có thể serialize của McpSdkServerConfig chỉ với field type ("sdk") và name (str); instance in-process bị lược bỏ. McpClaudeAIProxyServerConfig có field type ("claudeai-proxy"), url (str), và id (str).
McpStatusResponse
Phần tiêu đề “McpStatusResponse”Phản hồi từ ClaudeSDKClient.get_mcp_status(). Bọc danh sách trạng thái server dưới key mcpServers.
class McpStatusResponse(TypedDict): mcpServers: list[McpServerStatus]McpServerStatus
Phần tiêu đề “McpServerStatus”Trạng thái của một MCP server đã kết nối, nằm trong McpStatusResponse.
class McpServerStatus(TypedDict): name: str status: McpServerConnectionStatus # "connected" | "failed" | "needs-auth" | "pending" | "disabled" serverInfo: NotRequired[McpServerInfo] error: NotRequired[str] config: NotRequired[McpServerStatusConfig] scope: NotRequired[str] tools: NotRequired[list[McpToolInfo]]| Field | Type | Description |
|---|---|---|
name | str | Tên server |
status | str | Một trong "connected", "failed", "needs-auth", "pending", hoặc "disabled" |
serverInfo | dict (optional) | Tên và phiên bản server ({"name": str, "version": str}) |
error | str (optional) | Thông báo lỗi nếu server kết nối thất bại |
config | McpServerStatusConfig (optional) | Cấu hình server. Cùng dạng với McpServerConfig (stdio, SSE, HTTP, hoặc SDK), cộng thêm biến thể claudeai-proxy cho server kết nối qua claude.ai |
scope | str (optional) | Phạm vi cấu hình |
tools | list (optional) | Tool do server này cung cấp, mỗi cái kèm field name, description, và annotations |
SdkPluginConfig
Phần tiêu đề “SdkPluginConfig”Cấu hình để nạp plugin trong SDK.
class SdkPluginConfig(TypedDict): type: Literal["local"] path: str| Field | Type | Description |
|---|---|---|
type | Literal["local"] | Phải là "local" (hiện chỉ hỗ trợ plugin cục bộ) |
path | str | Đường dẫn tuyệt đối hoặc tương đối tới thư mục plugin |
Ví dụ:
plugins = [ {"type": "local", "path": "./my-plugin"}, {"type": "local", "path": "/absolute/path/to/plugin"},]Để biết thông tin đầy đủ về tạo và dùng plugin, xem Plugins.
Message Types
Phần tiêu đề “Message Types”Message
Phần tiêu đề “Message”Union type của mọi message có thể có.
Message = ( UserMessage | AssistantMessage | SystemMessage | ResultMessage | StreamEvent | RateLimitEvent)UserMessage
Phần tiêu đề “UserMessage”Message input người dùng.
@dataclassclass UserMessage: content: str | list[ContentBlock] uuid: str | None = None parent_tool_use_id: str | None = None tool_use_result: dict[str, Any] | None = None| Field | Type | Description |
|---|---|---|
content | str | list[ContentBlock] | Nội dung message dạng text hoặc content block |
uuid | str | None | Định danh message duy nhất |
parent_tool_use_id | str | None | Tool use ID nếu message này là phản hồi kết quả tool |
tool_use_result | dict[str, Any] | None | Dữ liệu kết quả tool nếu có |
AssistantMessage
Phần tiêu đề “AssistantMessage”Message phản hồi của assistant kèm content block.
@dataclassclass AssistantMessage: content: list[ContentBlock] model: str parent_tool_use_id: str | None = None error: AssistantMessageError | None = None usage: dict[str, Any] | None = None message_id: str | None = None stop_reason: str | None = None session_id: str | None = None uuid: str | None = None| Field | Type | Description |
|---|---|---|
content | list[ContentBlock] | Danh sách content block trong phản hồi |
model | str | Model đã sinh ra phản hồi |
parent_tool_use_id | str | None | Tool use ID nếu đây là phản hồi lồng nhau |
error | AssistantMessageError | None | Loại lỗi nếu phản hồi gặp lỗi |
usage | dict[str, Any] | None | Token usage của message này (cùng key với ResultMessage.usage) |
message_id | str | None | ID message của API. Nhiều message từ cùng một turn chia sẻ cùng ID |
stop_reason | str | None | Lý do dừng từ API (ví dụ end_turn, tool_use) |
session_id | str | None | ID session message này thuộc về |
uuid | str | None | Định danh message duy nhất trong transcript của session |
AssistantMessageError
Phần tiêu đề “AssistantMessageError”Các loại lỗi có thể có cho assistant message.
AssistantMessageError = Literal[ "authentication_failed", "billing_error", "rate_limit", "invalid_request", "server_error", "unknown",]Process con CLI bên dưới có thể phát ra loại lỗi không nằm trong Literal này, ví dụ max_output_tokens. SDK chuyển tiếp giá trị nguyên vẹn, nên hãy xử lý các chuỗi ngoài danh sách này giống như unknown. Type TypeScript SDKAssistantMessageError liệt kê đầy đủ tập giá trị mà CLI có thể phát ra.
SystemMessage
Phần tiêu đề “SystemMessage”Message hệ thống kèm metadata.
@dataclassclass SystemMessage: subtype: str data: dict[str, Any]ResultMessage
Phần tiêu đề “ResultMessage”Message kết quả cuối kèm thông tin chi phí và usage.
@dataclassclass ResultMessage: subtype: str duration_ms: int duration_api_ms: int is_error: bool num_turns: int session_id: str stop_reason: str | None = None total_cost_usd: float | None = None usage: dict[str, Any] | None = None result: str | None = None structured_output: Any = None model_usage: dict[str, ModelUsage] | None = None permission_denials: list[Any] | None = None deferred_tool_use: DeferredToolUse | None = None errors: list[str] | None = None api_error_status: int | None = None uuid: str | None = None terminal_reason: str | None = NoneField subtype quyết định field nào khác được điền. Nó là một trong "success", "error_during_execution", "error_max_turns", "error_max_budget_usd", hoặc "error_max_structured_output_retries". Python dataclass gộp mọi biến thể vào một hình dạng duy nhất, nên field không áp dụng cho subtype trả về sẽ là None.
Một số field mang chi tiết chẩn đoán về cách hội thoại kết thúc:
is_error:Truekhi hội thoại kết thúc ở trạng thái lỗi. LuônTruevới các subtypeerror_*. Vớisubtype="success", nó làTruekhi request model cuối cùng lỗi, nghĩa là vòng lặp agent đã hoàn tất nhưng lời gọi API cuối trả về lỗi.api_error_status: mã trạng thái HTTP của lỗi API kết thúc turn.Nonekhi turn kết thúc mà không có lỗi. Chỉ được điền khisubtype="success".result: text của assistant message cuối cùng khisubtype="success", hoặcNonevới các subtypeerror_*. Khisubtype="success"vàis_error=True, trường này chứa chuỗi lỗi API nếu có nhưng có thể rỗng, nên kiểm traapi_error_statusvà nội dungAssistantMessagetrước đó để biết chi tiết.errors: chuỗi lỗi cấp vòng lặp như thông báo max-turns. Chỉ được điền với các subtypeerror_*.terminal_reason: lý do vòng lặp query kết thúc, ví dụ"completed","max_turns","api_error","aborted_streaming", hoặc"aborted_tools". Giá trị"aborted_streaming"hoặc"aborted_tools"nghĩa là turn bị abort trước khi hoàn tất. Nguyên nhân phổ biến làinterrupt()và một permission callback trả vềPermissionResultDenyvớiinterrupt=True.Nonetrên các phiên bản CLI có trước field này, trên kết quả bỏ qua vòng lặp query như slash command cục bộ, hoặc trên kết quả lỗi tổng hợp phát ra khi session lỗi nghiêm trọng. Tương ứng vớiSDKResultMessage.terminal_reasoncủa TypeScript SDK, nơi liệt kê đầy đủ tập giá trị.
Dict usage chứa các key sau khi có mặt:
| Key | Type | Description |
|---|---|---|
input_tokens | int | Input token tiêu thụ bởi vòng lặp agent cấp cao nhất. Token của subagent không được gồm; dùng model_usage để hạch toán toàn bộ cây. |
output_tokens | int | Output token sinh ra bởi vòng lặp agent cấp cao nhất. Token của subagent không được gồm. |
cache_creation_input_tokens | int | Token dùng để tạo entry cache mới. |
cache_read_input_tokens | int | Token đọc từ entry cache đã có. |
Dict model_usage ánh xạ tên model tới usage theo từng model. Mỗi giá trị là một TypedDict ModelUsage có key dùng camelCase, vì giá trị được chuyển qua nguyên vẹn từ process con CLI bên dưới. Import qua from claude_agent_sdk.types import ModelUsage. Các key:
| Key | Type | Description |
|---|---|---|
inputTokens | int | Input token cho model này. |
outputTokens | int | Output token cho model này. |
cacheReadInputTokens | int | Token đọc cache cho model này. |
cacheCreationInputTokens | int | Token tạo cache cho model này. |
webSearchRequests | int | Số request web search model này đã thực hiện. |
costUSD | float | Chi phí ước tính bằng USD cho model này, tính phía client. Xem Track cost and usage để biết lưu ý về billing. |
contextWindow | int | Kích thước context window cho model này. |
maxOutputTokens | int | Giới hạn output token tối đa cho model này. |
canonicalModel | str | Model ID chuẩn dùng để tra cứu giá. Có thể khác với chuỗi model thô mà entry được key theo, như một ID hoặc alias riêng của provider. Không phải lúc nào cũng có. |
provider | str | API provider phục vụ model này, như firstParty, bedrock, vertex, foundry, anthropicAws, mantle, hoặc gateway. Không phải lúc nào cũng có. |
StreamEvent
Phần tiêu đề “StreamEvent”Stream event cho cập nhật message một phần trong lúc streaming. Chỉ nhận được khi include_partial_messages=True trong ClaudeAgentOptions. Import qua from claude_agent_sdk.types import StreamEvent.
@dataclassclass StreamEvent: uuid: str session_id: str event: dict[str, Any] # The raw Claude API stream event parent_tool_use_id: str | None = None| Field | Type | Description |
|---|---|---|
uuid | str | Định danh duy nhất cho event này |
session_id | str | Định danh session |
event | dict[str, Any] | Dữ liệu stream event thô từ Claude API |
parent_tool_use_id | str | None | Luôn None. Stream event chỉ phát cho session chính. Để phân định subagent, dùng message hoàn chỉnh như AssistantMessage |
RateLimitEvent
Phần tiêu đề “RateLimitEvent”Phát ra khi trạng thái rate limit thay đổi (ví dụ, từ "allowed" sang "allowed_warning"). Dùng cái này để cảnh báo người dùng trước khi họ chạm giới hạn cứng, hoặc để giảm tần suất khi trạng thái là "rejected".
@dataclassclass RateLimitEvent: rate_limit_info: RateLimitInfo uuid: str session_id: str| Field | Type | Description |
|---|---|---|
rate_limit_info | RateLimitInfo | Trạng thái rate limit hiện tại |
uuid | str | Định danh event duy nhất |
session_id | str | Định danh session |
RateLimitInfo
Phần tiêu đề “RateLimitInfo”Trạng thái rate limit mang bởi RateLimitEvent.
RateLimitStatus = Literal["allowed", "allowed_warning", "rejected"]RateLimitType = Literal[ "five_hour", "seven_day", "seven_day_opus", "seven_day_sonnet", "overage"]
@dataclassclass RateLimitInfo: status: RateLimitStatus resets_at: int | None = None rate_limit_type: RateLimitType | None = None utilization: float | None = None overage_status: RateLimitStatus | None = None overage_resets_at: int | None = None overage_disabled_reason: str | None = None raw: dict[str, Any] = field(default_factory=dict)| Field | Type | Description |
|---|---|---|
status | RateLimitStatus | Trạng thái hiện tại. "allowed_warning" nghĩa là gần chạm giới hạn; "rejected" nghĩa là đã chạm giới hạn |
resets_at | int | None | Unix timestamp khi cửa sổ rate limit reset |
rate_limit_type | RateLimitType | None | Cửa sổ rate limit nào áp dụng |
utilization | float | None | Tỷ lệ rate limit đã dùng (0.0 tới 1.0) |
overage_status | RateLimitStatus | None | Trạng thái sử dụng pay-as-you-go overage, nếu áp dụng |
overage_resets_at | int | None | Unix timestamp khi cửa sổ overage reset |
overage_disabled_reason | str | None | Vì sao overage không khả dụng, nếu status là "rejected" |
raw | dict[str, Any] | Dict thô đầy đủ từ CLI, gồm cả field chưa mô hình hoá ở trên |
TaskStartedMessage
Phần tiêu đề “TaskStartedMessage”Phát ra khi một background task bắt đầu. Một background task là bất kỳ thứ gì được theo dõi ngoài turn chính: một lệnh Bash chạy nền, một watch Monitor, một subagent sinh ra qua Agent tool, hoặc một remote agent. Field task_type cho biết đó là loại nào. Cách đặt tên này không liên quan tới việc đổi tên tool Task thành Agent.
@dataclassclass TaskStartedMessage(SystemMessage): task_id: str description: str uuid: str session_id: str tool_use_id: str | None = None task_type: str | None = None| Field | Type | Description |
|---|---|---|
task_id | str | Định danh duy nhất cho task |
description | str | Mô tả task |
uuid | str | Định danh message duy nhất |
session_id | str | Định danh session |
tool_use_id | str | None | Tool use ID liên quan |
task_type | str | None | Loại background task: "local_bash" cho Bash chạy nền và Monitor watch, "local_agent", hoặc "remote_agent" |
TaskUsage
Phần tiêu đề “TaskUsage”Dữ liệu token và thời gian cho một background task.
class TaskUsage(TypedDict): total_tokens: int tool_uses: int duration_ms: intTaskProgressMessage
Phần tiêu đề “TaskProgressMessage”Phát ra định kỳ với cập nhật tiến độ cho một background task đang chạy.
@dataclassclass TaskProgressMessage(SystemMessage): task_id: str description: str usage: TaskUsage uuid: str session_id: str tool_use_id: str | None = None last_tool_name: str | None = None| Field | Type | Description |
|---|---|---|
task_id | str | Định danh duy nhất cho task |
description | str | Mô tả trạng thái hiện tại |
usage | TaskUsage | Token usage của task tính tới hiện tại |
uuid | str | Định danh message duy nhất |
session_id | str | Định danh session |
tool_use_id | str | None | Tool use ID liên quan |
last_tool_name | str | None | Tên tool cuối cùng task đã dùng |
TaskNotificationMessage
Phần tiêu đề “TaskNotificationMessage”Phát ra khi một background task hoàn tất, lỗi, hoặc bị dừng. Background task gồm lệnh Bash chạy run_in_background, Monitor watch, và background subagent.
@dataclassclass TaskNotificationMessage(SystemMessage): task_id: str status: TaskNotificationStatus # "completed" | "failed" | "stopped" output_file: str summary: str uuid: str session_id: str tool_use_id: str | None = None usage: TaskUsage | None = None| Field | Type | Description |
|---|---|---|
task_id | str | Định danh duy nhất cho task |
status | TaskNotificationStatus | Một trong "completed", "failed", hoặc "stopped" |
output_file | str | Đường dẫn tới file output của task |
summary | str | Tóm tắt kết quả task |
uuid | str | Định danh message duy nhất |
session_id | str | Định danh session |
tool_use_id | str | None | Tool use ID liên quan |
usage | TaskUsage | None | Token usage cuối cùng của task |
Content Block Types
Phần tiêu đề “Content Block Types”ContentBlock
Phần tiêu đề “ContentBlock”Union type của mọi content block.
ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlockTextBlock
Phần tiêu đề “TextBlock”Content block dạng text.
@dataclassclass TextBlock: text: strThinkingBlock
Phần tiêu đề “ThinkingBlock”Content block dạng thinking (cho model có khả năng thinking).
@dataclassclass ThinkingBlock: thinking: str signature: strToolUseBlock
Phần tiêu đề “ToolUseBlock”Block yêu cầu dùng tool.
@dataclassclass ToolUseBlock: id: str name: str input: dict[str, Any]ToolResultBlock
Phần tiêu đề “ToolResultBlock”Block kết quả thực thi tool.
@dataclassclass ToolResultBlock: tool_use_id: str content: str | list[dict[str, Any]] | None = None is_error: bool | None = NoneError Types
Phần tiêu đề “Error Types”ClaudeSDKError
Phần tiêu đề “ClaudeSDKError”Base exception class cho mọi lỗi SDK.
class ClaudeSDKError(Exception): """Base error for Claude SDK."""Khi một query() single-shot kết thúc bằng kết quả lỗi, ví dụ lỗi giới hạn turn, SDK raise một Exception thường sau khi yield result message cuối, không phải một subclass của ClaudeSDKError.
CLINotFoundError
Phần tiêu đề “CLINotFoundError”Raise khi Claude Code CLI chưa được cài hoặc không tìm thấy.
class CLINotFoundError(CLIConnectionError): def __init__( self, message: str = "Claude Code not found", cli_path: str | None = None ): """ Args: message: Error message (default: "Claude Code not found") cli_path: Optional path to the CLI that was not found """CLIConnectionError
Phần tiêu đề “CLIConnectionError”Raise khi kết nối tới Claude Code thất bại.
class CLIConnectionError(ClaudeSDKError): """Failed to connect to Claude Code."""ProcessError
Phần tiêu đề “ProcessError”Raise khi process Claude Code lỗi.
class ProcessError(ClaudeSDKError): def __init__( self, message: str, exit_code: int | None = None, stderr: str | None = None ): self.exit_code = exit_code self.stderr = stderrCLIJSONDecodeError
Phần tiêu đề “CLIJSONDecodeError”Raise khi parse JSON thất bại.
class CLIJSONDecodeError(ClaudeSDKError): def __init__(self, line: str, original_error: Exception): """ Args: line: The line that failed to parse original_error: The original JSON decode exception """ self.line = line self.original_error = original_errorHook Types
Phần tiêu đề “Hook Types”Để có hướng dẫn đầy đủ về dùng hooks kèm ví dụ và pattern phổ biến, xem hướng dẫn Hooks.
HookEvent
Phần tiêu đề “HookEvent”Các loại hook event được hỗ trợ.
HookEvent = Literal[ "PreToolUse", # Called before tool execution "PostToolUse", # Called after tool execution "PostToolUseFailure", # Called when a tool execution fails "UserPromptSubmit", # Called when user submits a prompt "Stop", # Called when stopping execution "SubagentStop", # Called when a subagent stops "PreCompact", # Called before message compaction "Notification", # Called for notification events "SubagentStart", # Called when a subagent starts "PermissionRequest", # Called when a permission decision is needed]HookCallback
Phần tiêu đề “HookCallback”Định nghĩa type cho hàm callback hook.
HookCallback = Callable[[HookInput, str | None, HookContext], Awaitable[HookJSONOutput]]Tham số:
input: Hook input được đánh type mạnh với discriminated union dựa trênhook_event_name(xemHookInput)tool_use_id: Định danh tool use tuỳ chọn (cho hook liên quan tới tool)context: Hook context kèm thông tin bổ sung
Trả về một HookJSONOutput có thể chứa:
decision:"block"để chặn hành độngsystemMessage: thông báo cảnh báo hiển thị cho người dùnghookSpecificOutput: Dữ liệu output đặc thù cho hook
HookContext
Phần tiêu đề “HookContext”Thông tin context truyền cho callback hook.
class HookContext(TypedDict): signal: Any | None # Future: abort signal supportHookMatcher
Phần tiêu đề “HookMatcher”Cấu hình để khớp hook với event hoặc tool cụ thể.
@dataclassclass HookMatcher: matcher: str | None = ( None # Tool name or pattern to match (e.g., "Bash", "Write|Edit") ) hooks: list[HookCallback] = field( default_factory=list ) # List of callbacks to execute timeout: float | None = ( None # Timeout in seconds. When omitted, the per-event default applies: # 600 for most events, 30 for UserPromptSubmit )HookInput
Phần tiêu đề “HookInput”Union type của mọi loại hook input. Type thực tế phụ thuộc vào field hook_event_name.
HookInput = ( PreToolUseHookInput | PostToolUseHookInput | PostToolUseFailureHookInput | UserPromptSubmitHookInput | StopHookInput | SubagentStopHookInput | PreCompactHookInput | NotificationHookInput | SubagentStartHookInput | PermissionRequestHookInput)BaseHookInput
Phần tiêu đề “BaseHookInput”Các field cơ bản có mặt ở mọi loại hook input.
class BaseHookInput(TypedDict): session_id: str transcript_path: str cwd: str permission_mode: NotRequired[str]| Field | Type | Description |
|---|---|---|
session_id | str | Định danh session hiện tại |
transcript_path | str | Đường dẫn tới file transcript của session |
cwd | str | Thư mục làm việc hiện tại |
permission_mode | str (optional) | Permission mode hiện tại |
PreToolUseHookInput
Phần tiêu đề “PreToolUseHookInput”Dữ liệu input cho hook event PreToolUse.
class PreToolUseHookInput(BaseHookInput): hook_event_name: Literal["PreToolUse"] tool_name: str tool_input: dict[str, Any] tool_use_id: str agent_id: NotRequired[str] agent_type: NotRequired[str]| Field | Type | Description |
|---|---|---|
hook_event_name | Literal["PreToolUse"] | Luôn “PreToolUse” |
tool_name | str | Tên tool sắp được thực thi |
tool_input | dict[str, Any] | Tham số đầu vào cho tool |
tool_use_id | str | Định danh duy nhất cho lần dùng tool này |
agent_id | str (optional) | Định danh subagent, có mặt khi hook chạy trong một subagent |
agent_type | str (optional) | Loại subagent, có mặt khi hook chạy trong một subagent |
PostToolUseHookInput
Phần tiêu đề “PostToolUseHookInput”Dữ liệu input cho hook event PostToolUse.
class PostToolUseHookInput(BaseHookInput): hook_event_name: Literal["PostToolUse"] tool_name: str tool_input: dict[str, Any] tool_response: Any tool_use_id: str agent_id: NotRequired[str] agent_type: NotRequired[str]| Field | Type | Description |
|---|---|---|
hook_event_name | Literal["PostToolUse"] | Luôn “PostToolUse” |
tool_name | str | Tên tool đã được thực thi |
tool_input | dict[str, Any] | Tham số đầu vào đã dùng |
tool_response | Any | Phản hồi từ lần thực thi tool |
tool_use_id | str | Định danh duy nhất cho lần dùng tool này |
agent_id | str (optional) | Định danh subagent, có mặt khi hook chạy trong một subagent |
agent_type | str (optional) | Loại subagent, có mặt khi hook chạy trong một subagent |
PostToolUseFailureHookInput
Phần tiêu đề “PostToolUseFailureHookInput”Dữ liệu input cho hook event PostToolUseFailure. Được gọi khi một lần thực thi tool thất bại.
class PostToolUseFailureHookInput(BaseHookInput): hook_event_name: Literal["PostToolUseFailure"] tool_name: str tool_input: dict[str, Any] tool_use_id: str error: str is_interrupt: NotRequired[bool] agent_id: NotRequired[str] agent_type: NotRequired[str]| Field | Type | Description |
|---|---|---|
hook_event_name | Literal["PostToolUseFailure"] | Luôn “PostToolUseFailure” |
tool_name | str | Tên tool đã thất bại |
tool_input | dict[str, Any] | Tham số đầu vào đã dùng |
tool_use_id | str | Định danh duy nhất cho lần dùng tool này |
error | str | Thông báo lỗi từ lần thực thi thất bại |
is_interrupt | bool (optional) | Thất bại có phải do interrupt hay không |
agent_id | str (optional) | Định danh subagent, có mặt khi hook chạy trong một subagent |
agent_type | str (optional) | Loại subagent, có mặt khi hook chạy trong một subagent |
UserPromptSubmitHookInput
Phần tiêu đề “UserPromptSubmitHookInput”Dữ liệu input cho hook event UserPromptSubmit.
class UserPromptSubmitHookInput(BaseHookInput): hook_event_name: Literal["UserPromptSubmit"] prompt: str| Field | Type | Description |
|---|---|---|
hook_event_name | Literal["UserPromptSubmit"] | Luôn “UserPromptSubmit” |
prompt | str | Prompt người dùng đã gửi |
StopHookInput
Phần tiêu đề “StopHookInput”Dữ liệu input cho hook event Stop.
class StopHookInput(BaseHookInput): hook_event_name: Literal["Stop"] stop_hook_active: bool| Field | Type | Description |
|---|---|---|
hook_event_name | Literal["Stop"] | Luôn “Stop” |
stop_hook_active | bool | Stop hook có đang hoạt động hay không |
SubagentStopHookInput
Phần tiêu đề “SubagentStopHookInput”Dữ liệu input cho hook event SubagentStop.
class SubagentStopHookInput(BaseHookInput): hook_event_name: Literal["SubagentStop"] stop_hook_active: bool agent_id: str agent_transcript_path: str agent_type: str| Field | Type | Description |
|---|---|---|
hook_event_name | Literal["SubagentStop"] | Luôn “SubagentStop” |
stop_hook_active | bool | Stop hook có đang hoạt động hay không |
agent_id | str | Định danh duy nhất cho subagent |
agent_transcript_path | str | Đường dẫn tới file transcript của subagent |
agent_type | str | Loại subagent |
PreCompactHookInput
Phần tiêu đề “PreCompactHookInput”Dữ liệu input cho hook event PreCompact.
class PreCompactHookInput(BaseHookInput): hook_event_name: Literal["PreCompact"] trigger: Literal["manual", "auto"] custom_instructions: str | None| Field | Type | Description |
|---|---|---|
hook_event_name | Literal["PreCompact"] | Luôn “PreCompact” |
trigger | Literal["manual", "auto"] | Điều gì kích hoạt compaction |
custom_instructions | str | None | Hướng dẫn tuỳ chỉnh cho compaction |
NotificationHookInput
Phần tiêu đề “NotificationHookInput”Dữ liệu input cho hook event Notification.
class NotificationHookInput(BaseHookInput): hook_event_name: Literal["Notification"] message: str title: NotRequired[str] notification_type: str| Field | Type | Description |
|---|---|---|
hook_event_name | Literal["Notification"] | Luôn “Notification” |
message | str | Nội dung thông báo |
title | str (optional) | Tiêu đề thông báo |
notification_type | str | Loại thông báo |
SubagentStartHookInput
Phần tiêu đề “SubagentStartHookInput”Dữ liệu input cho hook event SubagentStart.
class SubagentStartHookInput(BaseHookInput): hook_event_name: Literal["SubagentStart"] agent_id: str agent_type: str| Field | Type | Description |
|---|---|---|
hook_event_name | Literal["SubagentStart"] | Luôn “SubagentStart” |
agent_id | str | Định danh duy nhất cho subagent |
agent_type | str | Loại subagent |
PermissionRequestHookInput
Phần tiêu đề “PermissionRequestHookInput”Dữ liệu input cho hook event PermissionRequest. Cho phép hook xử lý quyết định permission bằng code.
class PermissionRequestHookInput(BaseHookInput): hook_event_name: Literal["PermissionRequest"] tool_name: str tool_input: dict[str, Any] permission_suggestions: NotRequired[list[Any]] agent_id: NotRequired[str] agent_type: NotRequired[str]| Field | Type | Description |
|---|---|---|
hook_event_name | Literal["PermissionRequest"] | Luôn “PermissionRequest” |
tool_name | str | Tên tool đang yêu cầu permission |
tool_input | dict[str, Any] | Tham số đầu vào cho tool |
permission_suggestions | list[Any] (optional) | Gợi ý cập nhật permission từ CLI |
agent_id | str (optional) | Định danh subagent, có mặt khi hook chạy trong một subagent |
agent_type | str (optional) | Loại subagent, có mặt khi hook chạy trong một subagent |
HookJSONOutput
Phần tiêu đề “HookJSONOutput”Union type cho giá trị trả về của callback hook.
HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutputSyncHookJSONOutput
Phần tiêu đề “SyncHookJSONOutput”Output hook đồng bộ kèm field control và decision.
class SyncHookJSONOutput(TypedDict): # Control fields continue_: NotRequired[bool] # Whether to proceed (default: True) suppressOutput: NotRequired[bool] # Hide stdout from transcript stopReason: NotRequired[str] # Message when continue is False
# Decision fields decision: NotRequired[Literal["block"]] systemMessage: NotRequired[str] # Warning message for user reason: NotRequired[str] # Feedback for Claude
# Hook-specific output hookSpecificOutput: NotRequired[HookSpecificOutput]HookSpecificOutput
Phần tiêu đề “HookSpecificOutput”Một TypedDict chứa tên hook event và field đặc thù cho event. Hình dạng phụ thuộc vào giá trị hookEventName. Để biết đầy đủ field khả dụng theo từng hook event, xem “Control execution with hooks”.
Một discriminated union của các type output đặc thù cho từng event. Field hookEventName quyết định field nào hợp lệ.
class PreToolUseHookSpecificOutput(TypedDict): hookEventName: Literal["PreToolUse"] permissionDecision: NotRequired[Literal["allow", "deny", "ask", "defer"]] permissionDecisionReason: NotRequired[str] updatedInput: NotRequired[dict[str, Any]] additionalContext: NotRequired[str]
class PostToolUseHookSpecificOutput(TypedDict): hookEventName: Literal["PostToolUse"] additionalContext: NotRequired[str] updatedToolOutput: NotRequired[Any] updatedMCPToolOutput: NotRequired[Any] # Deprecated: use updatedToolOutput, which works for all tools
class PostToolUseFailureHookSpecificOutput(TypedDict): hookEventName: Literal["PostToolUseFailure"] additionalContext: NotRequired[str]
class UserPromptSubmitHookSpecificOutput(TypedDict): hookEventName: Literal["UserPromptSubmit"] additionalContext: NotRequired[str]
class NotificationHookSpecificOutput(TypedDict): hookEventName: Literal["Notification"] additionalContext: NotRequired[str]
class SubagentStartHookSpecificOutput(TypedDict): hookEventName: Literal["SubagentStart"] additionalContext: NotRequired[str]
class PermissionRequestHookSpecificOutput(TypedDict): hookEventName: Literal["PermissionRequest"] decision: dict[str, Any]
HookSpecificOutput = ( PreToolUseHookSpecificOutput | PostToolUseHookSpecificOutput | PostToolUseFailureHookSpecificOutput | UserPromptSubmitHookSpecificOutput | NotificationHookSpecificOutput | SubagentStartHookSpecificOutput | PermissionRequestHookSpecificOutput)AsyncHookJSONOutput
Phần tiêu đề “AsyncHookJSONOutput”Output hook bất đồng bộ, hoãn việc thực thi hook.
class AsyncHookJSONOutput(TypedDict): async_: Literal[True] # Set to True to defer execution asyncTimeout: NotRequired[int] # Timeout in millisecondsVí dụ dùng Hook
Phần tiêu đề “Ví dụ dùng Hook”Ví dụ này đăng ký hai hook: một hook chặn lệnh bash nguy hiểm như rm -rf /, và một hook khác ghi log mọi lần dùng tool để audit. Hook bảo mật chỉ chạy trên lệnh Bash (qua matcher), trong khi hook logging chạy trên mọi tool.
import asynciofrom claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher, HookContextfrom typing import Any
async def validate_bash_command( input_data: dict[str, Any], tool_use_id: str | None, context: HookContext) -> dict[str, Any]: """Validate and potentially block dangerous bash commands.""" if input_data["tool_name"] == "Bash": command = input_data["tool_input"].get("command", "") if "rm -rf /" in command: return { "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "Dangerous command blocked", } } return {}
async def log_tool_use( input_data: dict[str, Any], tool_use_id: str | None, context: HookContext) -> dict[str, Any]: """Log all tool usage for auditing.""" print(f"Tool used: {input_data.get('tool_name')}") return {}
options = ClaudeAgentOptions( hooks={ "PreToolUse": [ HookMatcher( matcher="Bash", hooks=[validate_bash_command], timeout=120 ), # 2 min for validation HookMatcher( hooks=[log_tool_use] ), # Applies to all tools (per-event default timeout) ], "PostToolUse": [HookMatcher(hooks=[log_tool_use])], })
async def main(): async for message in query(prompt="Analyze this codebase", options=options): print(message)
asyncio.run(main())Tool Input/Output Types
Phần tiêu đề “Tool Input/Output Types”Tài liệu về schema input/output cho mọi tool tích hợp sẵn của Claude Code. Dù Python SDK không export chúng dưới dạng type, chúng thể hiện cấu trúc input và output của tool trong message.
Agent
Phần tiêu đề “Agent”Tên tool: Agent. Tên cũ Task vẫn được chấp nhận như một alias, và danh sách tools trong SystemMessage init báo cáo tool này là Task để tương thích ngược.
Input:
{ "description": str, # A short (3-5 word) description of the task "prompt": str, # The task for the agent to perform "subagent_type": str | None, # The type of specialized agent to use "model": "sonnet" | "opus" | "haiku" | "fable" | None, # Model override for this agent "run_in_background": bool | None, # Agents run in the background by default; set to False to run synchronously "name": str | None, # Name for the spawned agent "team_name": str | None, # Deprecated; ignored "mode": "acceptEdits" | "auto" | "bypassPermissions" | "default" | "dontAsk" | "plan" | None, # Deprecated; ignored. Subagents inherit the parent session's permission mode; agent-definition frontmatter may override it "isolation": "worktree" | "remote" | None, # Isolation mode for the agent's changes}Khởi chạy một agent mới để xử lý tác vụ nhiều bước phức tạp một cách tự động.
Output (status: "completed"):
{ "status": "completed", "agentId": str, # ID of the agent that ran "agentType": str | None, # The subagent type that handled the task "content": [ # Result content blocks { "type": "text", "text": str, "citations": list | None, } ], "resolvedModel": str | None, # Model the subagent started on "modelsUsed": list[str] | None, # Models used in order, with consecutive repeats collapsed "totalToolUseCount": int, # Number of tool calls the agent made "totalDurationMs": int, # Execution duration in milliseconds "totalTokens": int, # Total tokens used "usage": { # Token usage statistics "input_tokens": int, "output_tokens": int, "cache_creation_input_tokens": int | None, "cache_read_input_tokens": int | None, "server_tool_use": {"web_search_requests": int, "web_fetch_requests": int} | None, "service_tier": str | None, "cache_creation": {"ephemeral_1h_input_tokens": int, "ephemeral_5m_input_tokens": int} | None, "inference_geo": str | None, "speed": str | None, "iterations": Any | None, }, "toolStats": { # Aggregate tool activity for the run "readCount": int, "searchCount": int, "bashCount": int, "editFileCount": int, "linesAdded": int, "linesRemoved": int, "otherToolCount": int, "frameCount": int | None, } | None, "prompt": str, # The prompt the agent ran "worktreePath": str | None, # Present for worktree-isolated runs "worktreeBranch": str | None, # Present for worktree-isolated runs}Output (status: "async_launched"):
{ "status": "async_launched", "isAsync": bool | None, # True on background launches "agentId": str, # ID of the launched agent "description": str, # The task description "resolvedModel": str | None, # Model in use at the backgrounding transition "modelsUsed": list[str] | None, # Models used before backgrounding, in order, with consecutive repeats collapsed "prompt": str, # The prompt the agent runs "outputFile": str, # File path where the agent's output is written "canReadOutputFile": bool | None, # Whether the output file can be read directly}Output (status: "remote_launched"):
{ "status": "remote_launched", "taskId": str, # ID of the remote task "sessionUrl": str, # Link to the remote cloud session "description": str, # The task description "prompt": str, # The prompt the agent runs "outputFile": str, # File path where the agent's output is written}Trả về kết quả từ subagent. Output được phân biệt theo field status: "completed" cho task đã hoàn tất, "async_launched" cho task chạy nền, và "remote_launched" cho task Claude Code gửi tới một remote cloud session, trong đó sessionUrl trỏ tới session đó và taskId định danh nó. Các lần chạy worktree-isolated gồm worktreePath và worktreeBranch trong biến thể completed.
Ở biến thể completed, resolvedModel cho biết tên model subagent đã bắt đầu chạy, có thể khác với model input được yêu cầu khi availableModels hoặc một override khác áp dụng. Field này cần Claude Code v2.1.174 trở lên. Ở biến thể async_launched, resolvedModel cho biết tên model đang dùng khi agent chuyển sang chạy nền, nên một lần đổi model xảy ra trước khi backgrounding sẽ được phản ánh ở đó. Field modelsUsed ở cả hai biến thể liệt kê các model đã dùng theo thứ tự, gộp các lần lặp lại liên tiếp; chỉ được đặt khi model bị đổi giữa chừng. modelsUsed và hành vi resolvedModel tại thời điểm backgrounding cần Claude Code v2.1.212 trở lên.
AskUserQuestion
Phần tiêu đề “AskUserQuestion”Tên tool: AskUserQuestion
Hỏi người dùng câu hỏi làm rõ trong lúc thực thi. Xem “Handle approvals and user input” để biết chi tiết cách dùng.
Input:
{ "questions": [ # Questions to ask the user (1-4 questions) { "question": str, # The complete question to ask the user "header": str, # Very short label displayed as a chip/tag (max 12 chars) "options": [ # The available choices (2-4 options) { "label": str, # Display text for this option (1-5 words) "description": str, # Explanation of what this option means "preview": str | None, # Preview content rendered when the option is focused } ], "multiSelect": bool, # Set to true to allow multiple selections } ], "answers": dict[str, str] | None, # User answers populated by the permission system. Multi-select # answers are a comma-joined string of the selected labels; a # list of labels is accepted on input and coerced to that form "annotations": dict[str, dict] | None, # Per-question annotations from the user, keyed by question text. # Each value can carry "preview" (the selected option's preview # content) and "notes" (free-text notes on the selection) "metadata": dict | None, # Analytics metadata, such as {"source": "remember"}; not displayed to the user}Output:
{ "questions": [ # The questions that were asked { "question": str, "header": str, "options": [{"label": str, "description": str, "preview": str | None}], "multiSelect": bool, } ], "answers": dict[str, str], # Maps question text to answer string # Multi-select answers are comma-separated "response": str | None, # Freeform reply typed instead of answering the questions; when set, # Claude receives "The user responded: ..." in place of the answer list "annotations": dict[str, dict] | None, # Per-question "preview" and "notes" from the user's selections "afkTimeoutMs": int | None, # Set when the dialog auto-resolved after this many milliseconds of user inactivity; absent when the user answered}Tên tool: Bash
Input:
{ "command": str, # The command to execute "timeout": int | None, # Optional timeout in milliseconds (max 600000; higher values are clamped to the max) "description": str | None, # Clear, concise description (5-10 words) "run_in_background": bool | None, # Set to true to run in background}Output:
{ "output": str, # Combined stdout and stderr output "exitCode": int, # Exit code of the command "killed": bool | None, # Whether command was killed due to timeout "shellId": str | None, # Shell ID for background processes}Monitor
Phần tiêu đề “Monitor”Tên tool: Monitor
Chạy một nguồn nền và gửi mỗi event tới Claude để nó phản ứng mà không cần polling: command chạy một script và phát một event cho mỗi dòng stdout, và ws mở một WebSocket và phát một event cho mỗi text frame. Cung cấp đúng một trong command hoặc ws.
Khi Monitor chạy một command, nó tuân theo cùng quy tắc permission như Bash; một WebSocket watch được hỏi chấp thuận riêng. Nguồn ws cần Claude Code v2.1.195 trở lên. Xem tham chiếu Monitor tool để biết hành vi và mức khả dụng theo provider.
Input:
{ "command": str | None, # Shell script; each stdout line is an event, exit ends the watch "ws": dict | None, # WebSocket source: {"url": str, "protocols": list[str] | None}; each text frame is an event "description": str, # Short description shown in notifications "timeout_ms": int | None, # Kill after this deadline (default 300000, max 3600000) "persistent": bool | None, # Run for the lifetime of the session; stop with TaskStop}Output:
{ "taskId": str, # ID of the background monitor task "timeoutMs": int, # Timeout deadline in milliseconds (0 when persistent) "persistent": bool | None, # True when running until TaskStop or session end}Tên tool: Edit
Input:
{ "file_path": str, # The absolute path to the file to modify "old_string": str, # The text to replace "new_string": str, # The text to replace it with "replace_all": bool | None, # Replace all occurrences (default False)}Output:
{ "message": str, # Confirmation message "replacements": int, # Number of replacements made "file_path": str, # File path that was edited}Tên tool: Read
Input:
{ "file_path": str, # The absolute path to the file to read "offset": int | None, # The line number to start reading from "limit": int | None, # The number of lines to read}Output (file text):
{ "content": str, # File contents with line numbers "total_lines": int, # Total number of lines in file "lines_returned": int, # Lines actually returned}Output (hình ảnh):
{ "image": str, # Base64 encoded image data "mime_type": str, # Image MIME type "file_size": int, # File size in bytes}Write
Phần tiêu đề “Write”Tên tool: Write
Input:
{ "file_path": str, # The absolute path to the file to write "content": str, # The content to write to the file}Output:
{ "message": str, # Success message "bytes_written": int, # Number of bytes written "file_path": str, # File path that was written}Tên tool: Glob
Input:
{ "pattern": str, # The glob pattern to match files against "path": str | None, # The directory to search in (defaults to cwd)}Output:
{ "matches": list[str], # Array of matching file paths "count": int, # Number of matches found "search_path": str, # Search directory used}Tên tool: Grep
Input:
{ "pattern": str, # The regular expression pattern "path": str | None, # File or directory to search in "glob": str | None, # Glob pattern to filter files "type": str | None, # File type to search "output_mode": str | None, # "content", "files_with_matches", or "count" "-i": bool | None, # Case insensitive search "-n": bool | None, # Show line numbers "-B": int | None, # Lines to show before each match "-A": int | None, # Lines to show after each match "-C": int | None, # Lines to show before and after "head_limit": int | None, # Limit output to first N lines/entries "multiline": bool | None, # Enable multiline mode}Output (content mode):
{ "matches": [ { "file": str, "line_number": int | None, "line": str, "before_context": list[str] | None, "after_context": list[str] | None, } ], "total_matches": int,}Output (files_with_matches mode):
{ "files": list[str], # Files containing matches "count": int, # Number of files with matches}NotebookEdit
Phần tiêu đề “NotebookEdit”Tên tool: NotebookEdit
Input:
{ "notebook_path": str, # Absolute path to the Jupyter notebook "cell_id": str | None, # The ID of the cell to edit "new_source": str, # The new source for the cell "cell_type": "code" | "markdown" | None, # The type of the cell "edit_mode": "replace" | "insert" | "delete" | None, # Edit operation type}Output:
{ "message": str, # Success message "edit_type": "replaced" | "inserted" | "deleted", # Type of edit performed "cell_id": str | None, # Cell ID that was affected "total_cells": int, # Total cells in notebook after edit}WebFetch
Phần tiêu đề “WebFetch”Tên tool: WebFetch
Input:
{ "url": str, # The URL to fetch content from "prompt": str, # The prompt to run on the fetched content}Output:
{ "bytes": int, # Size of the fetched content in bytes "code": int, # HTTP response code "codeText": str, # HTTP response code text "result": str, # Processed result from applying the prompt to the content "durationMs": int, # Time to fetch and process the content, in milliseconds "url": str, # URL that was fetched}WebSearch
Phần tiêu đề “WebSearch”Tên tool: WebSearch
Input:
{ "query": str, # The search query to use "allowed_domains": list[str] | None, # Only include results from these domains "blocked_domains": list[str] | None, # Never include results from these domains}Output:
{ "query": str, # The search query "results": list[str | {"tool_use_id": str, "content": list[{"title": str, "url": str}]}], "durationSeconds": float, # Search duration in seconds}TodoWrite
Phần tiêu đề “TodoWrite”Tên tool: TodoWrite
Input:
{ "todos": [ { "content": str, # The task description "status": "pending" | "in_progress" | "completed", # Task status "activeForm": str, # Active form of the description } ]}Output:
{ "message": str, # Success message "stats": {"total": int, "pending": int, "in_progress": int, "completed": int},}TaskCreate
Phần tiêu đề “TaskCreate”Tên tool: TaskCreate
Input:
{ "subject": str, # Short task title "description": str, # Detailed task body "activeForm": str | None, # Present-tense label shown while in progress "metadata": dict | None, # Arbitrary caller metadata}Output:
{ "task": {"id": str, "subject": str}, # Created task with assigned ID}TaskUpdate
Phần tiêu đề “TaskUpdate”Tên tool: TaskUpdate
Input:
{ "taskId": str, # ID of the task to patch "status": Literal["pending", "in_progress", "completed", "deleted"] | None, "subject": str | None, "description": str | None, "activeForm": str | None, "addBlocks": list[str] | None, # Task IDs this task now blocks "addBlockedBy": list[str] | None, # Task IDs that now block this task "owner": str | None, "metadata": dict | None,}Output:
{ "success": bool, "taskId": str, "updatedFields": list[str], # Names of fields that changed "error": str | None, "statusChange": {"from": str, "to": str} | None,}TaskGet
Phần tiêu đề “TaskGet”Tên tool: TaskGet
Input:
{ "taskId": str, # ID of the task to read}Output:
{ "task": { "id": str, "subject": str, "description": str, "status": Literal["pending", "in_progress", "completed"], "blocks": list[str], "blockedBy": list[str], } | None, # None when the ID is not found}TaskList
Phần tiêu đề “TaskList”Tên tool: TaskList
Input:
{}Output:
{ "tasks": [ { "id": str, "subject": str, "status": Literal["pending", "in_progress", "completed"], "owner": str | None, "blockedBy": list[str], } ],}TaskOutput
Phần tiêu đề “TaskOutput”Tên tool: TaskOutput. Tên cũ BashOutput vẫn được chấp nhận như một alias.
Input:
{ "task_id": str, # The task ID to get output from "block": bool, # Whether to wait for completion (default True) "timeout": int, # Max wait time in ms (default 30000)}Output:
{ "retrieval_status": "success" | "timeout" | "not_ready", # Whether the output was retrieved "task": dict | None, # Task details: task_id, task_type, status, description, output, plus type-specific fields such as exitCode}TaskStop
Phần tiêu đề “TaskStop”Tên tool: TaskStop. Tên cũ KillShell và KillBash vẫn được chấp nhận như alias.
Input:
{ "task_id": str | None, # The ID of the background task to stop "shell_id": str | None, # Deprecated: use task_id instead}Output:
{ "message": str, # Status message about the operation "task_id": str, # The ID of the task that was stopped "task_type": str, # The type of the task that was stopped "command": str | None, # The command or description of the stopped task}ExitPlanMode
Phần tiêu đề “ExitPlanMode”Tên tool: ExitPlanMode
Input:
{ "plan": str # The plan to run by the user for approval}Output:
{ "message": str, # Confirmation message "approved": bool | None, # Whether user approved the plan}ListMcpResources
Phần tiêu đề “ListMcpResources”Tên tool: ListMcpResourcesTool
Input:
{ "server": str | None # Optional server name to filter resources by}Output:
{ "resources": [ { "uri": str, "name": str, "description": str | None, "mimeType": str | None, "server": str, } ], "total": int,}ReadMcpResource
Phần tiêu đề “ReadMcpResource”Tên tool: ReadMcpResourceTool
Input:
{ "server": str, # The MCP server name "uri": str, # The resource URI to read}Output:
{ "contents": [ {"uri": str, "mimeType": str | None, "text": str | None, "blob": str | None} ], "server": str,}Tính năng nâng cao với ClaudeSDKClient
Phần tiêu đề “Tính năng nâng cao với ClaudeSDKClient”Xây dựng giao diện hội thoại liên tục
Phần tiêu đề “Xây dựng giao diện hội thoại liên tục”from claude_agent_sdk import ( ClaudeSDKClient, ClaudeAgentOptions, AssistantMessage, TextBlock,)import asyncio
class ConversationSession: """Maintains a single conversation session with Claude."""
def __init__(self, options: ClaudeAgentOptions | None = None): self.client = ClaudeSDKClient(options) self.turn_count = 0
async def start(self): await self.client.connect() print("Starting conversation session. Claude will remember context.") print( "Commands: 'exit' to quit, 'interrupt' to stop current task, 'new' for new session" )
while True: user_input = input(f"\n[Turn {self.turn_count + 1}] You: ")
if user_input.lower() == "exit": break elif user_input.lower() == "interrupt": await self.client.interrupt() print("Task interrupted!") continue elif user_input.lower() == "new": # Disconnect and reconnect for a fresh session await self.client.disconnect() await self.client.connect() self.turn_count = 0 print("Started new conversation session (previous context cleared)") continue
# Send message - the session retains all previous messages await self.client.query(user_input) self.turn_count += 1
# Process response print(f"[Turn {self.turn_count}] Claude: ", end="") async for message in self.client.receive_response(): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, TextBlock): print(block.text, end="") print() # New line after response
await self.client.disconnect() print(f"Conversation ended after {self.turn_count} turns.")
async def main(): options = ClaudeAgentOptions( allowed_tools=["Read", "Write", "Bash"], permission_mode="acceptEdits" ) session = ConversationSession(options) await session.start()
# Example conversation:# Turn 1 - You: "Create a file called hello.py"# Turn 1 - Claude: "I'll create a hello.py file for you..."# Turn 2 - You: "What's in that file?"# Turn 2 - Claude: "The hello.py file I just created contains..." (remembers!)# Turn 3 - You: "Add a main function to it"# Turn 3 - Claude: "I'll add a main function to hello.py..." (knows which file!)
asyncio.run(main())Dùng Hooks để chỉnh sửa hành vi
Phần tiêu đề “Dùng Hooks để chỉnh sửa hành vi”from claude_agent_sdk import ( ClaudeSDKClient, ClaudeAgentOptions, HookMatcher, HookContext,)import asynciofrom typing import Any
async def pre_tool_logger( input_data: dict[str, Any], tool_use_id: str | None, context: HookContext) -> dict[str, Any]: """Log all tool usage before execution.""" tool_name = input_data.get("tool_name", "unknown") print(f"[PRE-TOOL] About to use: {tool_name}")
# You can modify or block the tool execution here if tool_name == "Bash" and "rm -rf" in str(input_data.get("tool_input", {})): return { "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionDecisionReason": "Dangerous command blocked", } } return {}
async def post_tool_logger( input_data: dict[str, Any], tool_use_id: str | None, context: HookContext) -> dict[str, Any]: """Log results after tool execution.""" tool_name = input_data.get("tool_name", "unknown") print(f"[POST-TOOL] Completed: {tool_name}") return {}
async def user_prompt_modifier( input_data: dict[str, Any], tool_use_id: str | None, context: HookContext) -> dict[str, Any]: """Add context to user prompts.""" original_prompt = input_data.get("prompt", "")
# Add a timestamp as additional context for Claude to see from datetime import datetime
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return { "hookSpecificOutput": { "hookEventName": "UserPromptSubmit", "additionalContext": f"[Submitted at {timestamp}] Original prompt: {original_prompt}", } }
async def main(): options = ClaudeAgentOptions( hooks={ "PreToolUse": [ HookMatcher(hooks=[pre_tool_logger]), HookMatcher(matcher="Bash", hooks=[pre_tool_logger]), ], "PostToolUse": [HookMatcher(hooks=[post_tool_logger])], "UserPromptSubmit": [HookMatcher(hooks=[user_prompt_modifier])], }, allowed_tools=["Read", "Write", "Bash"], )
async with ClaudeSDKClient(options=options) as client: await client.query("List files in current directory")
async for message in client.receive_response(): # Hooks will automatically log tool usage pass
asyncio.run(main())Theo dõi tiến độ thời gian thực
Phần tiêu đề “Theo dõi tiến độ thời gian thực”from claude_agent_sdk import ( ClaudeSDKClient, ClaudeAgentOptions, AssistantMessage, ToolUseBlock, ToolResultBlock, TextBlock,)import asyncio
async def monitor_progress(): options = ClaudeAgentOptions( allowed_tools=["Write", "Bash"], permission_mode="acceptEdits" )
async with ClaudeSDKClient(options=options) as client: await client.query("Create 5 Python files with different sorting algorithms")
# Monitor progress in real-time async for message in client.receive_response(): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, ToolUseBlock): if block.name == "Write": file_path = block.input.get("file_path", "") print(f"Creating: {file_path}") elif isinstance(block, ToolResultBlock): print("Completed tool execution") elif isinstance(block, TextBlock): print(f"Claude says: {block.text[:100]}...")
print("Task completed!")
asyncio.run(monitor_progress())Ví dụ dùng
Phần tiêu đề “Ví dụ dùng”Thao tác file cơ bản (dùng query)
Phần tiêu đề “Thao tác file cơ bản (dùng query)”from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ToolUseBlockimport asyncio
async def create_project(): options = ClaudeAgentOptions( allowed_tools=["Read", "Write", "Bash"], permission_mode="acceptEdits", )
async for message in query( prompt="Create a Python project structure with setup.py", options=options ): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, ToolUseBlock): print(f"Using tool: {block.name}")
asyncio.run(create_project())Xử lý lỗi
Phần tiêu đề “Xử lý lỗi”import asyncio
from claude_agent_sdk import query, CLINotFoundError, ProcessError, CLIJSONDecodeError
async def main(): try: async for message in query(prompt="Hello"): print(message) except CLINotFoundError: print( "Claude Code CLI not found. Try reinstalling: pip install --force-reinstall claude-agent-sdk" ) except ProcessError as e: print(f"Process failed with exit code: {e.exit_code}") except CLIJSONDecodeError as e: print(f"Failed to parse response: {e}") # A single-shot query() raises a plain Exception after yielding an error result except Exception as e: print(f"Query ended with an error result: {e}")
asyncio.run(main())Streaming mode với client
Phần tiêu đề “Streaming mode với client”from claude_agent_sdk import ClaudeSDKClientimport asyncio
async def interactive_session(): async with ClaudeSDKClient() as client: # Send initial message await client.query("What's the weather like?")
# Process responses async for msg in client.receive_response(): print(msg)
# Send follow-up await client.query("Tell me more about that")
# Process follow-up response async for msg in client.receive_response(): print(msg)
asyncio.run(interactive_session())Dùng custom tools với ClaudeSDKClient
Phần tiêu đề “Dùng custom tools với ClaudeSDKClient”from claude_agent_sdk import ( ClaudeSDKClient, ClaudeAgentOptions, tool, create_sdk_mcp_server, AssistantMessage, TextBlock,)import asynciofrom typing import Any
# Define custom tools with @tool decorator@tool("calculate", "Perform mathematical calculations", {"expression": str})async def calculate(args: dict[str, Any]) -> dict[str, Any]: try: result = eval(args["expression"], {"__builtins__": {}}) return {"content": [{"type": "text", "text": f"Result: {result}"}]} except Exception as e: return { "content": [{"type": "text", "text": f"Error: {str(e)}"}], "is_error": True, }
@tool("get_time", "Get current time", {})async def get_time(args: dict[str, Any]) -> dict[str, Any]: from datetime import datetime
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") return {"content": [{"type": "text", "text": f"Current time: {current_time}"}]}
async def main(): # Create SDK MCP server with custom tools my_server = create_sdk_mcp_server( name="utilities", version="1.0.0", tools=[calculate, get_time] )
# Configure options with the server options = ClaudeAgentOptions( mcp_servers={"utils": my_server}, allowed_tools=["mcp__utils__calculate", "mcp__utils__get_time"], )
# Use ClaudeSDKClient for interactive tool usage async with ClaudeSDKClient(options=options) as client: await client.query("What's 123 * 456?")
# Process calculation response async for message in client.receive_response(): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, TextBlock): print(f"Calculation: {block.text}")
# Follow up with time query await client.query("What time is it now?")
async for message in client.receive_response(): if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, TextBlock): print(f"Time: {block.text}")
asyncio.run(main())Cấu hình Sandbox
Phần tiêu đề “Cấu hình Sandbox”SandboxSettings
Phần tiêu đề “SandboxSettings”Cấu hình cho hành vi sandbox. Dùng cái này để bật sandbox cho command và cấu hình giới hạn network bằng code.
class SandboxSettings(TypedDict, total=False): enabled: bool autoAllowBashIfSandboxed: bool excludedCommands: list[str] allowUnsandboxedCommands: bool network: SandboxNetworkConfig ignoreViolations: SandboxIgnoreViolations enableWeakerNestedSandbox: bool| Property | Type | Default | Description |
|---|---|---|---|
enabled | bool | False | Bật sandbox mode cho việc thực thi command |
autoAllowBashIfSandboxed | bool | True | Tự động chấp thuận lệnh bash khi sandbox được bật |
excludedCommands | list[str] | [] | Command luôn bỏ qua giới hạn sandbox (ví dụ, ["docker"]). Các command này chạy không sandbox tự động, mà không cần model can thiệp |
allowUnsandboxedCommands | bool | True | Cho phép model yêu cầu chạy command ngoài sandbox. Khi True, model có thể đặt dangerouslyDisableSandbox trong tool input, việc này rơi xuống hệ thống permissions |
network | SandboxNetworkConfig | None | Cấu hình sandbox riêng cho network |
ignoreViolations | SandboxIgnoreViolations | None | Cấu hình vi phạm sandbox nào cần bỏ qua |
enableWeakerNestedSandbox | bool | False | Bật một sandbox nested yếu hơn để tương thích |
Ví dụ dùng
Phần tiêu đề “Ví dụ dùng”import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions
sandbox_settings = { "enabled": True, "autoAllowBashIfSandboxed": True, "failIfUnavailable": True, "network": {"allowLocalBinding": True},}
async def main(): try: async for message in query( prompt="Build and test my project", options=ClaudeAgentOptions(sandbox=sandbox_settings), ): print(message) except Exception as error: # A single-shot query() raises after yielding an error result, # such as when failIfUnavailable is set and the sandbox can't start. print(f"Session ended with an error: {error}")
asyncio.run(main())SandboxNetworkConfig
Phần tiêu đề “SandboxNetworkConfig”Cấu hình riêng cho network của sandbox mode. Các setting này áp dụng cho lệnh Bash chạy sandbox khi enabled là True trong SandboxSettings cha. Chúng không giới hạn WebFetch tool, tool này dùng permission rules thay thế.
class SandboxNetworkConfig(TypedDict, total=False): allowedDomains: list[str] deniedDomains: list[str] allowManagedDomainsOnly: bool allowUnixSockets: list[str] allowAllUnixSockets: bool allowLocalBinding: bool allowMachLookup: list[str] httpProxyPort: int socksProxyPort: int| Property | Type | Default | Description |
|---|---|---|---|
allowedDomains | list[str] | [] | Tên domain mà process sandbox được truy cập |
deniedDomains | list[str] | [] | Tên domain mà process sandbox không được truy cập. Ưu tiên hơn allowedDomains |
allowManagedDomainsOnly | bool | False | Chỉ dành cho managed-settings: khi đặt trong managed settings, bỏ qua allowedDomains từ nguồn settings không phải managed. Không có tác dụng khi đặt qua SDK options |
allowUnixSockets | list[str] | [] | Đường dẫn Unix socket mà process được truy cập (ví dụ, Docker socket) |
allowAllUnixSockets | bool | False | Cho phép truy cập mọi Unix socket |
allowLocalBinding | bool | False | Cho phép process bind vào port cục bộ (ví dụ, cho dev server) |
allowMachLookup | list[str] | [] | Chỉ macOS: tên XPC/Mach service được phép. Hỗ trợ wildcard ở cuối |
httpProxyPort | int | None | Port HTTP proxy cho request network |
socksProxyPort | int | None | Port SOCKS proxy cho request network |
SandboxIgnoreViolations
Phần tiêu đề “SandboxIgnoreViolations”Cấu hình để bỏ qua các vi phạm sandbox cụ thể.
class SandboxIgnoreViolations(TypedDict, total=False): file: list[str] network: list[str]| Property | Type | Default | Description |
|---|---|---|---|
file | list[str] | [] | Pattern đường dẫn file cần bỏ qua vi phạm |
network | list[str] | [] | Pattern network cần bỏ qua vi phạm |
Fallback về Permissions cho command không sandbox
Phần tiêu đề “Fallback về Permissions cho command không sandbox”Khi allowUnsandboxedCommands được bật, model có thể yêu cầu chạy command ngoài sandbox bằng cách đặt dangerouslyDisableSandbox: True trong tool input. Các yêu cầu này rơi xuống hệ thống permissions hiện có, nghĩa là handler can_use_tool của bạn sẽ được gọi, cho phép bạn triển khai logic authorization tuỳ chỉnh.
import asynciofrom claude_agent_sdk import ( query, ClaudeAgentOptions, HookMatcher, PermissionResultAllow, PermissionResultDeny, ToolPermissionContext,)
def is_command_authorized(command: str | None) -> bool: # Replace with your own authorization logic return False
async def can_use_tool( tool: str, input: dict, context: ToolPermissionContext) -> PermissionResultAllow | PermissionResultDeny: # Check if the model is requesting to bypass the sandbox if tool == "Bash" and input.get("dangerouslyDisableSandbox"): # The model is requesting to run this command outside the sandbox print(f"Unsandboxed command requested: {input.get('command')}")
if is_command_authorized(input.get("command")): return PermissionResultAllow() return PermissionResultDeny( message="Command not authorized for unsandboxed execution" ) return PermissionResultAllow()
# Required: dummy hook keeps the stream open for can_use_toolasync def dummy_hook(input_data, tool_use_id, context): return {"continue_": True}
async def prompt_stream(): yield { "type": "user", "message": {"role": "user", "content": "Deploy my application"}, }
async def main(): async for message in query( prompt=prompt_stream(), options=ClaudeAgentOptions( sandbox={ "enabled": True, "allowUnsandboxedCommands": True, # Model can request unsandboxed execution }, permission_mode="default", can_use_tool=can_use_tool, hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]}, ), ): print(message)
asyncio.run(main())Pattern này cho phép bạn:
- Audit yêu cầu của model: Ghi log khi model yêu cầu thực thi không sandbox
- Triển khai allowlist: Chỉ cho phép một số command cụ thể chạy không sandbox
- Thêm luồng phê duyệt: Yêu cầu authorization tường minh cho các thao tác đặc quyền
Xem thêm
Phần tiêu đề “Xem thêm”- SDK overview - Khái niệm SDK tổng quát
- TypeScript SDK reference - Tài liệu TypeScript SDK
- CLI reference - Giao diện dòng lệnh
- Common workflows - Hướng dẫn từng bước
lượt xem