Перейти к основному содержанию

Установка

pip install claude-agent-sdk

Выбор между query() и ClaudeSDKClient

Python SDK предоставляет два способа взаимодействия с Claude Code:

Быстрое сравнение

Функцияquery()ClaudeSDKClient
СеансСоздает новый сеанс по умолчаниюПовторно использует один и тот же сеанс
РазговорОдин обменНесколько обменов в одном контексте
СоединениеУправляется автоматическиРучное управление
Потоковый ввод✅ Поддерживается✅ Поддерживается
Прерывания❌ Не поддерживается✅ Поддерживается
Hooks✅ Поддерживается✅ Поддерживается
Пользовательские инструменты✅ Поддерживается✅ Поддерживается
Продолжить чатРучное через continue_conversation или resume✅ Автоматическое
Вариант использованияОдноразовые задачиНепрерывные разговоры

Когда использовать query() (одноразовые задачи)

Лучше всего для:
  • Одноразовых вопросов, когда вам не нужна история разговора
  • Независимых задач, которые не требуют контекста из предыдущих обменов
  • Простых скриптов автоматизации
  • Когда вы хотите начать с чистого листа каждый раз

Когда использовать ClaudeSDKClient (непрерывный разговор)

Лучше всего для:
  • Продолжения разговоров - Когда вам нужно, чтобы Claude помнил контекст
  • Уточняющих вопросов - Построение на основе предыдущих ответов
  • Интерактивных приложений - Интерфейсы чата, REPL
  • Логики, управляемой ответом - Когда следующее действие зависит от ответа Claude
  • Управления сеансом - Явное управление жизненным циклом разговора

Функции

query()

Создает новый сеанс для каждого взаимодействия с Claude Code по умолчанию. Возвращает асинхронный итератор, который выдает сообщения по мере их поступления. Каждый вызов query() начинается с нуля без памяти о предыдущих взаимодействиях, если вы не передадите continue_conversation=True или resume в ClaudeAgentOptions. См. Sessions.
async def query(
    *,
    prompt: str | AsyncIterable[dict[str, Any]],
    options: ClaudeAgentOptions | None = None,
    transport: Transport | None = None
) -> AsyncIterator[Message]

Параметры

ПараметрТипОписание
promptstr | AsyncIterable[dict]Входная подсказка в виде строки или асинхронного итератора для режима потоковой передачи
optionsClaudeAgentOptions | NoneОбъект дополнительной конфигурации (по умолчанию ClaudeAgentOptions(), если None)
transportTransport | NoneДополнительный пользовательский транспорт для связи с процессом CLI

Возвращаемое значение

Возвращает AsyncIterator[Message], который выдает сообщения из разговора.

Пример - С параметрами

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions


async def main():
    options = ClaudeAgentOptions(
        system_prompt="You are an expert Python developer",
        permission_mode="acceptEdits",
        cwd="/home/user/project",
    )

    async for message in query(prompt="Create a Python web server", options=options):
        print(message)


asyncio.run(main())

tool()

Декоратор для определения MCP tools с проверкой типов.
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]]

Параметры

ПараметрТипОписание
namestrУникальный идентификатор инструмента
descriptionstrПонятное описание того, что делает инструмент
input_schematype | dict[str, Any]Схема, определяющая входные параметры инструмента (см. ниже)
annotationsToolAnnotations | NoneДополнительные аннотации MCP tool, предоставляющие подсказки поведения клиентам

Варианты схемы ввода

  1. Простое сопоставление типов (рекомендуется):
    {"text": str, "count": int, "enabled": bool}
    
  2. Формат JSON Schema (для сложной валидации):
    {
        "type": "object",
        "properties": {
            "text": {"type": "string"},
            "count": {"type": "integer", "minimum": 0},
        },
        "required": ["text"],
    }
    

Возвращаемое значение

Функция-декоратор, которая оборачивает реализацию инструмента и возвращает экземпляр SdkMcpTool.

Пример

from claude_agent_sdk import tool
from typing import Any


@tool("greet", "Greet a user", {"name": str})
async def greet(args: dict[str, Any]) -> dict[str, Any]:
    return {"content": [{"type": "text", "text": f"Hello, {args['name']}!"}]}

ToolAnnotations

Переэкспортировано из mcp.types (также доступно как from claude_agent_sdk import ToolAnnotations). Все поля являются дополнительными подсказками; клиенты не должны полагаться на них для решений безопасности.
ПолеТипПо умолчаниюОписание
titlestr | NoneNoneПонятное название инструмента
readOnlyHintbool | NoneFalseЕсли True, инструмент не изменяет свою среду
destructiveHintbool | NoneTrueЕсли True, инструмент может выполнять деструктивные обновления (имеет смысл только когда readOnlyHint равен False)
idempotentHintbool | NoneFalseЕсли True, повторные вызовы с одинаковыми аргументами не имеют дополнительного эффекта (имеет смысл только когда readOnlyHint равен False)
openWorldHintbool | NoneTrueЕсли True, инструмент взаимодействует с внешними сущностями (например, веб-поиск). Если False, область инструмента закрыта (например, инструмент памяти)
from claude_agent_sdk import tool, ToolAnnotations
from typing import Any


@tool(
    "search",
    "Search the web",
    {"query": str},
    annotations=ToolAnnotations(readOnlyHint=True, openWorldHint=True),
)
async def search(args: dict[str, Any]) -> dict[str, Any]:
    return {"content": [{"type": "text", "text": f"Results for: {args['query']}"}]}

create_sdk_mcp_server()

Создайте встроенный MCP server, который работает в вашем приложении Python.
def create_sdk_mcp_server(
    name: str,
    version: str = "1.0.0",
    tools: list[SdkMcpTool[Any]] | None = None
) -> McpSdkServerConfig

Параметры

ПараметрТипПо умолчаниюОписание
namestr-Уникальный идентификатор сервера
versionstr"1.0.0"Строка версии сервера
toolslist[SdkMcpTool[Any]] | NoneNoneСписок функций инструментов, созданных с помощью декоратора @tool

Возвращаемое значение

Возвращает объект McpSdkServerConfig, который можно передать в ClaudeAgentOptions.mcp_servers.

Пример

from claude_agent_sdk import tool, create_sdk_mcp_server


@tool("add", "Add two numbers", {"a": float, "b": float})
async def add(args):
    return {"content": [{"type": "text", "text": f"Sum: {args['a'] + args['b']}"}]}


@tool("multiply", "Multiply two numbers", {"a": float, "b": float})
async def multiply(args):
    return {"content": [{"type": "text", "text": f"Product: {args['a'] * args['b']}"}]}


calculator = create_sdk_mcp_server(
    name="calculator",
    version="2.0.0",
    tools=[add, multiply],  # Pass decorated functions
)

# Use with Claude
options = ClaudeAgentOptions(
    mcp_servers={"calc": calculator},
    allowed_tools=["mcp__calc__add", "mcp__calc__multiply"],
)

list_sessions()

Выводит список прошлых сеансов с метаданными. Фильтруйте по каталогу проекта или выводите сеансы во всех проектах. Синхронно; возвращается немедленно.
def list_sessions(
    directory: str | None = None,
    limit: int | None = None,
    include_worktrees: bool = True
) -> list[SDKSessionInfo]

Параметры

ПараметрТипПо умолчаниюОписание
directorystr | NoneNoneКаталог для вывода сеансов. Если опущено, возвращает сеансы во всех проектах
limitint | NoneNoneМаксимальное количество возвращаемых сеансов
include_worktreesboolTrueКогда directory находится внутри репозитория git, включайте сеансы из всех путей worktrees

Тип возвращаемого значения: SDKSessionInfo

СвойствоТипОписание
session_idstrУникальный идентификатор сеанса
summarystrОтображаемое название: пользовательское название, автоматически созданное резюме или первая подсказка
last_modifiedintВремя последнего изменения в миллисекундах с начала эпохи
file_sizeint | NoneРазмер файла сеанса в байтах (None для удаленных хранилищ)
custom_titlestr | NoneНазвание сеанса, установленное пользователем
first_promptstr | NoneПервая значимая подсказка пользователя в сеансе
git_branchstr | NoneВетка Git в конце сеанса
cwdstr | NoneРабочий каталог для сеанса
tagstr | NoneТег сеанса, установленный пользователем (см. tag_session())
created_atint | NoneВремя создания сеанса в миллисекундах с начала эпохи

Пример

Выведите 10 самых последних сеансов для проекта. Результаты отсортированы по last_modified в убывающем порядке, поэтому первый элемент - самый новый. Опустите directory, чтобы искать во всех проектах.
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()

Извлекает сообщения из прошлого сеанса. Синхронно; возвращается немедленно.
def get_session_messages(
    session_id: str,
    directory: str | None = None,
    limit: int | None = None,
    offset: int = 0
) -> list[SessionMessage]

Параметры

ПараметрТипПо умолчаниюОписание
session_idstrобязательноID сеанса для извлечения сообщений
directorystr | NoneNoneКаталог проекта для поиска. Если опущено, ищет во всех проектах
limitint | NoneNoneМаксимальное количество возвращаемых сообщений
offsetint0Количество сообщений для пропуска с начала

Тип возвращаемого значения: SessionMessage

СвойствоТипОписание
typeLiteral["user", "assistant"]Роль сообщения
uuidstrУникальный идентификатор сообщения
session_idstrИдентификатор сеанса
messageAnyНеобработанное содержимое сообщения
parent_tool_use_idNoneЗарезервировано для будущего использования

Пример

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()

Читает метаданные для одного сеанса по ID без сканирования полного каталога проекта. Синхронно; возвращается немедленно.
def get_session_info(
    session_id: str,
    directory: str | None = None,
) -> SDKSessionInfo | None

Параметры

ПараметрТипПо умолчаниюОписание
session_idstrобязательноUUID сеанса для поиска
directorystr | NoneNoneПуть каталога проекта. Если опущено, ищет во всех каталогах проектов
Возвращает SDKSessionInfo или None, если сеанс не найден.

Пример

Найдите метаданные одного сеанса без сканирования каталога проекта. Полезно, когда у вас уже есть ID сеанса из предыдущего запуска.
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()

Переименовывает сеанс, добавляя запись с пользовательским названием. Повторные вызовы безопасны; побеждает самое последнее название. Синхронно.
def rename_session(
    session_id: str,
    title: str,
    directory: str | None = None,
) -> None

Параметры

ПараметрТипПо умолчаниюОписание
session_idstrобязательноUUID сеанса для переименования
titlestrобязательноНовое название. Должно быть непустым после удаления пробелов
directorystr | NoneNoneПуть каталога проекта. Если опущено, ищет во всех каталогах проектов
Вызывает ValueError, если session_id не является допустимым UUID или title пуст; FileNotFoundError, если сеанс не найден.

Пример

Переименуйте самый последний сеанс, чтобы его было легче найти позже. Новое название появляется в SDKSessionInfo.custom_title при последующих чтениях.
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()

Помечает сеанс. Передайте None для очистки тега. Повторные вызовы безопасны; побеждает самый последний тег. Синхронно.
def tag_session(
    session_id: str,
    tag: str | None,
    directory: str | None = None,
) -> None

Параметры

ПараметрТипПо умолчаниюОписание
session_idstrобязательноUUID сеанса для пометки
tagstr | NoneобязательноСтрока тега или None для очистки. Очищается от Unicode перед сохранением
directorystr | NoneNoneПуть каталога проекта. Если опущено, ищет во всех каталогах проектов
Вызывает ValueError, если session_id не является допустимым UUID или tag пуст после очистки; FileNotFoundError, если сеанс не найден.

Пример

Пометьте сеанс, затем отфильтруйте по этому тегу при последующем чтении. Передайте None для очистки существующего тега.
from claude_agent_sdk import list_sessions, tag_session

# Tag a session
tag_session("550e8400-e29b-41d4-a716-446655440000", "needs-review")

# Later: find all sessions with that tag
for session in list_sessions(directory="/path/to/project"):
    if session.tag == "needs-review":
        print(session.summary)

Классы

ClaudeSDKClient

Поддерживает сеанс разговора через несколько обменов. Это эквивалент Python того, как функция query() TypeScript SDK работает внутри - она создает объект клиента, который может продолжать разговоры.

Ключевые особенности

  • Непрерывность сеанса: Поддерживает контекст разговора через несколько вызовов query()
  • Один разговор: Сеанс сохраняет предыдущие сообщения
  • Поддержка прерываний: Может остановить выполнение в середине задачи
  • Явный жизненный цикл: Вы контролируете, когда сеанс начинается и заканчивается
  • Поток, управляемый ответом: Может реагировать на ответы и отправлять дополнения
  • Пользовательские инструменты и hooks: Поддерживает пользовательские инструменты (созданные с помощью декоратора @tool) и hooks
class ClaudeSDKClient:
    def __init__(self, options: ClaudeAgentOptions | None = None, transport: Transport | None = None)
    async def connect(self, prompt: str | AsyncIterable[dict] | None = None) -> None
    async def query(self, prompt: str | AsyncIterable[dict], session_id: str = "default") -> None
    async def receive_messages(self) -> AsyncIterator[Message]
    async def receive_response(self) -> AsyncIterator[Message]
    async def interrupt(self) -> None
    async def set_permission_mode(self, mode: str) -> None
    async def set_model(self, model: str | None = None) -> None
    async def rewind_files(self, user_message_id: str) -> None
    async def get_mcp_status(self) -> McpStatusResponse
    async def reconnect_mcp_server(self, server_name: str) -> None
    async def toggle_mcp_server(self, server_name: str, enabled: bool) -> None
    async def stop_task(self, task_id: str) -> None
    async def get_server_info(self) -> dict[str, Any] | None
    async def disconnect(self) -> None

Методы

МетодОписание
__init__(options)Инициализируйте клиент с дополнительной конфигурацией
connect(prompt)Подключитесь к Claude с дополнительной начальной подсказкой или потоком сообщений
query(prompt, session_id)Отправьте новый запрос в режиме потоковой передачи
receive_messages()Получайте все сообщения от Claude как асинхронный итератор
receive_response()Получайте сообщения до и включая ResultMessage
interrupt()Отправьте сигнал прерывания (работает только в режиме потоковой передачи)
set_permission_mode(mode)Измените режим разрешений для текущего сеанса
set_model(model)Измените модель для текущего сеанса. Передайте None для сброса на значение по умолчанию
rewind_files(user_message_id)Восстановите файлы в их состояние в указанном пользовательском сообщении. Требует enable_file_checkpointing=True. См. File checkpointing
get_mcp_status()Получите статус всех настроенных MCP servers. Возвращает McpStatusResponse
reconnect_mcp_server(server_name)Повторите попытку подключения к MCP server, который не удался или был отключен
toggle_mcp_server(server_name, enabled)Включите или отключите MCP server в середине сеанса. Отключение удаляет его инструменты
stop_task(task_id)Остановите выполняющуюся фоновую задачу. TaskNotificationMessage со статусом "stopped" следует в потоке сообщений
get_server_info()Получите информацию о сервере, включая ID сеанса и возможности
disconnect()Отключитесь от Claude

Поддержка менеджера контекста

Клиент можно использовать как асинхронный менеджер контекста для автоматического управления соединением:
async with ClaudeSDKClient() as client:
    await client.query("Hello Claude")
    async for message in client.receive_response():
        print(message)
Важно: При итерации по сообщениям избегайте использования break для раннего выхода, так как это может вызвать проблемы с очисткой asyncio. Вместо этого позвольте итерации завершиться естественным образом или используйте флаги для отслеживания, когда вы нашли то, что вам нужно.

Пример - Продолжение разговора

import asyncio
from claude_agent_sdk import ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage


async def main():
    async with ClaudeSDKClient() as client:
        # First question
        await client.query("What's the capital of France?")

        # Process response
        async for message in client.receive_response():
            if isinstance(message, AssistantMessage):
                for block in message.content:
                    if isinstance(block, TextBlock):
                        print(f"Claude: {block.text}")

        # Follow-up question - the session retains the previous context
        await client.query("What's the population of that city?")

        async for message in client.receive_response():
            if isinstance(message, AssistantMessage):
                for block in message.content:
                    if isinstance(block, TextBlock):
                        print(f"Claude: {block.text}")

        # Another follow-up - still in the same conversation
        await client.query("What are some famous landmarks there?")

        async for message in client.receive_response():
            if isinstance(message, AssistantMessage):
                for block in message.content:
                    if isinstance(block, TextBlock):
                        print(f"Claude: {block.text}")


asyncio.run(main())

Пример - Потоковый ввод с ClaudeSDKClient

import asyncio
from claude_agent_sdk import ClaudeSDKClient


async def message_stream():
    """Generate messages dynamically."""
    yield {
        "type": "user",
        "message": {"role": "user", "content": "Analyze the following data:"},
    }
    await asyncio.sleep(0.5)
    yield {
        "type": "user",
        "message": {"role": "user", "content": "Temperature: 25°C, Humidity: 60%"},
    }
    await asyncio.sleep(0.5)
    yield {
        "type": "user",
        "message": {"role": "user", "content": "What patterns do you see?"},
    }


async def main():
    async with ClaudeSDKClient() as client:
        # Stream input to Claude
        await client.query(message_stream())

        # Process response
        async for message in client.receive_response():
            print(message)

        # Follow-up in same session
        await client.query("Should we be concerned about these readings?")

        async for message in client.receive_response():
            print(message)


asyncio.run(main())

Пример - Использование прерываний

import asyncio
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, ResultMessage


async def interruptible_task():
    options = ClaudeAgentOptions(allowed_tools=["Bash"], permission_mode="acceptEdits")

    async with ClaudeSDKClient(options=options) as client:
        # Start a long-running task
        await client.query("Count from 1 to 100 slowly, using the bash sleep command")

        # Let it run for a bit
        await asyncio.sleep(2)

        # Interrupt the task
        await client.interrupt()
        print("Task interrupted!")

        # Drain the interrupted task's messages (including its ResultMessage)
        async for message in client.receive_response():
            if isinstance(message, ResultMessage):
                print(f"Interrupted task finished with subtype={message.subtype!r}")
                # subtype is "error_during_execution" for interrupted tasks

        # Send a new command
        await client.query("Just say hello instead")

        # Now receive the new response
        async for message in client.receive_response():
            if isinstance(message, ResultMessage) and message.subtype == "success":
                print(f"New result: {message.result}")


asyncio.run(interruptible_task())
Поведение буфера после прерывания: interrupt() отправляет сигнал остановки, но не очищает буфер сообщений. Сообщения, уже созданные прерванной задачей, включая ее ResultMessagesubtype="error_during_execution"), остаются в потоке. Вы должны слить их с помощью receive_response() перед чтением ответа на новый запрос. Если вы отправите новый запрос сразу после interrupt() и вызовете receive_response() только один раз, вы получите сообщения прерванной задачи, а не ответ на новый запрос.

Пример - Расширенное управление разрешениями

from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
from claude_agent_sdk.types import (
    PermissionResultAllow,
    PermissionResultDeny,
    ToolPermissionContext,
)


async def custom_permission_handler(
    tool_name: str, input_data: dict, context: ToolPermissionContext
) -> PermissionResultAllow | PermissionResultDeny:
    """Custom logic for tool permissions."""

    # Block writes to system directories
    if tool_name == "Write" and input_data.get("file_path", "").startswith("/system/"):
        return PermissionResultDeny(
            message="System directory write not allowed", interrupt=True
        )

    # Redirect sensitive file operations
    if tool_name in ["Write", "Edit"] and "config" in input_data.get("file_path", ""):
        safe_path = f"./sandbox/{input_data['file_path']}"
        return PermissionResultAllow(
            updated_input={**input_data, "file_path": safe_path}
        )

    # Allow everything else
    return PermissionResultAllow(updated_input=input_data)


async def main():
    options = ClaudeAgentOptions(
        can_use_tool=custom_permission_handler, allowed_tools=["Read", "Write", "Edit"]
    )

    async with ClaudeSDKClient(options=options) as client:
        await client.query("Update the system config file")

        async for message in client.receive_response():
            # Will use sandbox path instead
            print(message)


asyncio.run(main())

Типы

@dataclass vs TypedDict: Этот SDK использует два вида типов. Классы, украшенные @dataclass (такие как ResultMessage, AgentDefinition, TextBlock), являются экземплярами объектов во время выполнения и поддерживают доступ к атрибутам: msg.result. Классы, определенные с помощью TypedDict (такие как ThinkingConfigEnabled, McpStdioServerConfig, SyncHookJSONOutput), являются простыми словарями во время выполнения и требуют доступа к ключам: config["budget_tokens"], а не config.budget_tokens. Синтаксис вызова ClassName(field=value) работает для обоих, но только dataclasses создают объекты с атрибутами.

SdkMcpTool

Определение для SDK MCP tool, созданного с помощью декоратора @tool.
@dataclass
class SdkMcpTool(Generic[T]):
    name: str
    description: str
    input_schema: type[T] | dict[str, Any]
    handler: Callable[[T], Awaitable[dict[str, Any]]]
    annotations: ToolAnnotations | None = None
СвойствоТипОписание
namestrУникальный идентификатор инструмента
descriptionstrПонятное описание
input_schematype[T] | dict[str, Any]Схема для валидации ввода
handlerCallable[[T], Awaitable[dict[str, Any]]]Асинхронная функция, которая обрабатывает выполнение инструмента
annotationsToolAnnotations | NoneДополнительные аннотации MCP tool (например, readOnlyHint, destructiveHint, openWorldHint). Из mcp.types

Transport

Абстрактный базовый класс для пользовательских реализаций транспорта. Используйте это для связи с процессом Claude через пользовательский канал (например, удаленное соединение вместо локального подпроцесса).
Это низкоуровневый внутренний API. Интерфейс может измениться в будущих выпусках. Пользовательские реализации должны быть обновлены в соответствии с любыми изменениями интерфейса.
from abc import ABC, abstractmethod
from collections.abc import AsyncIterator
from typing import Any


class Transport(ABC):
    @abstractmethod
    async def connect(self) -> None: ...

    @abstractmethod
    async def write(self, data: str) -> None: ...

    @abstractmethod
    def read_messages(self) -> AsyncIterator[dict[str, Any]]: ...

    @abstractmethod
    async def close(self) -> None: ...

    @abstractmethod
    def is_ready(self) -> bool: ...

    @abstractmethod
    async def end_input(self) -> None: ...
МетодОписание
connect()Подключите транспорт и подготовьте к связи
write(data)Напишите необработанные данные (JSON + новая строка) в транспорт
read_messages()Асинхронный итератор, который выдает разобранные JSON сообщения
close()Закройте соединение и очистите ресурсы
is_ready()Возвращает True, если транспорт может отправлять и получать
end_input()Закройте входной поток (например, закройте stdin для транспортов подпроцесса)
Импорт: from claude_agent_sdk import Transport

ClaudeAgentOptions

Dataclass конфигурации для запросов Claude Code.
@dataclass
class ClaudeAgentOptions:
    tools: list[str] | ToolsPreset | None = None
    allowed_tools: list[str] = field(default_factory=list)
    system_prompt: str | SystemPromptPreset | None = None
    mcp_servers: dict[str, McpServerConfig] | str | Path = field(default_factory=dict)
    strict_mcp_config: bool = False
    permission_mode: PermissionMode | None = None
    continue_conversation: bool = False
    resume: str | None = None
    max_turns: int | None = None
    max_budget_usd: float | None = None
    disallowed_tools: list[str] = field(default_factory=list)
    model: str | None = None
    fallback_model: str | None = None
    betas: list[SdkBeta] = field(default_factory=list)
    output_format: dict[str, Any] | None = None
    permission_prompt_tool_name: str | None = None
    cwd: str | Path | None = None
    cli_path: str | Path | None = None
    settings: str | None = None
    add_dirs: list[str | Path] = field(default_factory=list)
    env: dict[str, str] = field(default_factory=dict)
    extra_args: dict[str, str | None] = field(default_factory=dict)
    max_buffer_size: int | None = None
    debug_stderr: Any = sys.stderr  # Deprecated
    stderr: Callable[[str], None] | None = None
    can_use_tool: CanUseTool | None = None
    hooks: dict[HookEvent, list[HookMatcher]] | None = None
    user: str | None = None
    include_partial_messages: bool = False
    include_hook_events: bool = False
    fork_session: bool = False
    agents: dict[str, AgentDefinition] | None = None
    setting_sources: list[SettingSource] | None = None
    sandbox: SandboxSettings | None = None
    plugins: list[SdkPluginConfig] = field(default_factory=list)
    max_thinking_tokens: int | None = None  # Deprecated: use thinking instead
    thinking: ThinkingConfig | None = None
    effort: EffortLevel | None = None
    enable_file_checkpointing: bool = False
    session_store: SessionStore | None = None
    session_store_flush: SessionStoreFlushMode = "batched"
СвойствоТипПо умолчаниюОписание
toolslist[str] | ToolsPreset | NoneNoneКонфигурация инструментов. Используйте {"type": "preset", "preset": "claude_code"} для инструментов Claude Code по умолчанию
allowed_toolslist[str][]Инструменты для автоматического одобрения без запроса. Это не ограничивает Claude только этими инструментами; неуказанные инструменты переходят к permission_mode и can_use_tool. Используйте disallowed_tools для блокировки инструментов. См. Permissions
system_promptstr | SystemPromptPreset | NoneNoneКонфигурация системной подсказки. Передайте строку для пользовательской подсказки или используйте {"type": "preset", "preset": "claude_code"} для системной подсказки Claude Code. Добавьте "append" для расширения предустановки
mcp_serversdict[str, McpServerConfig] | str | Path{}Конфигурации MCP server или путь к файлу конфигурации
strict_mcp_configboolFalseКогда True, используйте только servers, переданные в mcp_servers, и игнорируйте проект .mcp.json, параметры пользователя, MCP servers, предоставленные plugins, и claude.ai connectors. Соответствует флагу CLI --strict-mcp-config
permission_modePermissionMode | NoneNoneРежим разрешений для использования инструментов
continue_conversationboolFalseПродолжить самый последний разговор
resumestr | NoneNoneID сеанса для возобновления
max_turnsint | NoneNoneМаксимальное количество агентских ходов (раунды использования инструментов)
max_budget_usdfloat | NoneNoneОстановите запрос, когда оценка стоимости на стороне клиента достигнет этого значения USD. Сравнивается с той же оценкой, что и total_cost_usd; см. Track cost and usage для предостережений точности
disallowed_toolslist[str][]Инструменты для отклонения. Простое имя, такое как "Bash", удаляет инструмент из контекста Claude. Правило с областью действия, такое как "Bash(rm *)", оставляет инструмент доступным и отклоняет совпадающие вызовы в каждом режиме разрешений, включая bypassPermissions. См. Permissions
enable_file_checkpointingboolFalseВключить отслеживание изменений файлов для перемотки. См. File checkpointing
modelstr | NoneNoneМодель Claude для использования
fallback_modelstr | NoneNoneРезервная модель для использования, если основная модель не работает
betaslist[SdkBeta][]Функции бета-версии для включения. См. SdkBeta для доступных опций
output_formatdict[str, Any] | NoneNoneФормат вывода для структурированных ответов (например, {"type": "json_schema", "schema": {...}}). См. Structured outputs для деталей
permission_prompt_tool_namestr | NoneNoneИмя MCP tool для подсказок разрешений
cwdstr | Path | NoneNoneТекущий рабочий каталог
cli_pathstr | Path | NoneNoneПользовательский путь к исполняемому файлу Claude Code CLI
settingsstr | NoneNoneПуть к файлу параметров
add_dirslist[str | Path][]Дополнительные каталоги, к которым Claude может получить доступ
envdict[str, str]{}Переменные окружения, объединенные поверх унаследованного окружения процесса. См. Environment variables для переменных, которые читает базовый CLI, и Handle slow or stalled API responses для переменных, связанных с тайм-аутом
extra_argsdict[str, str | None]{}Дополнительные аргументы CLI для прямой передачи в CLI
max_buffer_sizeint | NoneNoneМаксимальные байты при буферизации stdout CLI
debug_stderrAnysys.stderrУстарело - Объект, подобный файлу, для вывода отладки. Вместо этого используйте обратный вызов stderr
stderrCallable[[str], None] | NoneNoneФункция обратного вызова для вывода stderr из CLI
can_use_toolCanUseTool | NoneNoneФункция обратного вызова разрешения инструмента. См. Permission types для деталей
hooksdict[HookEvent, list[HookMatcher]] | NoneNoneКонфигурации hooks для перехвата событий
userstr | NoneNoneИдентификатор пользователя
include_partial_messagesboolFalseВключить события потоковой передачи частичных сообщений. Когда включено, выдаются сообщения StreamEvent
include_hook_eventsboolFalseВключить события жизненного цикла hooks в поток сообщений как объекты HookEventMessage
fork_sessionboolFalseПри возобновлении с resume разветвитесь на новый ID сеанса вместо продолжения исходного сеанса
agentsdict[str, AgentDefinition] | NoneNoneПрограммно определенные подагенты
pluginslist[SdkPluginConfig][]Загрузите пользовательские plugins из локальных путей. См. Plugins для деталей
sandboxSandboxSettings | NoneNoneПрограммно настройте поведение sandbox. См. Sandbox settings для деталей
setting_sourceslist[SettingSource] | NoneNone (CLI defaults: all sources)Контролируйте, какие параметры файловой системы загружать. Передайте [] для отключения пользовательских, проектных и локальных параметров. Управляемые параметры политики загружаются независимо. См. Use Claude Code features
skillslist[str] | Literal["all"] | NoneNoneSkills, доступные сеансу. Передайте "all" для включения каждого обнаруженного skill, или список имен skills. Когда установлено, SDK автоматически добавляет инструмент Skill в allowed_tools. Если вы также передаете tools, включите "Skill" в этот список. См. Skills
max_thinking_tokensint | NoneNoneУстарело - Максимальные токены для блоков мышления. Вместо этого используйте thinking
thinkingThinkingConfig | NoneNoneУправляет поведением расширенного мышления. Имеет приоритет над max_thinking_tokens
effortEffortLevel | NoneNoneУровень усилий для глубины мышления
session_storeSessionStore | NoneNoneЗеркалируйте стенограммы сеансов во внешний бэкэнд, чтобы любой хост мог их возобновить. См. Persist sessions to external storage
session_store_flushLiteral["batched", "eager"]"batched"Когда сбрасывать записи зеркальной стенограммы в session_store. "batched" сбрасывает один раз за ход или когда буфер заполняется; "eager" запускает фоновый сброс после каждого кадра. Игнорируется, когда session_store равен None

Обработка медленных или зависших ответов API

Подпроцесс CLI читает несколько переменных окружения, которые управляют тайм-аутами API и обнаружением зависания. Передайте их через ClaudeAgentOptions.env:
options = ClaudeAgentOptions(
    env={
        "API_TIMEOUT_MS": "120000",
        "CLAUDE_CODE_MAX_RETRIES": "2",
        "CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS": "120000",
    },
)
  • API_TIMEOUT_MS: тайм-аут для каждого запроса на клиенте Anthropic в миллисекундах. По умолчанию 600000. Применяется к основному циклу и всем подагентам.
  • CLAUDE_CODE_MAX_RETRIES: максимальное количество повторных попыток API. По умолчанию 10. Каждая повторная попытка получает свое собственное окно API_TIMEOUT_MS, поэтому наихудшее время стены примерно API_TIMEOUT_MS × (CLAUDE_CODE_MAX_RETRIES + 1) плюс отступ.
  • CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS: сторожевой таймер зависания для подагентов, запущенных с run_in_background. По умолчанию 600000. Сбрасывается при каждом событии потока; при зависании он прерывает подагента, отмечает задачу как неудачную и выводит ошибку родителю с любым частичным результатом. Не применяется к синхронным подагентам.
  • CLAUDE_ENABLE_STREAM_WATCHDOG=1 с CLAUDE_STREAM_IDLE_TIMEOUT_MS: прерывает запрос, когда заголовки прибыли, но тело ответа перестает потоковать. По умолчанию отключено. CLAUDE_STREAM_IDLE_TIMEOUT_MS по умолчанию 300000 и зажимается до этого минимума. Прерванный запрос проходит через обычный путь повторной попытки.

OutputFormat

Конфигурация для валидации структурированного вывода. Передайте это как dict в поле output_format на ClaudeAgentOptions:
# Expected dict shape for output_format
{
    "type": "json_schema",
    "schema": {...},  # Your JSON Schema definition
}
ПолеОбязательноОписание
typeДаДолжно быть "json_schema" для валидации JSON Schema
schemaДаОпределение JSON Schema для валидации вывода

SystemPromptPreset

Конфигурация для использования предустановленной системной подсказки Claude Code с дополнительными добавлениями.
class SystemPromptPreset(TypedDict):
    type: Literal["preset"]
    preset: Literal["claude_code"]
    append: NotRequired[str]
    exclude_dynamic_sections: NotRequired[bool]
ПолеОбязательноОписание
typeДаДолжно быть "preset" для использования предустановленной системной подсказки
presetДаДолжно быть "claude_code" для использования системной подсказки Claude Code
appendНетДополнительные инструкции для добавления к предустановленной системной подсказке
exclude_dynamic_sectionsНетПереместите контекст для каждого сеанса, такой как рабочий каталог, статус git и пути памяти, из системной подсказки в первое пользовательское сообщение. Улучшает повторное использование кэша подсказок между пользователями и машинами. См. Modify system prompts

SettingSource

Управляет тем, какие источники конфигурации на основе файловой системы загружает SDK.
SettingSource = Literal["user", "project", "local"]
ЗначениеОписаниеМестоположение
"user"Глобальные параметры пользователя~/.claude/settings.json
"project"Общие параметры проекта (контролируемые версией).claude/settings.json
"local"Локальные параметры проекта (gitignored).claude/settings.local.json

Поведение по умолчанию

Когда setting_sources опущено или None, query() загружает те же параметры файловой системы, что и Claude Code CLI: пользовательские, проектные и локальные. Управляемые параметры политики загружаются во всех случаях. См. What settingSources does not control для входов, которые читаются независимо от этой опции, и как их отключить.

Почему использовать setting_sources

Отключить параметры файловой системы:
# Do not load user, project, or local settings from disk
from claude_agent_sdk import query, ClaudeAgentOptions

async for message in query(
    prompt="Analyze this code",
    options=ClaudeAgentOptions(
        setting_sources=[]
    ),
):
    print(message)
В Python SDK 0.1.59 и более ранних версиях пустой список рассматривался так же, как опущение опции, поэтому setting_sources=[] не отключал параметры файловой системы. Обновитесь до более новой версии, если вам нужно, чтобы пустой список вступил в силу. TypeScript SDK не затронут.
Загрузить все параметры файловой системы явно:
from claude_agent_sdk import query, ClaudeAgentOptions

async for message in query(
    prompt="Analyze this code",
    options=ClaudeAgentOptions(
        setting_sources=["user", "project", "local"]
    ),
):
    print(message)
Загрузить только определенные источники параметров:
# Load only project settings, ignore user and local
async for message in query(
    prompt="Run CI checks",
    options=ClaudeAgentOptions(
        setting_sources=["project"]  # Only .claude/settings.json
    ),
):
    print(message)
Тестирование и окружения CI:
# Ensure consistent behavior in CI by excluding local settings
async for message in query(
    prompt="Run tests",
    options=ClaudeAgentOptions(
        setting_sources=["project"],  # Only team-shared settings
        permission_mode="bypassPermissions",
    ),
):
    print(message)
Приложения только SDK:
# Define everything programmatically.
# Pass [] to opt out of filesystem setting sources.
async for message in query(
    prompt="Review this PR",
    options=ClaudeAgentOptions(
        setting_sources=[],
        agents={...},
        mcp_servers={...},
        allowed_tools=["Read", "Grep", "Glob"],
    ),
):
    print(message)
Загрузка инструкций проекта CLAUDE.md:
# Load project settings to include CLAUDE.md files
async for message in query(
    prompt="Add a new feature following project conventions",
    options=ClaudeAgentOptions(
        system_prompt={
            "type": "preset",
            "preset": "claude_code",  # Use Claude Code's system prompt
        },
        setting_sources=["project"],  # Loads CLAUDE.md from project
        allowed_tools=["Read", "Write", "Edit"],
    ),
):
    print(message)

Приоритет параметров

Когда загружаются несколько источников, параметры объединяются с этим приоритетом (от наивысшего к наименьшему):
  1. Локальные параметры (.claude/settings.local.json)
  2. Параметры проекта (.claude/settings.json)
  3. Параметры пользователя (~/.claude/settings.json)
Программные опции, такие как agents и allowed_tools, переопределяют параметры пользователя, проекта и локальной файловой системы. Управляемые параметры политики имеют приоритет над программными опциями.

AgentDefinition

Конфигурация для подагента, определенного программно.
@dataclass
class AgentDefinition:
    description: str
    prompt: str
    tools: list[str] | None = None
    disallowedTools: list[str] | None = None
    model: str | None = None
    skills: list[str] | None = None
    memory: Literal["user", "project", "local"] | None = None
    mcpServers: list[str | dict[str, Any]] | None = None
    initialPrompt: str | None = None
    maxTurns: int | None = None
    background: bool | None = None
    effort: EffortLevel | int | None = None
    permissionMode: PermissionMode | None = None
ПолеОбязательноОписание
descriptionДаОписание на естественном языке, когда использовать этого агента
promptДаСистемная подсказка агента
toolsНетМассив разрешенных имен инструментов. Если опущено, наследует все инструменты
disallowedToolsНетМассив имен инструментов для удаления из набора инструментов агента
modelНетПереопределение модели для этого агента. Принимает псевдоним, такой как "sonnet", "opus", "haiku" или "inherit", или полный ID модели. Если опущено, использует основную модель
skillsНетСписок имен skills для предварительной загрузки в контекст агента при запуске. Неуказанные skills остаются вызываемыми через инструмент Skill
memoryНетИсточник памяти для этого агента: "user", "project" или "local"
mcpServersНетMCP servers, доступные этому агенту. Каждая запись - это имя сервера или встроенный словарь {name: config}
initialPromptНетАвтоматически отправляется как первый ход пользователя, когда этот агент работает как основной агент потока
maxTurnsНетМаксимальное количество агентских ходов перед остановкой агента
backgroundНетЗапустите этого агента как неблокирующую фоновую задачу при вызове
effortНетУровень усилий рассуждения для этого агента. Принимает именованный уровень или целое число. См. EffortLevel
permissionModeНетРежим разрешений для выполнения инструментов в этом агенте. См. PermissionMode
Имена полей AgentDefinition используют camelCase, такие как disallowedTools, permissionMode и maxTurns. Эти имена напрямую соответствуют формату проводки, общему с TypeScript SDK. Это отличается от ClaudeAgentOptions, который использует Python snake_case для эквивалентных полей верхнего уровня, таких как disallowed_tools и permission_mode. Поскольку AgentDefinition является dataclass, передача ключевого слова snake_case вызывает TypeError во время конструирования.

PermissionMode

Режимы разрешений для управления выполнением инструментов.
PermissionMode = Literal[
    "default",  # Standard permission behavior
    "acceptEdits",  # Auto-accept file edits
    "plan",  # Planning mode - read-only tools only
    "dontAsk",  # Deny anything not pre-approved instead of prompting
    "bypassPermissions",  # Bypass all permission checks (use with caution)
]

EffortLevel

Уровни усилий для руководства глубиной мышления.
EffortLevel = Literal[
    "low",  # Minimal thinking, fastest responses
    "medium",  # Moderate thinking
    "high",  # Deep reasoning
    "xhigh",  # Extended reasoning (Opus 4.7 only; falls back to "high" on other models)
    "max",  # Maximum effort
]

CanUseTool

Псевдоним типа для функций обратного вызова разрешения инструмента.
CanUseTool = Callable[
    [str, dict[str, Any], ToolPermissionContext], Awaitable[PermissionResult]
]
Обратный вызов получает:
  • tool_name: Имя вызываемого инструмента
  • input_data: Входные параметры инструмента
  • context: ToolPermissionContext с дополнительной информацией
Возвращает PermissionResult (либо PermissionResultAllow, либо PermissionResultDeny).

ToolPermissionContext

Информация контекста, передаваемая в обратные вызовы разрешения инструмента.
@dataclass
class ToolPermissionContext:
    signal: Any | None = None  # Future: abort signal support
    suggestions: list[PermissionUpdate] = field(default_factory=list)
    blocked_path: str | None = None
    decision_reason: str | None = None
    title: str | None = None
    display_name: str | None = None
    description: str | None = None
ПолеТипОписание
signalAny | NoneЗарезервировано для будущей поддержки сигнала прерывания
suggestionslist[PermissionUpdate]Предложения обновления разрешений из CLI. Подсказки Bash включают предложение с назначением localSettings, поэтому возврат его в updated_permissions записывает правило в .claude/settings.local.json и сохраняется между сеансами.
blocked_pathstr | NoneПуть к файлу, который вызвал запрос разрешения, если применимо. Например, когда команда Bash пытается получить доступ к пути вне разрешенных каталогов
decision_reasonstr | NoneПричина, по которой был вызван этот запрос разрешения. Переадресовано из permissionDecisionReason hook PreToolUse, когда hook вернул "ask"
titlestr | NoneПолное предложение запроса разрешения, такое как Claude wants to read foo.txt. Используйте как основной текст подсказки, если присутствует
display_namestr | NoneКороткая именная фраза для действия инструмента, такая как Read file, подходящая для меток кнопок
descriptionstr | NoneПонятный подзаголовок для пользовательского интерфейса разрешений

PermissionResult

Тип объединения для результатов обратного вызова разрешения.
PermissionResult = PermissionResultAllow | PermissionResultDeny

PermissionResultAllow

Результат, указывающий, что вызов инструмента должен быть разрешен.
@dataclass
class PermissionResultAllow:
    behavior: Literal["allow"] = "allow"
    updated_input: dict[str, Any] | None = None
    updated_permissions: list[PermissionUpdate] | None = None
ПолеТипПо умолчаниюОписание
behaviorLiteral["allow"]"allow"Должно быть “allow”
updated_inputdict[str, Any] | NoneNoneИзмененный ввод для использования вместо оригинала
updated_permissionslist[PermissionUpdate] | NoneNoneОбновления разрешений для применения

PermissionResultDeny

Результат, указывающий, что вызов инструмента должен быть отклонен.
@dataclass
class PermissionResultDeny:
    behavior: Literal["deny"] = "deny"
    message: str = ""
    interrupt: bool = False
ПолеТипПо умолчаниюОписание
behaviorLiteral["deny"]"deny"Должно быть “deny”
messagestr""Сообщение, объясняющее, почему инструмент был отклонен
interruptboolFalseСледует ли прерывать текущее выполнение

PermissionUpdate

Конфигурация для программного обновления разрешений.
@dataclass
class PermissionUpdate:
    type: Literal[
        "addRules",
        "replaceRules",
        "removeRules",
        "setMode",
        "addDirectories",
        "removeDirectories",
    ]
    rules: list[PermissionRuleValue] | None = None
    behavior: Literal["allow", "deny", "ask"] | None = None
    mode: PermissionMode | None = None
    directories: list[str] | None = None
    destination: (
        Literal["userSettings", "projectSettings", "localSettings", "session"] | None
    ) = None
ПолеТипОписание
typeLiteral[...]Тип операции обновления разрешений
ruleslist[PermissionRuleValue] | NoneПравила для операций добавления/замены/удаления
behaviorLiteral["allow", "deny", "ask"] | NoneПоведение для операций на основе правил
modePermissionMode | NoneРежим для операции setMode
directorieslist[str] | NoneКаталоги для операций добавления/удаления каталога
destinationLiteral[...] | NoneГде применить обновление разрешений

PermissionRuleValue

Правило для добавления, замены или удаления в обновлении разрешений.
@dataclass
class PermissionRuleValue:
    tool_name: str
    rule_content: str | None = None

ToolsPreset

Конфигурация предустановленных инструментов для использования набора инструментов Claude Code по умолчанию.
class ToolsPreset(TypedDict):
    type: Literal["preset"]
    preset: Literal["claude_code"]

ThinkingConfig

Управляет поведением расширенного мышления. Объединение трех конфигураций:
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
ВариантПоляОписание
adaptivetype, displayClaude адаптивно решает, когда думать
enabledtype, budget_tokens, displayВключить мышление с определенным бюджетом токенов
disabledtypeОтключить мышление
Дополнительное поле display управляет тем, возвращается ли текст мышления "summarized" или "omitted". На Claude Opus 4.7 и более поздних версиях API по умолчанию используется "omitted", поэтому установите "summarized" для получения содержимого мышления в выводах ThinkingBlock. Поскольку это классы TypedDict, они являются простыми словарями во время выполнения. Либо создавайте их как литералы словарей, либо вызывайте класс как конструктор; оба создают dict. Получайте доступ к полям с помощью config["budget_tokens"], а не config.budget_tokens:
from claude_agent_sdk import ClaudeAgentOptions, ThinkingConfigEnabled

# Option 1: dict literal (recommended, no import needed)
options = ClaudeAgentOptions(thinking={"type": "enabled", "budget_tokens": 20000})

# Option 2: constructor-style (returns a plain dict)
config = ThinkingConfigEnabled(type="enabled", budget_tokens=20000)
print(config["budget_tokens"])  # 20000
# config.budget_tokens would raise AttributeError

SdkBeta

Тип Literal для функций бета-версии SDK.
SdkBeta = Literal["context-1m-2025-08-07"]
Используйте с полем betas в ClaudeAgentOptions для включения функций бета-версии.
Бета-версия context-1m-2025-08-07 снята с производства по состоянию на 30 апреля 2026 года. Передача этого заголовка с Claude Sonnet 4.5 или Sonnet 4 не имеет эффекта, и запросы, превышающие стандартное окно контекста 200k-токенов, возвращают ошибку. Чтобы использовать окно контекста 1M-токенов, перейдите на Claude Sonnet 4.6, Claude Opus 4.6 или Claude Opus 4.7, которые включают контекст 1M по стандартной цене без требования заголовка бета-версии.

McpSdkServerConfig

Конфигурация для SDK MCP servers, созданных с помощью create_sdk_mcp_server().
class McpSdkServerConfig(TypedDict):
    type: Literal["sdk"]
    name: str
    instance: Any  # MCP Server instance

McpServerConfig

Тип объединения для конфигураций MCP server.
McpServerConfig = (
    McpStdioServerConfig | McpSSEServerConfig | McpHttpServerConfig | McpSdkServerConfig
)

McpStdioServerConfig

class McpStdioServerConfig(TypedDict):
    type: NotRequired[Literal["stdio"]]  # Optional for backwards compatibility
    command: str
    args: NotRequired[list[str]]
    env: NotRequired[dict[str, str]]

McpSSEServerConfig

class McpSSEServerConfig(TypedDict):
    type: Literal["sse"]
    url: str
    headers: NotRequired[dict[str, str]]

McpHttpServerConfig

class McpHttpServerConfig(TypedDict):
    type: Literal["http"]
    url: str
    headers: NotRequired[dict[str, str]]

McpServerStatusConfig

Конфигурация MCP server, как сообщается get_mcp_status(). Это объединение всех вариантов транспорта McpServerConfig плюс вариант claudeai-proxy только для вывода для servers, проксированных через claude.ai.
McpServerStatusConfig = (
    McpStdioServerConfig
    | McpSSEServerConfig
    | McpHttpServerConfig
    | McpSdkServerConfigStatus
    | McpClaudeAIProxyServerConfig
)
McpSdkServerConfigStatus - это сериализуемая форма McpSdkServerConfig с только полями type ("sdk") и name (str); встроенный instance опущен. McpClaudeAIProxyServerConfig имеет поля type ("claudeai-proxy"), url (str) и id (str).

McpStatusResponse

Ответ от ClaudeSDKClient.get_mcp_status(). Оборачивает список статусов сервера под ключом mcpServers.
class McpStatusResponse(TypedDict):
    mcpServers: list[McpServerStatus]

McpServerStatus

Статус подключенного MCP server, содержащийся в 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]]
ПолеТипОписание
namestrИмя сервера
statusstrОдин из "connected", "failed", "needs-auth", "pending" или "disabled"
serverInfodict (опционально)Имя и версия сервера ({"name": str, "version": str})
errorstr (опционально)Сообщение об ошибке, если серверу не удалось подключиться
configMcpServerStatusConfig (опционально)Конфигурация сервера. Та же форма, что и McpServerConfig (stdio, SSE, HTTP или SDK), плюс вариант claudeai-proxy для servers, подключенных через claude.ai
scopestr (опционально)Область конфигурации
toolslist (опционально)Инструменты, предоставляемые этим сервером, каждый с полями name, description и annotations

SdkPluginConfig

Конфигурация для загрузки plugins в SDK.
class SdkPluginConfig(TypedDict):
    type: Literal["local"]
    path: str
ПолеТипОписание
typeLiteral["local"]Должно быть "local" (в настоящее время поддерживаются только локальные plugins)
pathstrАбсолютный или относительный путь к каталогу plugin
Пример:
plugins = [
    {"type": "local", "path": "./my-plugin"},
    {"type": "local", "path": "/absolute/path/to/plugin"},
]
Для полной информации о создании и использовании plugins см. Plugins.

Типы сообщений

Message

Тип объединения всех возможных сообщений.
Message = (
    UserMessage
    | AssistantMessage
    | SystemMessage
    | ResultMessage
    | StreamEvent
    | RateLimitEvent
)

UserMessage

Сообщение пользовательского ввода.
@dataclass
class UserMessage:
    content: str | list[ContentBlock]
    uuid: str | None = None
    parent_tool_use_id: str | None = None
    tool_use_result: dict[str, Any] | None = None
ПолеТипОписание
contentstr | list[ContentBlock]Содержимое сообщения как текст или блоки содержимого
uuidstr | NoneУникальный идентификатор сообщения
parent_tool_use_idstr | NoneID использования инструмента, если это сообщение является ответом результата инструмента
tool_use_resultdict[str, Any] | NoneДанные результата инструмента, если применимо

AssistantMessage

Сообщение ответа помощника с блоками содержимого.
@dataclass
class AssistantMessage:
    content: list[ContentBlock]
    model: str
    parent_tool_use_id: str | None = None
    error: AssistantMessageError | None = None
    usage: dict[str, Any] | None = None
    message_id: str | None = None
ПолеТипОписание
contentlist[ContentBlock]Список блоков содержимого в ответе
modelstrМодель, которая создала ответ
parent_tool_use_idstr | NoneID использования инструмента, если это вложенный ответ
errorAssistantMessageError | NoneТип ошибки, если ответ столкнулся с ошибкой
usagedict[str, Any] | NoneИспользование токенов для каждого сообщения (те же ключи, что и ResultMessage.usage)
message_idstr | NoneID сообщения API. Несколько сообщений из одного хода имеют одинаковый ID

AssistantMessageError

Возможные типы ошибок для сообщений помощника.
AssistantMessageError = Literal[
    "authentication_failed",
    "billing_error",
    "rate_limit",
    "invalid_request",
    "server_error",
    "max_output_tokens",
    "unknown",
]

SystemMessage

Системное сообщение с метаданными.
@dataclass
class SystemMessage:
    subtype: str
    data: dict[str, Any]

ResultMessage

Финальное сообщение результата с информацией о стоимости и использовании.
@dataclass
class 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, Any] | 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
Словарь usage содержит следующие ключи, если они присутствуют:
КлючТипОписание
input_tokensintВсего потреблено входных токенов.
output_tokensintВсего создано выходных токенов.
cache_creation_input_tokensintТокены, используемые для создания новых записей кэша.
cache_read_input_tokensintТокены, прочитанные из существующих записей кэша.
Словарь model_usage отображает имена моделей на использование для каждой модели. Внутренние ключи словаря используют camelCase, потому что значение передается без изменений из базового процесса CLI, соответствуя типу TypeScript ModelUsage:
КлючТипОписание
inputTokensintВходные токены для этой модели.
outputTokensintВыходные токены для этой модели.
cacheReadInputTokensintТокены чтения кэша для этой модели.
cacheCreationInputTokensintТокены создания кэша для этой модели.
webSearchRequestsintЗапросы веб-поиска, сделанные этой моделью.
costUSDfloatПредполагаемая стоимость в USD для этой модели, вычисленная на стороне клиента. См. Track cost and usage для предостережений выставления счетов.
contextWindowintРазмер окна контекста для этой модели.
maxOutputTokensintМаксимальный лимит выходных токенов для этой модели.

StreamEvent

Событие потока для частичных обновлений сообщений во время потоковой передачи. Получается только когда include_partial_messages=True в ClaudeAgentOptions. Импортируйте через from claude_agent_sdk.types import StreamEvent.
@dataclass
class StreamEvent:
    uuid: str
    session_id: str
    event: dict[str, Any]  # The raw Claude API stream event
    parent_tool_use_id: str | None = None
ПолеТипОписание
uuidstrУникальный идентификатор для этого события
session_idstrИдентификатор сеанса
eventdict[str, Any]Необработанные данные события потока Claude API
parent_tool_use_idstr | NoneID использования родительского инструмента, если это событие из подагента

RateLimitEvent

Выдается при изменении статуса ограничения скорости (например, с "allowed" на "allowed_warning"). Используйте это для предупреждения пользователей перед достижением жесткого лимита или для отката, когда статус "rejected".
@dataclass
class RateLimitEvent:
    rate_limit_info: RateLimitInfo
    uuid: str
    session_id: str
ПолеТипОписание
rate_limit_infoRateLimitInfoТекущее состояние ограничения скорости
uuidstrУникальный идентификатор события
session_idstrИдентификатор сеанса

RateLimitInfo

Состояние ограничения скорости, переносимое RateLimitEvent.
RateLimitStatus = Literal["allowed", "allowed_warning", "rejected"]
RateLimitType = Literal[
    "five_hour", "seven_day", "seven_day_opus", "seven_day_sonnet", "overage"
]


@dataclass
class RateLimitInfo:
    status: RateLimitStatus
    resets_at: int | None = None
    rate_limit_type: RateLimitType | None = None
    utilization: float | None = None
    overage_status: RateLimitStatus | None = None
    overage_resets_at: int | None = None
    overage_disabled_reason: str | None = None
    raw: dict[str, Any] = field(default_factory=dict)
ПолеТипОписание
statusRateLimitStatusТекущий статус. "allowed_warning" означает приближение к лимиту; "rejected" означает, что лимит был достигнут
resets_atint | NoneВременная метка Unix, когда окно ограничения скорости сбрасывается
rate_limit_typeRateLimitType | NoneКакое окно ограничения скорости применяется
utilizationfloat | NoneДоля потребленного ограничения скорости (0,0 до 1,0)
overage_statusRateLimitStatus | NoneСтатус использования переплаты по мере использования, если применимо
overage_resets_atint | NoneВременная метка Unix, когда окно переплаты сбрасывается
overage_disabled_reasonstr | NoneПочему переплата недоступна, если статус "rejected"
rawdict[str, Any]Полный необработанный словарь из CLI, включая поля, не смоделированные выше

TaskStartedMessage

Выдается при запуске фоновой задачи. Фоновая задача - это все, что отслеживается вне основного хода: фоновая команда Bash, наблюдение Monitor, подагент, порожденный через инструмент Agent, или удаленный агент. Поле task_type говорит вам, какой. Это именование не связано с переименованием инструмента Task на Agent.
@dataclass
class TaskStartedMessage(SystemMessage):
    task_id: str
    description: str
    uuid: str
    session_id: str
    tool_use_id: str | None = None
    task_type: str | None = None
ПолеТипОписание
task_idstrУникальный идентификатор для задачи
descriptionstrОписание задачи
uuidstrУникальный идентификатор сообщения
session_idstrИдентификатор сеанса
tool_use_idstr | NoneСвязанный ID использования инструмента
task_typestr | NoneКакой вид фоновой задачи: "local_bash" для фонового Bash и наблюдений Monitor, "local_agent" или "remote_agent"

TaskUsage

Данные токенов и времени для фоновой задачи.
class TaskUsage(TypedDict):
    total_tokens: int
    tool_uses: int
    duration_ms: int

TaskProgressMessage

Выдается периодически с обновлениями прогресса для выполняющейся фоновой задачи.
@dataclass
class TaskProgressMessage(SystemMessage):
    task_id: str
    description: str
    usage: TaskUsage
    uuid: str
    session_id: str
    tool_use_id: str | None = None
    last_tool_name: str | None = None
ПолеТипОписание
task_idstrУникальный идентификатор для задачи
descriptionstrОписание текущего статуса
usageTaskUsageИспользование токенов для этой задачи до сих пор
uuidstrУникальный идентификатор сообщения
session_idstrИдентификатор сеанса
tool_use_idstr | NoneСвязанный ID использования инструмента
last_tool_namestr | NoneИмя последнего инструмента, который использовала задача

TaskNotificationMessage

Выдается при завершении, сбое или остановке фоновой задачи. Фоновые задачи включают команды Bash run_in_background, наблюдения Monitor и фоновые подагенты.
@dataclass
class TaskNotificationMessage(SystemMessage):
    task_id: str
    status: TaskNotificationStatus  # "completed" | "failed" | "stopped"
    output_file: str
    summary: str
    uuid: str
    session_id: str
    tool_use_id: str | None = None
    usage: TaskUsage | None = None
ПолеТипОписание
task_idstrУникальный идентификатор для задачи
statusTaskNotificationStatusОдин из "completed", "failed" или "stopped"
output_filestrПуть к файлу вывода задачи
summarystrРезюме результата задачи
uuidstrУникальный идентификатор сообщения
session_idstrИдентификатор сеанса
tool_use_idstr | NoneСвязанный ID использования инструмента
usageTaskUsage | NoneФинальное использование токенов для задачи

Типы блоков содержимого

ContentBlock

Тип объединения всех блоков содержимого.
ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock

TextBlock

Блок содержимого текста.
@dataclass
class TextBlock:
    text: str

ThinkingBlock

Блок содержимого мышления (для моделей с возможностью мышления).
@dataclass
class ThinkingBlock:
    thinking: str
    signature: str

ToolUseBlock

Блок запроса использования инструмента.
@dataclass
class ToolUseBlock:
    id: str
    name: str
    input: dict[str, Any]

ToolResultBlock

Блок результата выполнения инструмента.
@dataclass
class ToolResultBlock:
    tool_use_id: str
    content: str | list[dict[str, Any]] | None = None
    is_error: bool | None = None

Типы ошибок

ClaudeSDKError

Базовый класс исключения для всех ошибок SDK.
class ClaudeSDKError(Exception):
    """Base error for Claude SDK."""

CLINotFoundError

Вызывается, когда Claude Code CLI не установлен или не найден.
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

Вызывается, когда соединение с Claude Code не удается.
class CLIConnectionError(ClaudeSDKError):
    """Failed to connect to Claude Code."""

ProcessError

Вызывается, когда процесс Claude Code не работает.
class ProcessError(ClaudeSDKError):
    def __init__(
        self, message: str, exit_code: int | None = None, stderr: str | None = None
    ):
        self.exit_code = exit_code
        self.stderr = stderr

CLIJSONDecodeError

Вызывается, когда разбор JSON не удается.
class CLIJSONDecodeError(ClaudeSDKError):
    def __init__(self, line: str, original_error: Exception):
        """
        Args:
            line: The line that failed to parse
            original_error: The original JSON decode exception
        """
        self.line = line
        self.original_error = original_error

Типы hooks

Для полного руководства по использованию hooks с примерами и общими шаблонами см. Hooks guide.

HookEvent

Поддерживаемые типы событий hooks.
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
]
TypeScript SDK поддерживает дополнительные события hooks, которые еще недоступны в Python: SessionStart, SessionEnd, Setup, TeammateIdle, TaskCompleted, ConfigChange, WorktreeCreate, WorktreeRemove, PostToolBatch и MessageDisplay.

HookCallback

Определение типа для функций обратного вызова hooks.
HookCallback = Callable[[HookInput, str | None, HookContext], Awaitable[HookJSONOutput]]
Параметры:
  • input: Строго типизированный ввод hooks с дискриминированными объединениями на основе hook_event_name (см. HookInput)
  • tool_use_id: Дополнительный идентификатор использования инструмента (для hooks, связанных с инструментами)
  • context: Контекст hooks с дополнительной информацией
Возвращает HookJSONOutput, который может содержать:
  • decision: "block" для блокировки действия
  • systemMessage: Предупреждающее сообщение, показываемое пользователю
  • hookSpecificOutput: Вывод, специфичный для hooks

HookContext

Информация контекста, передаваемая в обратные вызовы hooks.
class HookContext(TypedDict):
    signal: Any | None  # Future: abort signal support

HookMatcher

Конфигурация для сопоставления hooks с определенными событиями или инструментами.
@dataclass
class HookMatcher:
    matcher: str | None = (
        None  # Tool name or pattern to match (e.g., "Bash", "Write|Edit")
    )
    hooks: list[HookCallback] = field(
        default_factory=list
    )  # List of callbacks to execute
    timeout: float | None = (
        None  # Timeout in seconds for all hooks in this matcher (default: 60)
    )

HookInput

Тип объединения всех типов ввода hooks. Фактический тип зависит от поля hook_event_name.
HookInput = (
    PreToolUseHookInput
    | PostToolUseHookInput
    | PostToolUseFailureHookInput
    | UserPromptSubmitHookInput
    | StopHookInput
    | SubagentStopHookInput
    | PreCompactHookInput
    | NotificationHookInput
    | SubagentStartHookInput
    | PermissionRequestHookInput
)

BaseHookInput

Базовые поля, присутствующие во всех типах ввода hooks.
class BaseHookInput(TypedDict):
    session_id: str
    transcript_path: str
    cwd: str
    permission_mode: NotRequired[str]
ПолеТипОписание
session_idstrТекущий идентификатор сеанса
transcript_pathstrПуть к файлу стенограммы сеанса
cwdstrТекущий рабочий каталог
permission_modestr (опционально)Текущий режим разрешений

PreToolUseHookInput

Входные данные для событий hooks 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]
ПолеТипОписание
hook_event_nameLiteral["PreToolUse"]Всегда “PreToolUse”
tool_namestrИмя инструмента, который вот-вот будет выполнен
tool_inputdict[str, Any]Входные параметры для инструмента
tool_use_idstrУникальный идентификатор для этого использования инструмента
agent_idstr (опционально)Идентификатор подагента, присутствует, когда hooks срабатывает внутри подагента
agent_typestr (опционально)Тип подагента, присутствует, когда hooks срабатывает внутри подагента

PostToolUseHookInput

Входные данные для событий hooks 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]
ПолеТипОписание
hook_event_nameLiteral["PostToolUse"]Всегда “PostToolUse”
tool_namestrИмя выполненного инструмента
tool_inputdict[str, Any]Использованные входные параметры
tool_responseAnyОтвет от выполнения инструмента
tool_use_idstrУникальный идентификатор для этого использования инструмента
agent_idstr (опционально)Идентификатор подагента, присутствует, когда hooks срабатывает внутри подагента
agent_typestr (опционально)Тип подагента, присутствует, когда hooks срабатывает внутри подагента

PostToolUseFailureHookInput

Входные данные для событий hooks PostToolUseFailure. Вызывается, когда выполнение инструмента не удается.
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]
ПолеТипОписание
hook_event_nameLiteral["PostToolUseFailure"]Всегда “PostToolUseFailure”
tool_namestrИмя инструмента, который не удался
tool_inputdict[str, Any]Использованные входные параметры
tool_use_idstrУникальный идентификатор для этого использования инструмента
errorstrСообщение об ошибке из неудачного выполнения
is_interruptbool (опционально)Была ли ошибка вызвана прерыванием
agent_idstr (опционально)Идентификатор подагента, присутствует, когда hooks срабатывает внутри подагента
agent_typestr (опционально)Тип подагента, присутствует, когда hooks срабатывает внутри подагента

UserPromptSubmitHookInput

Входные данные для событий hooks UserPromptSubmit.
class UserPromptSubmitHookInput(BaseHookInput):
    hook_event_name: Literal["UserPromptSubmit"]
    prompt: str
ПолеТипОписание
hook_event_nameLiteral["UserPromptSubmit"]Всегда “UserPromptSubmit”
promptstrОтправленная пользователем подсказка

StopHookInput

Входные данные для событий hooks Stop.
class StopHookInput(BaseHookInput):
    hook_event_name: Literal["Stop"]
    stop_hook_active: bool
ПолеТипОписание
hook_event_nameLiteral["Stop"]Всегда “Stop”
stop_hook_activeboolАктивен ли hooks остановки

SubagentStopHookInput

Входные данные для событий hooks SubagentStop.
class SubagentStopHookInput(BaseHookInput):
    hook_event_name: Literal["SubagentStop"]
    stop_hook_active: bool
    agent_id: str
    agent_transcript_path: str
    agent_type: str
ПолеТипОписание
hook_event_nameLiteral["SubagentStop"]Всегда “SubagentStop”
stop_hook_activeboolАктивен ли hooks остановки
agent_idstrУникальный идентификатор подагента
agent_transcript_pathstrПуть к файлу стенограммы подагента
agent_typestrТип подагента

PreCompactHookInput

Входные данные для событий hooks PreCompact.
class PreCompactHookInput(BaseHookInput):
    hook_event_name: Literal["PreCompact"]
    trigger: Literal["manual", "auto"]
    custom_instructions: str | None
ПолеТипОписание
hook_event_nameLiteral["PreCompact"]Всегда “PreCompact”
triggerLiteral["manual", "auto"]Что вызвало уплотнение
custom_instructionsstr | NoneПользовательские инструкции для уплотнения

NotificationHookInput

Входные данные для событий hooks Notification.
class NotificationHookInput(BaseHookInput):
    hook_event_name: Literal["Notification"]
    message: str
    title: NotRequired[str]
    notification_type: str
ПолеТипОписание
hook_event_nameLiteral["Notification"]Всегда “Notification”
messagestrСодержимое сообщения уведомления
titlestr (опционально)Название уведомления
notification_typestrТип уведомления

SubagentStartHookInput

Входные данные для событий hooks SubagentStart.
class SubagentStartHookInput(BaseHookInput):
    hook_event_name: Literal["SubagentStart"]
    agent_id: str
    agent_type: str
ПолеТипОписание
hook_event_nameLiteral["SubagentStart"]Всегда “SubagentStart”
agent_idstrУникальный идентификатор подагента
agent_typestrТип подагента

PermissionRequestHookInput

Входные данные для событий hooks PermissionRequest. Позволяет hooks программно обрабатывать решения разрешений.
class PermissionRequestHookInput(BaseHookInput):
    hook_event_name: Literal["PermissionRequest"]
    tool_name: str
    tool_input: dict[str, Any]
    permission_suggestions: NotRequired[list[Any]]
ПолеТипОписание
hook_event_nameLiteral["PermissionRequest"]Всегда “PermissionRequest”
tool_namestrИмя инструмента, запрашивающего разрешение
tool_inputdict[str, Any]Входные параметры для инструмента
permission_suggestionslist[Any] (опционально)Предложенные обновления разрешений из CLI

HookJSONOutput

Тип объединения для возвращаемых значений обратного вызова hooks.
HookJSONOutput = AsyncHookJSONOutput | SyncHookJSONOutput

SyncHookJSONOutput

Синхронный вывод hooks с полями управления и решения.
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]
Используйте continue_ (с подчеркиванием) в коде Python. Он автоматически преобразуется в continue при отправке в CLI.

HookSpecificOutput

TypedDict, содержащий имя события hooks и поля, специфичные для события. Форма зависит от значения hookEventName. Для полных деталей доступных полей для каждого события hooks см. Control execution with hooks. Дискриминированное объединение типов вывода, специфичных для события. Поле hookEventName определяет, какие поля действительны.
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

Асинхронный вывод hooks, который откладывает выполнение hooks.
class AsyncHookJSONOutput(TypedDict):
    async_: Literal[True]  # Set to True to defer execution
    asyncTimeout: NotRequired[int]  # Timeout in milliseconds
Используйте async_ (с подчеркиванием) в коде Python. Он автоматически преобразуется в async при отправке в CLI.

Пример использования hooks

Этот пример регистрирует два hooks: один, который блокирует опасные команды bash, такие как rm -rf /, и другой, который регистрирует все использование инструментов для аудита. Hooks безопасности работает только на командах Bash (через matcher), в то время как hooks логирования работает на всех инструментах.
from claude_agent_sdk import query, ClaudeAgentOptions, HookMatcher, HookContext
from typing import Any


async def validate_bash_command(
    input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
    """Validate and potentially block dangerous bash commands."""
    if input_data["tool_name"] == "Bash":
        command = input_data["tool_input"].get("command", "")
        if "rm -rf /" in command:
            return {
                "hookSpecificOutput": {
                    "hookEventName": "PreToolUse",
                    "permissionDecision": "deny",
                    "permissionDecisionReason": "Dangerous command blocked",
                }
            }
    return {}


async def log_tool_use(
    input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
    """Log all tool usage for auditing."""
    print(f"Tool used: {input_data.get('tool_name')}")
    return {}


options = ClaudeAgentOptions(
    hooks={
        "PreToolUse": [
            HookMatcher(
                matcher="Bash", hooks=[validate_bash_command], timeout=120
            ),  # 2 min for validation
            HookMatcher(
                hooks=[log_tool_use]
            ),  # Applies to all tools (default 60s timeout)
        ],
        "PostToolUse": [HookMatcher(hooks=[log_tool_use])],
    }
)

async for message in query(prompt="Analyze this codebase", options=options):
    print(message)

Типы ввода/вывода инструментов

Документация схем ввода/вывода для всех встроенных инструментов Claude Code. Хотя Python SDK не экспортирует их как типы, они представляют структуру входов и выходов инструментов в сообщениях.

Agent

Имя инструмента: Agent (ранее Task, который все еще принимается как псевдоним) Ввод:
{
    "description": str,  # Краткое описание задачи (3-5 слов)
    "prompt": str,  # Задача для выполнения агентом
    "subagent_type": str,  # Тип специализированного агента для использования
}
Вывод:
{
    "result": str,  # Финальный результат от подагента
    "usage": dict | None,  # Статистика использования токенов
    "total_cost_usd": float | None,  # Предполагаемая общая стоимость в USD
    "duration_ms": int | None,  # Длительность выполнения в миллисекундах
}

AskUserQuestion

Имя инструмента: AskUserQuestion Задает пользователю уточняющие вопросы во время выполнения. См. Обработка одобрений и ввода пользователя для деталей использования. Ввод:
{
    "questions": [  # Вопросы для пользователя (1-4 вопроса)
        {
            "question": str,  # Полный вопрос для пользователя
            "header": str,  # Очень короткая метка, отображаемая как чип/тег (макс 12 символов)
            "options": [  # Доступные варианты (2-4 варианта)
                {
                    "label": str,  # Текст отображения для этого варианта (1-5 слов)
                    "description": str,  # Объяснение того, что означает этот вариант
                }
            ],
            "multiSelect": bool,  # Установите значение true, чтобы разрешить множественный выбор
        }
    ],
    "answers": dict[str, str | list[str]] | None,
    # Ответы пользователя, заполненные системой разрешений. Ответы с множественным выбором
    # могут быть списком меток или строкой, объединенной запятыми
}
Вывод:
{
    "questions": [  # Вопросы, которые были заданы
        {
            "question": str,
            "header": str,
            "options": [{"label": str, "description": str}],
            "multiSelect": bool,
        }
    ],
    "answers": dict[str, str],  # Сопоставляет текст вопроса со строкой ответа
    # Ответы с множественным выбором разделены запятыми
}

Bash

Имя инструмента: Bash Ввод:
{
    "command": str,  # Команда для выполнения
    "timeout": int | None,  # Необязательный тайм-аут в миллисекундах (макс 600000)
    "description": str | None,  # Четкое, краткое описание (5-10 слов)
    "run_in_background": bool | None,  # Установите значение true для выполнения в фоне
}
Вывод:
{
    "output": str,  # Объединенный вывод stdout и stderr
    "exitCode": int,  # Код выхода команды
    "killed": bool | None,  # Была ли команда убита из-за тайм-аута
    "shellId": str | None,  # ID оболочки для фоновых процессов
}

Monitor

Имя инструмента: Monitor Запускает фоновый скрипт и доставляет каждую строку stdout в Claude как событие, чтобы он мог реагировать без опроса. Monitor следует тем же правилам разрешений, что и Bash. См. Справочник инструмента Monitor для поведения и доступности поставщика. Ввод:
{
    "command": str,  # Скрипт оболочки; каждая строка stdout является событием, выход завершает наблюдение
    "description": str,  # Краткое описание, показываемое в уведомлениях
    "timeout_ms": int | None,  # Завершить после этого срока (по умолчанию 300000, макс 3600000)
    "persistent": bool | None,  # Запускать в течение всего времени сеанса; остановить с помощью TaskStop
}
Вывод:
{
    "taskId": str,  # ID фоновой задачи мониторинга
    "timeoutMs": int,  # Срок тайм-аута в миллисекундах (0 при постоянном режиме)
    "persistent": bool | None,  # True при выполнении до TaskStop или конца сеанса
}

Edit

Имя инструмента: Edit Ввод:
{
    "file_path": str,  # Абсолютный путь к файлу для изменения
    "old_string": str,  # Текст для замены
    "new_string": str,  # Текст для замены на
    "replace_all": bool | None,  # Заменить все вхождения (по умолчанию False)
}
Вывод:
{
    "message": str,  # Сообщение подтверждения
    "replacements": int,  # Количество выполненных замен
    "file_path": str,  # Путь файла, который был отредактирован
}

Read

Имя инструмента: Read Ввод:
{
    "file_path": str,  # Абсолютный путь к файлу для чтения
    "offset": int | None,  # Номер строки для начала чтения
    "limit": int | None,  # Количество строк для чтения
}
Вывод (текстовые файлы):
{
    "content": str,  # Содержимое файла с номерами строк
    "total_lines": int,  # Общее количество строк в файле
    "lines_returned": int,  # Фактически возвращенные строки
}
Вывод (изображения):
{
    "image": str,  # Данные изображения в кодировке Base64
    "mime_type": str,  # MIME-тип изображения
    "file_size": int,  # Размер файла в байтах
}

Write

Имя инструмента: Write Ввод:
{
    "file_path": str,  # Абсолютный путь к файлу для записи
    "content": str,  # Содержимое для записи в файл
}
Вывод:
{
    "message": str,  # Сообщение об успехе
    "bytes_written": int,  # Количество записанных байтов
    "file_path": str,  # Путь файла, который был записан
}

Glob

Имя инструмента: Glob Ввод:
{
    "pattern": str,  # Шаблон glob для сопоставления файлов
    "path": str | None,  # Каталог для поиска (по умолчанию текущий каталог)
}
Вывод:
{
    "matches": list[str],  # Массив совпадающих путей файлов
    "count": int,  # Количество найденных совпадений
    "search_path": str,  # Использованный каталог поиска
}

Grep

Имя инструмента: Grep Ввод:
{
    "pattern": str,  # Шаблон регулярного выражения
    "path": str | None,  # Файл или каталог для поиска
    "glob": str | None,  # Шаблон glob для фильтрации файлов
    "type": str | None,  # Тип файла для поиска
    "output_mode": str | None,  # "content", "files_with_matches" или "count"
    "-i": bool | None,  # Поиск без учета регистра
    "-n": bool | None,  # Показать номера строк
    "-B": int | None,  # Строки для отображения перед каждым совпадением
    "-A": int | None,  # Строки для отображения после каждого совпадения
    "-C": int | None,  # Строки для отображения до и после
    "head_limit": int | None,  # Ограничить вывод первыми N строками/записями
    "multiline": bool | None,  # Включить многострочный режим
}
Вывод (режим content):
{
    "matches": [
        {
            "file": str,
            "line_number": int | None,
            "line": str,
            "before_context": list[str] | None,
            "after_context": list[str] | None,
        }
    ],
    "total_matches": int,
}
Вывод (режим files_with_matches):
{
    "files": list[str],  # Файлы, содержащие совпадения
    "count": int,  # Количество файлов с совпадениями
}

NotebookEdit

Имя инструмента: NotebookEdit Ввод:
{
    "notebook_path": str,  # Абсолютный путь к записной книжке Jupyter
    "cell_id": str | None,  # ID ячейки для редактирования
    "new_source": str,  # Новый исходный код для ячейки
    "cell_type": "code" | "markdown" | None,  # Тип ячейки
    "edit_mode": "replace" | "insert" | "delete" | None,  # Тип операции редактирования
}
Вывод:
{
    "message": str,  # Сообщение об успехе
    "edit_type": "replaced" | "inserted" | "deleted",  # Тип выполненного редактирования
    "cell_id": str | None,  # ID ячейки, которая была затронута
    "total_cells": int,  # Общее количество ячеек в записной книжке после редактирования
}

WebFetch

Имя инструмента: WebFetch Ввод:
{
    "url": str,  # URL для получения содержимого
    "prompt": str,  # Подсказка для запуска на полученном содержимом
}
Вывод:
{
    "bytes": int,  # Размер полученного содержимого в байтах
    "code": int,  # Код ответа HTTP
    "codeText": str,  # Текст кода ответа HTTP
    "result": str,  # Обработанный результат от применения подсказки к содержимому
    "durationMs": int,  # Время получения и обработки содержимого в миллисекундах
    "url": str,  # URL, который был получен
}

WebSearch

Имя инструмента: WebSearch Ввод:
{
    "query": str,  # Поисковый запрос для использования
    "allowed_domains": list[str] | None,  # Включать результаты только с этих доменов
    "blocked_domains": list[str] | None,  # Никогда не включать результаты с этих доменов
}
Вывод:
{
    "query": str,  # Поисковый запрос
    "results": list[str | {"tool_use_id": str, "content": list[{"title": str, "url": str}]}],
    "durationSeconds": float,  # Длительность поиска в секундах
}

TodoWrite

Имя инструмента: TodoWrite
Начиная с Claude Code v2.1.142, TodoWrite отключен по умолчанию. Используйте вместо этого TaskCreate, TaskGet, TaskUpdate и TaskList. См. Миграция на инструменты Task для обновления кода мониторинга, или установите CLAUDE_CODE_ENABLE_TASKS=0 для возврата к TodoWrite.
Ввод:
{
    "todos": [
        {
            "content": str,  # Описание задачи
            "status": "pending" | "in_progress" | "completed",  # Статус задачи
            "activeForm": str,  # Активная форма описания
        }
    ]
}
Вывод:
{
    "message": str,  # Сообщение об успехе
    "stats": {"total": int, "pending": int, "in_progress": int, "completed": int},
}

TaskCreate

Имя инструмента: TaskCreate Ввод:
{
    "subject": str,  # Краткое название задачи
    "description": str,  # Подробное описание задачи
    "activeForm": str | None,  # Метка в настоящем времени, показываемая во время выполнения
    "metadata": dict | None,  # Произвольные метаданные вызывающей стороны
}
Вывод:
{
    "task": {"id": str, "subject": str},  # Созданная задача с назначенным ID
}

TaskUpdate

Имя инструмента: TaskUpdate Ввод:
{
    "taskId": str,  # ID задачи для обновления
    "status": Literal["pending", "in_progress", "completed", "deleted"] | None,
    "subject": str | None,
    "description": str | None,
    "activeForm": str | None,
    "addBlocks": list[str] | None,  # ID задач, которые эта задача теперь блокирует
    "addBlockedBy": list[str] | None,  # ID задач, которые теперь блокируют эту задачу
    "owner": str | None,
    "metadata": dict | None,
}
Вывод:
{
    "success": bool,
    "taskId": str,
    "updatedFields": list[str],  # Названия полей, которые изменились
    "error": str | None,
    "statusChange": {"from": str, "to": str} | None,
}

TaskGet

Имя инструмента: TaskGet Ввод:
{
    "taskId": str,  # ID задачи для чтения
}
Вывод:
{
    "task": {
        "id": str,
        "subject": str,
        "description": str,
        "status": Literal["pending", "in_progress", "completed"],
        "blocks": list[str],
        "blockedBy": list[str],
    } | None,  # None, когда ID не найден
}

TaskList

Имя инструмента: TaskList Ввод:
{}
Вывод:
{
    "tasks": [
        {
            "id": str,
            "subject": str,
            "status": Literal["pending", "in_progress", "completed"],
            "owner": str | None,
            "blockedBy": list[str],
        }
    ],
}

BashOutput

Имя инструмента: BashOutput Ввод:
{
    "bash_id": str,  # ID фоновой оболочки
    "filter": str | None,  # Необязательное регулярное выражение для фильтрации строк вывода
}
Вывод:
{
    "output": str,  # Новый вывод с момента последней проверки
    "status": "running" | "completed" | "failed",  # Текущий статус оболочки
    "exitCode": int | None,  # Код выхода при завершении
}

KillBash

Имя инструмента: KillBash Ввод:
{
    "shell_id": str  # ID фоновой оболочки для завершения
}
Вывод:
{
    "message": str,  # Сообщение об успехе
    "shell_id": str,  # ID завершенной оболочки
}

ExitPlanMode

Имя инструмента: ExitPlanMode Ввод:
{
    "plan": str  # План для запуска пользователем на одобрение
}
Вывод:
{
    "message": str,  # Сообщение подтверждения
    "approved": bool | None,  # Одобрил ли пользователь план
}

ListMcpResources

Имя инструмента: ListMcpResourcesTool Ввод:
{
    "server": str | None  # Необязательное имя сервера для фильтрации ресурсов
}
Вывод:
{
    "resources": [
        {
            "uri": str,
            "name": str,
            "description": str | None,
            "mimeType": str | None,
            "server": str,
        }
    ],
    "total": int,
}

ReadMcpResource

Имя инструмента: ReadMcpResourceTool Ввод:
{
    "server": str,  # Имя сервера MCP
    "uri": str,  # URI ресурса для чтения
}
Вывод:
{
    "contents": [
        {"uri": str, "mimeType": str | None, "text": str | None, "blob": str | None}
    ],
    "server": str,
}

Расширенные функции с ClaudeSDKClient

Построение интерфейса непрерывного разговора

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())

Использование hooks для модификации поведения

from claude_agent_sdk import (
    ClaudeSDKClient,
    ClaudeAgentOptions,
    HookMatcher,
    HookContext,
)
import asyncio
from typing import Any


async def pre_tool_logger(
    input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
    """Log all tool usage before execution."""
    tool_name = input_data.get("tool_name", "unknown")
    print(f"[PRE-TOOL] About to use: {tool_name}")

    # You can modify or block the tool execution here
    if tool_name == "Bash" and "rm -rf" in str(input_data.get("tool_input", {})):
        return {
            "hookSpecificOutput": {
                "hookEventName": "PreToolUse",
                "permissionDecision": "deny",
                "permissionDecisionReason": "Dangerous command blocked",
            }
        }
    return {}


async def post_tool_logger(
    input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
    """Log results after tool execution."""
    tool_name = input_data.get("tool_name", "unknown")
    print(f"[POST-TOOL] Completed: {tool_name}")
    return {}


async def user_prompt_modifier(
    input_data: dict[str, Any], tool_use_id: str | None, context: HookContext
) -> dict[str, Any]:
    """Add context to user prompts."""
    original_prompt = input_data.get("prompt", "")

    # Add a timestamp as additional context for Claude to see
    from datetime import datetime

    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    return {
        "hookSpecificOutput": {
            "hookEventName": "UserPromptSubmit",
            "additionalContext": f"[Submitted at {timestamp}] Original prompt: {original_prompt}",
        }
    }


async def main():
    options = ClaudeAgentOptions(
        hooks={
            "PreToolUse": [
                HookMatcher(hooks=[pre_tool_logger]),
                HookMatcher(matcher="Bash", hooks=[pre_tool_logger]),
            ],
            "PostToolUse": [HookMatcher(hooks=[post_tool_logger])],
            "UserPromptSubmit": [HookMatcher(hooks=[user_prompt_modifier])],
        },
        allowed_tools=["Read", "Write", "Bash"],
    )

    async with ClaudeSDKClient(options=options) as client:
        await client.query("List files in current directory")

        async for message in client.receive_response():
            # Hooks will automatically log tool usage
            pass


asyncio.run(main())

Мониторинг прогресса в реальном времени

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())

Пример использования

Базовые операции с файлами (используя query)

from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, ToolUseBlock
import asyncio


async def create_project():
    options = ClaudeAgentOptions(
        allowed_tools=["Read", "Write", "Bash"],
        permission_mode="acceptEdits",
        cwd="/home/user/project",
    )

    async for message in query(
        prompt="Create a Python project structure with setup.py", options=options
    ):
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, ToolUseBlock):
                    print(f"Using tool: {block.name}")


asyncio.run(create_project())

Обработка ошибок

from claude_agent_sdk import query, CLINotFoundError, ProcessError, CLIJSONDecodeError

try:
    async for message in query(prompt="Hello"):
        print(message)
except CLINotFoundError:
    print(
        "Claude Code CLI not found. Try reinstalling: pip install --force-reinstall claude-agent-sdk"
    )
except ProcessError as e:
    print(f"Process failed with exit code: {e.exit_code}")
except CLIJSONDecodeError as e:
    print(f"Failed to parse response: {e}")

Режим потоковой передачи с клиентом

from claude_agent_sdk import ClaudeSDKClient
import asyncio


async def interactive_session():
    async with ClaudeSDKClient() as client:
        # Send initial message
        await client.query("What's the weather like?")

        # Process responses
        async for msg in client.receive_response():
            print(msg)

        # Send follow-up
        await client.query("Tell me more about that")

        # Process follow-up response
        async for msg in client.receive_response():
            print(msg)


asyncio.run(interactive_session())

Использование пользовательских инструментов с ClaudeSDKClient

from claude_agent_sdk import (
    ClaudeSDKClient,
    ClaudeAgentOptions,
    tool,
    create_sdk_mcp_server,
    AssistantMessage,
    TextBlock,
)
import asyncio
from typing import Any


# Define custom tools with @tool decorator
@tool("calculate", "Perform mathematical calculations", {"expression": str})
async def calculate(args: dict[str, Any]) -> dict[str, Any]:
    try:
        result = eval(args["expression"], {"__builtins__": {}})
        return {"content": [{"type": "text", "text": f"Result: {result}"}]}
    except Exception as e:
        return {
            "content": [{"type": "text", "text": f"Error: {str(e)}"}],
            "is_error": True,
        }


@tool("get_time", "Get current time", {})
async def get_time(args: dict[str, Any]) -> dict[str, Any]:
    from datetime import datetime

    current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    return {"content": [{"type": "text", "text": f"Current time: {current_time}"}]}


async def main():
    # Create SDK MCP server with custom tools
    my_server = create_sdk_mcp_server(
        name="utilities", version="1.0.0", tools=[calculate, get_time]
    )

    # Configure options with the server
    options = ClaudeAgentOptions(
        mcp_servers={"utils": my_server},
        allowed_tools=["mcp__utils__calculate", "mcp__utils__get_time"],
    )

    # Use ClaudeSDKClient for interactive tool usage
    async with ClaudeSDKClient(options=options) as client:
        await client.query("What's 123 * 456?")

        # Process calculation response
        async for message in client.receive_response():
            if isinstance(message, AssistantMessage):
                for block in message.content:
                    if isinstance(block, TextBlock):
                        print(f"Calculation: {block.text}")

        # Follow up with time query
        await client.query("What time is it now?")

        async for message in client.receive_response():
            if isinstance(message, AssistantMessage):
                for block in message.content:
                    if isinstance(block, TextBlock):
                        print(f"Time: {block.text}")


asyncio.run(main())

Конфигурация sandbox

SandboxSettings

Конфигурация для поведения sandbox. Используйте это для включения sandboxing команд и программной настройки ограничений сети.
class SandboxSettings(TypedDict, total=False):
    enabled: bool
    autoAllowBashIfSandboxed: bool
    excludedCommands: list[str]
    allowUnsandboxedCommands: bool
    network: SandboxNetworkConfig
    ignoreViolations: SandboxIgnoreViolations
    enableWeakerNestedSandbox: bool
СвойствоТипПо умолчаниюОписание
enabledboolFalseВключить режим sandbox для выполнения команд
autoAllowBashIfSandboxedboolTrueАвтоматически одобрять команды bash, когда sandbox включен
excludedCommandslist[str][]Команды, которые всегда обходят ограничения sandbox (например, ["docker"]). Они работают без sandbox автоматически без участия модели
allowUnsandboxedCommandsboolTrueРазрешить модели запрашивать выполнение команд вне sandbox. Когда True, модель может установить dangerouslyDisableSandbox в входе инструмента, что переходит к системе разрешений
networkSandboxNetworkConfigNoneКонфигурация sandbox, специфичная для сети
ignoreViolationsSandboxIgnoreViolationsNoneНастройте, какие нарушения sandbox игнорировать
enableWeakerNestedSandboxboolFalseВключить более слабый вложенный sandbox для совместимости
Sandbox зависит от поддержки платформы и, в Linux, от инструментов, таких как bubblewrap и socat. По умолчанию, когда enabled имеет значение True, но sandbox не может запуститься, команды выполняются без sandbox с предупреждением на stderr. Это поведение по умолчанию отличается от TypeScript SDK, где failIfUnavailable по умолчанию имеет значение true.Установите "failIfUnavailable": True в параметрах sandbox, чтобы остановиться вместо этого. Ключ еще не объявлен на SandboxSettings, но SDK передает его в Claude Code, который его соблюдает. query() затем сообщает ResultMessage с subtype="error_during_execution" и причину в errors. Следите за этим подтипом, а не ожидайте, что query() вызовет исключение перед выдачей сообщений.

Пример использования

from claude_agent_sdk import query, ClaudeAgentOptions, SandboxSettings

sandbox_settings: SandboxSettings = {
    "enabled": True,
    "autoAllowBashIfSandboxed": True,
    "network": {"allowLocalBinding": True},
}

async for message in query(
    prompt="Build and test my project",
    options=ClaudeAgentOptions(sandbox=sandbox_settings),
):
    print(message)
Безопасность Unix socket: Опция allowUnixSockets может предоставить доступ к мощным системным сервисам. Например, разрешение /var/run/docker.sock фактически предоставляет полный доступ к хост-системе через Docker API, обходя изоляцию sandbox. Разрешайте только Unix sockets, которые строго необходимы, и поймите последствия безопасности каждого.

SandboxNetworkConfig

Конфигурация, специфичная для сети, для режима sandbox. Эти параметры применяются к sandboxed Bash командам, когда enabled имеет значение True в родительском SandboxSettings. Они не ограничивают инструмент WebFetch, который вместо этого использует правила разрешений.
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
СвойствоТипПо умолчаниюОписание
allowedDomainslist[str][]Имена доменов, к которым могут получить доступ процессы в sandbox
deniedDomainslist[str][]Имена доменов, к которым процессы в sandbox не могут получить доступ. Имеет приоритет над allowedDomains
allowManagedDomainsOnlyboolFalseТолько управляемые параметры: когда установлено в управляемых параметрах, игнорируйте allowedDomains из источников неуправляемых параметров. Не имеет эффекта при установке через параметры SDK
allowUnixSocketslist[str][]Пути Unix socket, к которым процессы могут получить доступ (например, Docker socket)
allowAllUnixSocketsboolFalseРазрешить доступ ко всем Unix sockets
allowLocalBindingboolFalseРазрешить процессам привязываться к локальным портам (например, для dev servers)
allowMachLookuplist[str][]Только macOS: имена сервисов XPC/Mach для разрешения. Поддерживает завершающий подстановочный знак
httpProxyPortintNoneПорт HTTP proxy для сетевых запросов
socksProxyPortintNoneПорт SOCKS proxy для сетевых запросов
Встроенный прокси sandbox обеспечивает соблюдение списка разрешенных сетей на основе запрашиваемого имени хоста и не завершает и не проверяет трафик TLS, поэтому такие методы, как domain fronting, потенциально могут его обойти. Подробнее см. в разделе Ограничения безопасности Sandboxing и Безопасное развертывание для настройки прокси, завершающего TLS.

SandboxIgnoreViolations

Конфигурация для игнорирования определенных нарушений sandbox.
class SandboxIgnoreViolations(TypedDict, total=False):
    file: list[str]
    network: list[str]
СвойствоТипПо умолчаниюОписание
filelist[str][]Шаблоны путей файлов для игнорирования нарушений
networklist[str][]Шаблоны сети для игнорирования нарушений

Fallback разрешений для команд без sandbox

Когда allowUnsandboxedCommands включен, модель может запросить выполнение команд вне sandbox, установив dangerouslyDisableSandbox: True во входе инструмента. Эти запросы переходят к существующей системе разрешений, что означает, что ваш обработчик can_use_tool будет вызван, позволяя вам реализовать пользовательскую логику авторизации.
excludedCommands vs allowUnsandboxedCommands:
  • excludedCommands: Статический список команд, которые всегда обходят sandbox автоматически (например, ["docker"]). Модель не имеет контроля над этим.
  • allowUnsandboxedCommands: Позволяет модели решать во время выполнения, запрашивать ли выполнение без sandbox, установив dangerouslyDisableSandbox: True во входе инструмента.
from claude_agent_sdk import (
    query,
    ClaudeAgentOptions,
    HookMatcher,
    PermissionResultAllow,
    PermissionResultDeny,
    ToolPermissionContext,
)


async def can_use_tool(
    tool: str, input: dict, context: ToolPermissionContext
) -> PermissionResultAllow | PermissionResultDeny:
    # Check if the model is requesting to bypass the sandbox
    if tool == "Bash" and input.get("dangerouslyDisableSandbox"):
        # The model is requesting to run this command outside the sandbox
        print(f"Unsandboxed command requested: {input.get('command')}")

        if is_command_authorized(input.get("command")):
            return PermissionResultAllow()
        return PermissionResultDeny(
            message="Command not authorized for unsandboxed execution"
        )
    return PermissionResultAllow()


# Required: dummy hook keeps the stream open for can_use_tool
async def dummy_hook(input_data, tool_use_id, context):
    return {"continue_": True}


async def prompt_stream():
    yield {
        "type": "user",
        "message": {"role": "user", "content": "Deploy my application"},
    }


async def main():
    async for message in query(
        prompt=prompt_stream(),
        options=ClaudeAgentOptions(
            sandbox={
                "enabled": True,
                "allowUnsandboxedCommands": True,  # Model can request unsandboxed execution
            },
            permission_mode="default",
            can_use_tool=can_use_tool,
            hooks={"PreToolUse": [HookMatcher(matcher=None, hooks=[dummy_hook])]},
        ),
    ):
        print(message)
Этот шаблон позволяет вам:
  • Аудит запросов модели: Логируйте, когда модель запрашивает выполнение без sandbox
  • Реализовать allowlists: Разрешайте только определенные команды работать без sandbox
  • Добавить рабочие процессы одобрения: Требуйте явной авторизации для привилегированных операций
Команды, работающие с dangerouslyDisableSandbox: True, имеют полный доступ к системе. Убедитесь, что ваш обработчик can_use_tool тщательно проверяет эти запросы.Если permission_mode установлен на bypassPermissions и allow_unsandboxed_commands включен, модель может автономно выполнять команды вне sandbox без каких-либо подсказок одобрения. Эта комбинация фактически позволяет модели молча выходить из изоляции sandbox.

См. также