Как работает цикл агента
Поймите жизненный цикл сообщений, выполнение инструментов, контекстное окно и архитектуру, которые питают ваших агентов SDK.
Agent SDK позволяет встроить автономный цикл агента Claude Code в ваши собственные приложения. SDK — это отдельный пакет, который дает вам программный контроль над инструментами, разрешениями, ограничениями затрат и выводом.
Оба SDK (TypeScript и Python) включают собственный бинарный файл Claude Code, поэтому большинству установок не требуется отдельная установка Claude Code. Примечание об установке см. в quickstart.
Когда вы запускаете агента, SDK запускает тот же цикл выполнения, который питает Claude Code: Claude оценивает ваш запрос, вызывает инструменты для выполнения действий, получает результаты и повторяет до завершения задачи. На этой странице объясняется, что происходит внутри этого цикла, чтобы вы могли эффективно создавать, отлаживать и оптимизировать своих агентов.
Цикл с первого взгляда
Каждая сессия агента следует одному и тому же циклу:
- Получить запрос. Claude получает ваш запрос вместе с системным запросом, определениями инструментов и историей разговора. SDK выдает
SystemMessageс подтипом"init", содержащий метаданные сессии. - Оценить и ответить. Claude оценивает текущее состояние и определяет, как действовать дальше. Он может ответить текстом, запросить один или несколько вызовов инструментов или оба варианта. SDK выдает один или несколько объектов
AssistantMessage, по одному для каждого блока содержимого, такого как текстовый блок или запрос вызова инструмента. - Выполнить инструменты. SDK запускает каждый запрошенный инструмент и собирает результаты. Каждый набор результатов инструментов возвращается Claude для следующего решения. Вы можете использовать hooks для перехвата, изменения или блокировки вызовов инструментов перед их выполнением.
- Повторить. Шаги 2 и 3 повторяются как цикл. Каждый полный цикл — это один ход. Claude продолжает вызывать инструменты и обрабатывать результаты до тех пор, пока не выдаст ответ без вызовов инструментов.
- Вернуть результат. SDK выдает финальное
AssistantMessageс текстовым ответом (без вызовов инструментов), за которым следуетResultMessageс финальным текстом, использованием токенов, стоимостью и ID сессии.
Быстрый вопрос («какие файлы здесь?») может занять один или два хода вызова Glob и ответа с результатами. Сложная задача («рефакторить модуль аутентификации и обновить тесты») может связать десятки вызовов инструментов на протяжении многих ходов, читая файлы, редактируя код и запуская тесты, при этом Claude корректирует свой подход на основе каждого результата.
Ходы и сообщения
Ход — это один цикл внутри цикла: Claude выдает выход, который включает вызовы инструментов, SDK выполняет эти инструменты, и результаты автоматически возвращаются Claude. Это происходит без возврата управления вашему коду. Ходы продолжаются до тех пор, пока Claude не выдаст выход без вызовов инструментов, после чего цикл заканчивается и доставляется финальный результат.
Рассмотрим, как может выглядеть полная сессия для запроса «Исправить неудачные тесты в auth.ts».
Сначала SDK отправляет ваш запрос Claude и выдает SystemMessage с метаданными сессии. Затем начинается цикл:
- Ход 1: Claude вызывает
Bashдля запускаnpm test. SDK выдаетAssistantMessageс вызовом инструмента, выполняет команду, затем выдаетUserMessageс выводом (три ошибки). - Ход 2: Claude вызывает
Readнаauth.tsиauth.test.ts. SDK выдаетAssistantMessageдля каждого вызова и возвращает содержимое файлов. - Ход 3: Claude вызывает
Editдля исправленияauth.ts, затем вызываетBashдля повторного запускаnpm test. Все три теста проходят. SDK выдаетAssistantMessageдля каждого вызова. - Финальный ход: Claude выдает текстовый ответ без вызовов инструментов: «Исправлена ошибка аутентификации, все три теста теперь проходят.» SDK выдает финальное
AssistantMessageс этим текстом, затемResultMessageс тем же текстом плюс стоимость и использование.
Это было четыре хода: три с вызовами инструментов, один финальный текстовый ответ.
Вы можете ограничить цикл с помощью max_turns / maxTurns, который считает только ходы с использованием инструментов. Например, max_turns=2 в цикле выше остановился бы перед шагом редактирования. Вы также можете использовать max_budget_usd / maxBudgetUsd для ограничения ходов на основе порога расходов.
Без ограничений цикл работает до тех пор, пока Claude не закончит самостоятельно, что хорошо для хорошо определенных задач, но может работать долго на открытых запросах («улучшить этот кодовую базу»). Установка бюджета — хороший стандарт для производственных агентов. См. Ходы и бюджет ниже для справки по опциям.
Типы сообщений
По мере выполнения цикла SDK выдает поток сообщений. Каждое сообщение имеет тип, который говорит вам, на каком этапе цикла оно пришло. Пять основных типов:
-
SystemMessage: события жизненного цикла сессии. Полеsubtypeих различает:"init": метаданные сессии для запуска. Когда hookSessionStartилиSetupзапускается при инициализации сессии, его сообщения жизненного цикла hook прибывают перед сообщениемinit"compact_boundary": срабатывает после компактирования"informational": простые текстовые баннеры статуса из цикла"worker_shutting_down": цикл завершится после текущего хода, потому что хост выходит или Remote Control отключился
В TypeScript каждый подтип, кроме
"init", является собственным типом в объединенииSDKMessage, а не подтипомSDKSystemMessage. -
AssistantMessage: выдается для каждого блока содержимого в ответах Claude, включая финальный текстовый. Каждое содержит один блок содержимого, такой как текст или вызов инструмента, и сообщения из одного ответа имеют общий ID сообщения. -
UserMessage: выдается после каждого выполнения инструмента с результатом инструмента, отправленным обратно Claude. Также выдается для любых пользовательских входов, которые вы транслируете в середине цикла. -
StreamEvent: выдается только при включении частичных сообщений. Содержит необработанные события потоковой передачи API (дельты текста, фрагменты входных данных инструмента). См. Потоковые ответы. -
ResultMessage: отмечает конец цикла агента. Содержит финальный текстовый результат, использование токенов, стоимость и ID сессии. Проверьте полеsubtype, чтобы определить, успешна ли задача или достигнут ли лимит. Небольшое количество завершающих системных событий, таких какprompt_suggestion, может прибыть после него, поэтому итерируйте поток до завершения, а не прерывайте на результате. См. Обработать результат.
Эти пять типов охватывают полный жизненный цикл цикла агента. Оба SDK также выдают события наблюдаемости, такие как статус ограничения скорости и уведомления задач, которые не требуются для управления циклом. См. справку по типам сообщений Python и справку по типам сообщений TypeScript для полных списков.
Обработать сообщения
Какие сообщения вы обрабатываете, зависит от того, что вы создаете:
- Только финальные результаты: обработайте
ResultMessage, чтобы получить выход, стоимость и то, успешна ли задача или достигнут ли лимит. - Обновления прогресса: обработайте
AssistantMessage, чтобы увидеть, что делает Claude на каждом ходу, включая какие инструменты он вызвал. - Прямая потоковая передача: включите частичные сообщения (
include_partial_messagesв Python,includePartialMessagesв TypeScript), чтобы получить сообщенияStreamEventв реальном времени. См. Потоковые ответы в реальном времени.
Как вы проверяете типы сообщений, зависит от SDK:
- Python: проверьте типы сообщений с помощью
isinstance()для классов, импортированных изclaude_agent_sdk(например,isinstance(message, ResultMessage)). - TypeScript: проверьте строковое поле
type(например,message.type === "result").AssistantMessageиUserMessageоборачивают необработанное сообщение API в поле.message, поэтому блоки содержимого находятся вmessage.message.content, а не вmessage.content.
Пример: Проверить типы сообщений и обработать результаты
import asyncio
from claude_agent_sdk import query, AssistantMessage, ResultMessage, TextBlock, ToolUseBlock
async def main():
try:
async for message in query(prompt="Summarize this project"):
if isinstance(message, AssistantMessage):
# Each AssistantMessage carries one content block
for block in message.content:
if isinstance(block, TextBlock):
print(f"Claude: {block.text}")
elif isinstance(block, ToolUseBlock):
print(f"Tool call: {block.name}")
if isinstance(message, ResultMessage):
if message.subtype == "success":
print(message.result)
else:
print(f"Stopped: {message.subtype}")
except Exception as error:
# A single-shot query() raises after yielding an error result. If the
# failure was an error result, the error subtype branches above have
# already run; connection or process failures yield no result message.
print(f"Session ended with an error: {error}")
asyncio.run(main())
import { query } from "@anthropic-ai/claude-agent-sdk";
try {
for await (const message of query({ prompt: "Summarize this project" })) {
if (message.type === "assistant") {
// Each assistant message carries one content block
for (const block of message.message.content) {
if (block.type === "text") {
console.log(`Claude: ${block.text}`);
} else if (block.type === "tool_use") {
console.log(`Tool call: ${block.name}`);
}
}
}
if (message.type === "result") {
if (message.subtype === "success") {
console.log(message.result);
} else {
console.log(`Stopped: ${message.subtype}`);
}
}
}
} catch (error) {
// A single-shot query() throws after yielding an error result. If the
// failure was an error result, the error subtype branches above have
// already run; connection or process failures yield no result message.
console.log(`Session ended with an error: ${error}`);
}
Выполнение инструментов
Инструменты дают вашему агенту возможность действовать. Без инструментов Claude может только отвечать текстом. С инструментами Claude может читать файлы, запускать команды, искать код и взаимодействовать с внешними сервисами.
Встроенные инструменты
SDK включает те же инструменты, которые питают Claude Code:
| Категория | Инструменты | Что они делают |
|---|---|---|
| Операции с файлами | Read, Edit, Write |
Читать, изменять и создавать файлы |
| Поиск | Glob, Grep |
Найти файлы по шаблону, искать содержимое с помощью regex |
| Выполнение | Bash |
Запускать команды оболочки, скрипты, операции git |
| Веб | WebSearch, WebFetch |
Искать в веб, получать и анализировать страницы |
| Обнаружение | ToolSearch |
Динамически находить и загружать инструменты по требованию вместо предварительной загрузки всех |
| Оркестрация | Agent, Skill, AskUserQuestion, TaskCreate, TaskUpdate |
Порождать подагентов, вызывать skills, спрашивать пользователя, отслеживать задачи |
На моделях, которые не получают инструменты отслеживания задач, Claude Code предоставляет TaskCreate и TaskUpdate только когда вы согласитесь.
Помимо встроенных инструментов, вы можете:
- Подключить внешние сервисы с помощью MCP servers (базы данных, браузеры, API)
- Определить пользовательские инструменты с помощью пользовательских обработчиков инструментов
- Загрузить skills проекта через источники настроек для повторно используемых рабочих процессов
Разрешения инструментов
Claude определяет, какие инструменты вызывать на основе задачи, но вы контролируете, разрешено ли выполнение этих вызовов. Вы можете автоматически одобрить определенные инструменты, полностью заблокировать другие или требовать одобрения для всего. Три опции работают вместе, чтобы определить, что работает:
allowed_tools/allowedToolsавтоматически одобряет перечисленные инструменты. Агент только для чтения с["Read", "Glob", "Grep"]в списке разрешенных инструментов запускает эти инструменты без подсказок. Инструменты, не указанные в списке, все еще доступны, и вызовы к ним, которые требуют одобрения, переходят к режиму разрешения иcanUseTool.disallowed_tools/disallowedToolsблокирует перечисленные инструменты, независимо от других настроек. См. Разрешения для порядка, в котором правила проверяются перед запуском инструмента.permission_mode/permissionModeконтролирует, сколько человеческого надзора вы хотите. SDK оценивает активный режим вместе с вашими правилами разрешения и запрета в фиксированном порядке, описанном в Как оцениваются разрешения. См. Режим разрешения для доступных режимов.
Вы также можете ограничить отдельные инструменты правилами, такими как "Bash(npm *)", чтобы разрешить только определенные команды. См. Разрешения для полного синтаксиса правил.
Когда инструмент отклоняется, Claude получает сообщение об отклонении как результат инструмента и обычно пытается использовать другой подход или сообщает, что не может продолжить.
Параллельное выполнение инструментов
Когда Claude запрашивает несколько вызовов инструментов в одном ходе, оба SDK могут запускать их одновременно или последовательно в зависимости от инструмента. Инструменты только для чтения (такие как Read, Glob, Grep и MCP инструменты, отмеченные как только для чтения) могут работать одновременно. Инструменты, которые изменяют состояние (такие как Edit, Write и Bash), работают последовательно, чтобы избежать конфликтов.
Пользовательские инструменты по умолчанию работают последовательно. Чтобы включить параллельное выполнение для пользовательского инструмента, установите readOnlyHint в его аннотациях. Оба SDK TypeScript и Python используют это имя поля из MCP SDK.
Контролировать, как работает цикл
Вы можете ограничить количество ходов, которые делает цикл, сколько он стоит, насколько глубоко Claude рассуждает, и требуют ли инструменты одобрения перед запуском. Все это поля на ClaudeAgentOptions (Python) / Options (TypeScript).
Ходы и бюджет
| Опция | Что она контролирует | По умолчанию |
|---|---|---|
Максимум ходов (max_turns / maxTurns) |
Максимум раундов использования инструментов | Без ограничений |
Максимум бюджета (max_budget_usd / maxBudgetUsd) |
Максимальная стоимость перед остановкой | Без ограничений |
Когда достигается любой лимит, SDK возвращает ResultMessage с соответствующим подтипом ошибки (error_max_turns или error_max_budget_usd). См. Обработать результат для того, как проверить эти подтипы, и ClaudeAgentOptions / Options для синтаксиса.
Крышка бюджета охватывает подагентов: их расходы учитываются в общей сумме. Когда расходы достигают крышки, создание другого подагента не удается с Budget limit reached, и Claude Code останавливает любых фоновых подагентов, которые все еще работают. Поведение принудительного применения крышки требует Claude Code v2.1.217 или позже.
При потоковом вводе сообщение, которое все еще находится в очереди, когда ход заканчивается на пределе максимальных ходов, остается в очереди. Claude Code не добавляет его в последний вызов модели этого хода. Он начинает новый ход для сообщения, и счетчик максимальных ходов начинается заново для этого хода.
Уровень усилий
Опция effort контролирует, сколько рассуждений применяет Claude. Более низкие уровни усилий используют меньше токенов за ход и снижают стоимость. Не все модели поддерживают параметр effort. См. Effort для того, какие модели его поддерживают.
| Уровень | Поведение | Хорошо для |
|---|---|---|
"low" |
Минимальное рассуждение, быстрые ответы | Поиск файлов, список каталогов |
"medium" |
Сбалансированное рассуждение | Обычные редактирования, стандартные задачи |
"high" |
Тщательный анализ | Рефакторинг, отладка |
"xhigh" |
Расширенная глубина рассуждения | Задачи кодирования и агентские на моделях, которые это поддерживают |
"max" |
Максимальная глубина рассуждения | Многошаговые проблемы, требующие глубокого анализа |
Если вы не установите effort, оба SDK оставляют параметр неустановленным и полагаются на поведение модели по умолчанию.
effort обменивает задержку и стоимость токена на глубину рассуждения в каждом ответе. Extended thinking — это отдельная функция, которая выдает блоки thinking в выводе, и поле display на ThinkingConfig для Python или TypeScript контролирует, получаете ли вы их текст. Они независимы: вы можете установить effort: "low" с включенным extended thinking или effort: "max" без него.
Используйте более низкие усилия для агентов, выполняющих простые, хорошо определенные задачи (такие как список файлов или запуск одного grep), чтобы снизить стоимость и задержку. Установите effort в опциях верхнего уровня query() для всей сессии или для каждого подагента с полем effort на AgentDefinition, чтобы переопределить уровень сессии.
Режим разрешения
Опция режима разрешения (permission_mode в Python, permissionMode в TypeScript) контролирует, просит ли агент одобрения перед использованием инструментов:
| Режим | Поведение | Вариант использования |
|---|---|---|
"default" |
Вызовы инструментов, которые требуют одобрения и не охватываются правилами разрешения, запускают ваш обратный вызов canUseTool; отсутствие обратного вызова означает отклонение |
Интерактивные приложения с пользовательским обратным вызовом одобрения |
"acceptEdits" |
Автоматически одобряет редактирование файлов и общие команды файловой системы (mkdir, touch, mv, cp и т. д.); другие команды Bash следуют правилам по умолчанию |
Вы доверяете редактированиям Claude и хотите более быстрой итерации, например во время прототипирования или при работе в изолированном каталоге |
"plan" |
Claude исследует и планирует без редактирования ваших исходных файлов; редактирование файлов никогда не одобряется автоматически и запрашивается через ваш обратный вызов canUseTool |
Вы хотите, чтобы Claude предложил изменения без их выполнения, например во время проверки кода или когда вам нужно одобрить изменения перед их внесением |
"dontAsk" |
Никогда не подсказывает. Инструменты, предварительно одобренные правилами разрешения, работают, и также работают вызовы, которые не требуют одобрения в режиме default, такие как чтение файлов в ваших рабочих каталогах; каждый вызов, который иначе подсказал бы, отклоняется. AskUserQuestion, инструменты соединителя установленные вашей организацией на ask и инструменты MCP, отмеченные requiresUserInteraction, отклоняются даже если вы их разрешили |
Вы хотите фиксированную, явную поверхность инструментов для безголового агента и предпочитаете жесткое отклонение молчаливой опоре на отсутствие canUseTool |
"auto" |
Использует классификатор модели для одобрения или отклонения подсказок разрешения. См. Режим Auto для доступности и поведения | Автономные агенты, которые все еще хотят гарантии безопасности при использовании инструментов |
"bypassPermissions" |
Запускает все разрешенные инструменты без запроса, кроме инструментов, совпадающих с явным правилом ask, инструментов соединителя установленных вашей организацией на ask и инструментов, требующих взаимодействия с пользователем. Гарантии безопасности обмена сообщениями между сессиями все еще применяются. См. Как оцениваются разрешения для порядка приоритета. В TypeScript SDK также требует allowDangerouslySkipPermissions: true в options. Не может использоваться при запуске от root на Unix. Используйте только в изолированных окружениях, где действия агента не могут повлиять на системы, которые вам важны |
CI, контейнеры или другие изолированные окружения |
Для интерактивных приложений используйте "default" с обратным вызовом одобрения инструмента для отображения подсказок одобрения. Для автономных агентов на машине разработки используйте "acceptEdits", чтобы автоматически одобрить редактирование файлов и общие команды файловой системы (mkdir, touch, mv, cp и т. д.), при этом все еще ограничивая другие команды Bash правилами разрешения. Зарезервируйте "bypassPermissions" для CI, контейнеров или других изолированных окружений. См. Разрешения для полных деталей.
Модель
Если вы не установите model, SDK использует значение по умолчанию Claude Code, которое зависит от вашего метода аутентификации и подписки. Установите его явно (например, model="claude-sonnet-5"), чтобы закрепить определенную модель или использовать меньшую модель для более быстрых и дешевых агентов. См. models для доступных ID.
Контекстное окно
Контекстное окно — это общее количество информации, доступной Claude во время сессии. Оно не сбрасывается между ходами в пределах сессии. Все накапливается: системный запрос, определения инструментов, история разговора, входные данные инструментов и выходные данные инструментов. Содержимое, которое остается неизменным на протяжении ходов (системный запрос, определения инструментов, CLAUDE.md), автоматически кэшируется в запросе, что снижает стоимость и задержку для повторяющихся префиксов. Для информации о том, как пользовательский системный запрос или текст append влияет на повторное использование кэша между сессиями, см. Изменение системных запросов.
Что потребляет контекст
Вот как каждый компонент влияет на контекст в SDK:
| Источник | Когда он загружается | Влияние |
|---|---|---|
| Системный запрос | Каждый запрос | Небольшая фиксированная стоимость, всегда присутствует |
| CLAUDE.md файлы | Начало сессии, через settingSources |
Полное содержимое в каждом запросе (но кэшировано в запросе, поэтому только первый запрос платит полную стоимость) |
| Определения инструментов | Каждый запрос; схемы MCP отложены по умолчанию | Встроенные схемы инструментов загружаются в каждом запросе. Поиск инструментов отложит схемы инструментов MCP по умолчанию, возвращаясь к предварительной загрузке на неподдерживаемых моделях и определенных платформах. См. Настройка поиска инструментов для полной матрицы |
| История разговора | Накапливается на протяжении ходов | Растет с каждым ходом: запросы, ответы, входные данные инструментов, выходные данные инструментов |
| Описания skills | Начало сессии, через источники настроек | Короткие резюме; полное содержимое загружается только при вызове |
Большие выходные данные инструментов потребляют значительный контекст. Чтение большого файла или запуск команды с подробным выводом может использовать тысячи токенов в одном ходе. Контекст накапливается на протяжении ходов, поэтому более длительные сессии с множеством вызовов инструментов накапливают значительно больше контекста, чем короткие.
Автоматическое компактирование
Когда контекстное окно приближается к своему лимиту, SDK автоматически компактирует разговор: он суммирует более старую историю, чтобы освободить место, сохраняя ваши самые последние обмены и ключевые решения нетронутыми. SDK выдает сообщение с type: "system" и subtype: "compact_boundary" в потоке, когда это происходит (в Python это SystemMessage; в TypeScript это отдельный тип SDKCompactBoundaryMessage).
Компактирование заменяет более старые сообщения резюме, поэтому конкретные инструкции с начала разговора могут не сохраниться. Постоянные правила должны находиться в CLAUDE.md (загружаемые через settingSources), а не в начальном запросе, потому что содержимое CLAUDE.md повторно вводится в каждом запросе.
Вы можете настроить поведение компактирования несколькими способами:
- Инструкции по суммированию в CLAUDE.md: Компактор читает ваш CLAUDE.md как любой другой контекст, поэтому вы можете включить раздел, рассказывающий ему, что сохранить при суммировании. Компактор совпадает по намерению, поэтому заголовок раздела свободной формы.
- Hook
PreCompact: Запустите пользовательскую логику перед компактированием, например для архивирования полной транскрипции. Hook получает полеtrigger(manualилиauto). См. hooks. - Ручное компактирование: Отправьте
/compactкак строку запроса для запуска компактирования по требованию. Команды, отправленные таким образом, — это обычные входные данные SDK. См. dispatch commands by name.
Пример: Инструкции по суммированию в CLAUDE.md
Добавьте раздел в CLAUDE.md вашего проекта, рассказывающий компактору, что сохранить. Имя заголовка не является специальным; используйте любой четкий ярлык.
# Summary instructions
When summarizing this conversation, always preserve:
- The current task objective and acceptance criteria
- File paths that have been read or modified
- Test results and error messages
- Decisions made and the reasoning behind them
Держите контекст эффективным
Несколько стратегий для долгоживущих агентов:
- Используйте подагентов для подзадач. Каждый подагент начинает со свежего разговора (без предыдущей истории сообщений, хотя он загружает свой собственный системный запрос и контекст уровня проекта, такой как CLAUDE.md). Он не видит ходы родителя, и только его финальный ответ возвращается родителю как результат инструмента. Контекст основного агента растет на эту резюме, а не на полную транскрипцию подзадачи. См. Что наследуют подагенты для деталей.
- Будьте избирательны с инструментами. Каждое определение инструмента занимает место контекста. Используйте поле
toolsнаAgentDefinitionдля ограничения подагентов минимальным набором, который им нужен. - Следите за стоимостью MCP сервера. MCP tool search отложит схемы инструментов MCP по умолчанию и загружает их по требованию. Когда поиск инструментов отключен или вернулся к предварительной загрузке, каждый MCP сервер добавляет все свои схемы инструментов в каждый запрос, поэтому несколько серверов с множеством инструментов могут потребить значительный контекст перед тем, как агент выполнит какую-либо работу. См. Configure tool search для конфигураций, где применяется fallback.
- Используйте более низкие усилия для обычных задач. Установите effort на
"low"для агентов, которым нужно только читать файлы или список каталогов. Это снижает использование токенов и стоимость.
Для подробного разбора стоимости контекста для каждой функции см. Понять стоимость контекста.
Сессии и непрерывность
Каждое взаимодействие с SDK создает или продолжает сессию. Захватите ID сессии из ResultMessage.session_id (доступно в обоих SDK) для возобновления позже. TypeScript SDK также выставляет его как прямое поле на инициализирующем SystemMessage; в Python он вложен в SystemMessage.data.
Когда вы возобновляете, полный контекст из предыдущих ходов восстанавливается: файлы, которые были прочитаны, анализ, который был выполнен, и действия, которые были предприняты. Вы также можете разветвить сессию, чтобы ветвиться в другой подход без изменения оригинала.
См. Управление сессией для полного руководства по возобновлению, продолжению и разветвлению паттернов. Для возобновления сессий в контейнерах без состояния или бессерверных хостах передайте адаптер session_store / sessionStore, чтобы SDK зеркалировал стенограммы на ваш собственный бэкенд и другой хост мог их возобновить. Подпроцесс Claude Code по-прежнему сначала записывает на локальный диск. См. Архитектура двойной записи для того, какая копия пережидает свежую сессию в сравнении с запуском, возобновленным из хранилища, и как сохранить локальную копию эфемерной.
В Python ClaudeSDKClient автоматически обрабатывает ID сессий на протяжении нескольких вызовов. См. справку Python SDK для деталей.
Обработать результат
Когда цикл заканчивается, ResultMessage говорит вам, что произошло, и дает вам выход. Поле subtype (доступно в обоих SDK) — это основной способ проверить состояние завершения.
| Подтип результата | Что произошло | Поле result доступно? |
|---|---|---|
success |
Claude нормально завершил задачу | Да |
error_max_turns |
Достигнут лимит maxTurns перед завершением |
Нет |
error_max_budget_usd |
Достигнут лимит maxBudgetUsd перед завершением |
Нет |
error_during_execution |
Ошибка прервала цикл (например, отказ API или отмененный запрос) | Нет |
error_max_structured_output_retries |
Валидация структурированного выхода не прошла после настроенного лимита повторов | Нет |
Поле result содержит финальный текстовый выход и присутствует только в варианте success, поэтому всегда проверяйте подтип перед его чтением.
Все подтипы результатов содержат total_cost_usd, usage, num_turns и session_id, поэтому вы можете отслеживать стоимость и возобновлять даже после ошибок. Есть две вещи, на которые нужно обратить внимание:
- После сбоя сеанса финальный результат — это
error_during_execution, чьи поля стоимости могут быть обнулены и чейstop_reasonравенnull, и процесс завершается после его выдачи. См. Восстановление итогов после сбоя сеанса. - В Python
total_cost_usd,usageиmodel_usageтипизированы как опциональные, поэтому проверьте, что они не равныNoneперед их чтением.
Поле usage охватывает только основной цикл агента. Используйте modelUsage или model_usage в Python для полного учета токенов и стоимости дерева. См. Отслеживание стоимости и использования для деталей по интерпретации полей usage.
Когда запрос заканчивается на результате ошибки:
- Одиночный вызов
query()выдает финальное сообщение результата, затем вызывает ошибку, которая включает текст отказа, такой какReached maximum number of turns. Вызов ошибки намеренный. Оберните цикл в блок try, если вашему коду нужно продолжить работу после него. Базовый процесс Claude Code также завершается с ненулевым кодом. - Сеанс потоковой передачи входных данных остается активным, и вы можете продолжать отправлять сообщения, кроме случаев после сбоя сеанса, который выдает финальный результат
error_during_executionи завершает процесс.
Результат также включает поле stop_reason (string | null в TypeScript, str | None в Python), указывающее, почему модель остановила генерацию на своем финальном ходе. Общие значения — end_turn (модель закончила нормально), max_tokens (достигнут лимит выходных токенов) и refusal (модель отклонила запрос). На результатах ошибок, которые произвел цикл, stop_reason содержит значение из последнего ответа помощника перед завершением цикла; результат, который Claude Code синтезирует после сбоя сеанса, содержит null.
Для обнаружения отклонений проверьте stop_reason === "refusal" (TypeScript) или stop_reason == "refusal" (Python). См. SDKResultMessage (TypeScript) или ResultMessage (Python) для полного типа.
Hooks
Hooks — это обратные вызовы, которые срабатывают в определенных точках цикла: перед запуском инструмента, после его возврата, когда агент заканчивает, и так далее. Некоторые часто используемые hooks:
| Hook | Когда он срабатывает | Общие использования |
|---|---|---|
PreToolUse |
Перед выполнением инструмента | Валидировать входные данные, блокировать опасные команды |
PostToolUse |
После возврата инструмента | Аудировать выходные данные, запускать побочные эффекты |
UserPromptSubmit |
Когда запрос отправляется | Вводить дополнительный контекст в запросы |
Stop |
Когда агент заканчивает | Валидировать результат, сохранять состояние сессии |
SubagentStart / SubagentStop |
Когда подагент порождается или завершается | Отслеживать и агрегировать результаты параллельных задач |
PreCompact |
Перед компактированием контекста | Архивировать полную транскрипцию перед суммированием |
Hooks работают в процессе вашего приложения, а не внутри контекстного окна агента, поэтому они не потребляют контекст. Hooks также могут короткозамкнуть цикл: hook PreToolUse, который отклоняет вызов инструмента, предотвращает его выполнение, и Claude получает сообщение об отклонении вместо этого.
Оба SDK поддерживают все события выше. TypeScript SDK включает дополнительные события, которые Python еще не поддерживает. См. Контролировать выполнение с помощью hooks для полного списка событий, доступности для каждого SDK и полного API обратного вызова.
Собрать все вместе
Этот пример объединяет ключевые концепции с этой страницы в одного агента, который исправляет неудачные тесты. Он конфигурирует агента с разрешенными инструментами (автоматически одобренными, поэтому агент работает автономно), настройками проекта и ограничениями безопасности на ходы и усилия рассуждения. По мере выполнения цикла он захватывает ID сессии для потенциального возобновления, обрабатывает финальный результат и выводит общую стоимость.
Поскольку один вызов query() вызывает исключение после выдачи результата ошибки, цикл обернут в блок try, чтобы скрипт корректно завершился при достижении лимита.
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
async def run_agent():
session_id = None
try:
async for message in query(
prompt="Find and fix the bug causing test failures in the auth module",
options=ClaudeAgentOptions(
allowed_tools=[
"Read",
"Edit",
"Bash",
"Glob",
"Grep",
], # Listing tools here auto-approves them (no prompting)
setting_sources=[
"project"
], # Load CLAUDE.md, skills, hooks from current directory
max_turns=30, # Prevent runaway sessions
effort="high", # Thorough reasoning for complex debugging
),
):
# Handle the final result
if isinstance(message, ResultMessage):
session_id = message.session_id # Save for potential resumption
if message.subtype == "success":
print(f"Done: {message.result}")
elif message.subtype == "error_max_turns":
# Agent ran out of turns. Resume with a higher limit.
print(f"Hit turn limit. Resume session {session_id} to continue.")
elif message.subtype == "error_max_budget_usd":
print("Hit budget limit.")
else:
print(f"Stopped: {message.subtype}")
if message.total_cost_usd is not None:
print(f"Cost: ${message.total_cost_usd:.4f}")
except Exception as error:
# A single-shot query() raises after yielding an error result. If the
# failure was an error result, the error subtype branches above have
# already run; connection or process failures yield no result message.
print(f"Session ended with an error: {error}")
asyncio.run(run_agent())
import { query } from "@anthropic-ai/claude-agent-sdk";
let sessionId: string | undefined;
try {
for await (const message of query({
prompt: "Find and fix the bug causing test failures in the auth module",
options: {
allowedTools: ["Read", "Edit", "Bash", "Glob", "Grep"], // Listing tools here auto-approves them (no prompting)
settingSources: ["project"], // Load CLAUDE.md, skills, hooks from current directory
maxTurns: 30, // Prevent runaway sessions
effort: "high" // Thorough reasoning for complex debugging
}
})) {
// Save the session ID to resume later if needed
if (message.type === "system" && message.subtype === "init") {
sessionId = message.session_id;
}
// Handle the final result
if (message.type === "result") {
if (message.subtype === "success") {
console.log(`Done: ${message.result}`);
} else if (message.subtype === "error_max_turns") {
// Agent ran out of turns. Resume with a higher limit.
console.log(`Hit turn limit. Resume session ${sessionId} to continue.`);
} else if (message.subtype === "error_max_budget_usd") {
console.log("Hit budget limit.");
} else {
console.log(`Stopped: ${message.subtype}`);
}
console.log(`Cost: $${message.total_cost_usd.toFixed(4)}`);
}
}
} catch (error) {
// A single-shot query() throws after yielding an error result. If the
// failure was an error result, the error subtype branches above have
// already run; connection or process failures yield no result message.
console.log(`Session ended with an error: ${error}`);
}
Когда агент успешно завершает работу, пример выводит строку Done: с резюме исправления агента, а затем строку вроде Cost: $0.0312.
Следующие шаги
Теперь, когда вы понимаете цикл, вот куда идти в зависимости от того, что вы создаете:
- Еще не запустили агента? Начните с quickstart, чтобы установить SDK и увидеть полный пример, работающий от начала до конца.
- Готовы подключиться к вашему проекту? Загрузите CLAUDE.md, skills и hooks файловой системы, чтобы агент автоматически следовал соглашениям вашего проекта.
- Создаете интерактивный UI? Включите потоковую передачу, чтобы показать живой текст и вызовы инструментов по мере выполнения цикла.
- Нужен более плотный контроль над тем, что может делать агент? Заблокируйте доступ к инструментам с помощью разрешений и используйте hooks для аудита, блокировки или преобразования вызовов инструментов перед их выполнением.
- Запускаете долгие или дорогие задачи? Перенесите изолированную работу на подагентов, чтобы держать ваш основной контекст стройным.
- Развертываете как сервис? См. Hosting the Agent SDK для руководства по контейнерам и бессерверным решениям, и Session storage для сохранения сессий в вашем собственном бэкенде.
Для более широкой концептуальной картины цикла агента (не специфичной для SDK) см. Как работает Claude Code. Для практического руководства по проектированию циклов в Claude Code, от циклов на основе ходов к циклам на основе целей и проактивным циклам, см. Loop engineering: getting started with loops в блоге.