SpyBara
Go Premium

agent-sdk/agent-loop.md 2026-11-08 22:58 UTC to 2026-11-09 23:02 UTC

No changes for this document in this history range.

2026
Tue 3 23:58 Wed 4 23:59 Fri 6 23:01 Wed 11 22:59

Как работает цикл агента

Поймите жизненный цикл сообщений, выполнение инструментов, контекстное окно и архитектуру, которые питают ваших агентов SDK.

Agent SDK позволяет встроить автономный цикл агента Claude Code в ваши собственные приложения. SDK — это отдельный пакет, который дает вам программный контроль над инструментами, разрешениями, ограничениями затрат и выводом.

Оба SDK (TypeScript и Python) включают собственный бинарный файл Claude Code, поэтому большинству установок не требуется отдельная установка Claude Code. Примечание об установке см. в quickstart.

Когда вы запускаете агента, SDK запускает тот же цикл выполнения, который питает Claude Code: Claude оценивает ваш запрос, вызывает инструменты для выполнения действий, получает результаты и повторяет до завершения задачи. На этой странице объясняется, что происходит внутри этого цикла, чтобы вы могли эффективно создавать, отлаживать и оптимизировать своих агентов.

Цикл с первого взгляда

Каждая сессия агента следует одному и тому же циклу:

Диаграмма цикла агента: ваш запрос входит в цикл агента, где Claude оценивает и либо запрашивает вызовы инструментов, результаты которых возвращаются в следующую оценку, либо возвращает финальный ответ

  1. Получить запрос. Claude получает ваш запрос вместе с системным запросом, определениями инструментов и историей разговора. SDK выдает SystemMessage с подтипом "init", содержащий метаданные сессии.
  2. Оценить и ответить. Claude оценивает текущее состояние и определяет, как действовать дальше. Он может ответить текстом, запросить один или несколько вызовов инструментов или оба варианта. SDK выдает один или несколько объектов AssistantMessage, по одному для каждого блока содержимого, такого как текстовый блок или запрос вызова инструмента.
  3. Выполнить инструменты. SDK запускает каждый запрошенный инструмент и собирает результаты. Каждый набор результатов инструментов возвращается Claude для следующего решения. Вы можете использовать hooks для перехвата, изменения или блокировки вызовов инструментов перед их выполнением.
  4. Повторить. Шаги 2 и 3 повторяются как цикл. Claude продолжает вызывать инструменты и обрабатывать результаты до тех пор, пока не выдаст ответ без вызовов инструментов.
  5. Вернуть результат. SDK выдает финальное AssistantMessage с текстовым ответом (без вызовов инструментов), за которым следует ResultMessage с финальным текстом, использованием токенов, стоимостью и ID сессии.

Быстрый вопрос, например «какие файлы здесь?», может занять два или три хода: один или два с вызовом Glob, затем один с ответом, содержащим результаты. Сложная задача, например «выполни рефакторинг модуля аутентификации и обнови тесты», может связать десятки вызовов инструментов на протяжении многих ходов, поскольку Claude корректирует свои действия после каждого результата.

Ходы и сообщения

Ход — это один проход цикла: Claude выдает выход, и если он включает вызовы инструментов, SDK выполняет их, а результаты автоматически возвращаются Claude. Это происходит без возврата управления вашему коду. Ходы продолжаются до тех пор, пока Claude не выдаст выход без вызовов инструментов, после чего цикл заканчивается и доставляется финальный результат.

Рассмотрим, как может выглядеть полная сессия для запроса «Исправить неудачные тесты в auth.ts».

Сначала SDK отправляет ваш запрос Claude и выдает SystemMessage с метаданными сессии. Затем начинается цикл:

  1. Ход 1: Claude вызывает Bash для запуска npm test. SDK выдает AssistantMessage с вызовом инструмента, выполняет команду, затем выдает UserMessage с выводом (три ошибки).
  2. Ход 2: Claude вызывает Read на auth.ts и auth.test.ts. SDK выдает AssistantMessage для каждого вызова и возвращает содержимое файлов.
  3. Ход 3: Claude вызывает Edit для исправления auth.ts, затем вызывает Bash для повторного запуска npm test. Все три теста проходят. SDK выдает AssistantMessage для каждого вызова.
  4. Финальный ход: Claude выдает текстовый ответ без вызовов инструментов: «Исправлена ошибка аутентификации, все три теста теперь проходят.» SDK выдает финальное AssistantMessage с этим текстом, затем ResultMessage с тем же текстом плюс стоимость и использование.

Это было четыре хода: три с вызовами инструментов, один финальный текстовый ответ.

Вы можете ограничить цикл с помощью max_turns / maxTurns. Считайте каждый ход с вызовами инструментов плюс один для финального текстового ответа. Без этого дополнительного хода выполнение завершится сообщением ResultMessage с подтипом error_max_turns и без финального ответа. Например, max_turns=2 в цикле выше остановился бы перед шагом редактирования. Вы также можете использовать max_budget_usd / maxBudgetUsd для ограничения ходов на основе порога расходов.

Без ограничений цикл работает до тех пор, пока Claude не закончит самостоятельно, что хорошо для хорошо определенных задач, но может работать долго на открытых запросах («улучшить этот кодовую базу»). Установка бюджета — хороший стандарт для производственных агентов. См. Ходы и бюджет ниже для справки по опциям.

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

По мере выполнения цикла SDK выдает поток сообщений. Каждое сообщение имеет тип, который говорит вам, на каком этапе цикла оно пришло. Пять основных типов:

  • SystemMessage: события жизненного цикла сессии. Поле subtype их различает:

    • "init": метаданные сессии для запуска. Когда hook SessionStart или 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.

[accordion] Пример: Проверить типы сообщений и обработать результаты

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 только когда вы согласитесь.

Помимо встроенных инструментов, вы можете:

Разрешения инструментов

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 не добавляет его в последний вызов модели этого хода. Он начинает для сообщения новый ход, и счетчик максимального количества ходов для этого хода начинается заново. Общая сумма бюджета продолжает накапливаться между сообщениями, и как только расходы достигают maxBudgetUsd, последующие сообщения в том же диалоге завершаются результатом error_max_budget_usd. Команда /clear сбрасывает бюджет.

Запас бюджета

Claude Code сравнивает расходы с лимитом max_budget_usd / maxBudgetUsd после получения ответов модели, поскольку стоимость каждого ответа вычисляется по данным об использовании токенов, которые API возвращает вместе с ним. Ответ, при котором достигается лимит, все равно завершается и учитывается в total_cost_usd. Поэтому расходы могут превысить лимит не более чем на стоимость этого одного ответа плюс все, что потратят субагенты, еще работающие в этот момент, до своей остановки. Учитывайте этот запас при установке лимита.

Уровень effort

Параметр effort определяет, насколько глубоко рассуждает Claude. Более низкие уровни effort расходуют меньше токенов за ход и снижают стоимость. Не все модели поддерживают параметр effort. Список поддерживающих его моделей см. в разделе Effort.

Уровень Поведение Подходит для
"low" Минимальные рассуждения, быстрые ответы Поиск файлов, вывод содержимого каталогов
"medium" Сбалансированные рассуждения Рутинные правки, стандартные задачи
"high" Тщательный анализ Рефакторинг, отладка
"xhigh" Расширенная глубина рассуждений Задачи программирования и агентные задачи на моделях, которые это поддерживают
"max" Максимальная глубина рассуждений Многошаговые задачи, требующие глубокого анализа

Если вы не задаете effort, Claude Code определяет уровень effort самостоятельно в порядке, описанном в разделе Настройка уровня effort.

[!NOTE]

effort позволяет обменять задержку и стоимость токенов на глубину рассуждений в рамках каждого ответа. Расширенное мышление — это отдельная функция, которая создает блоки thinking в выводе, а поле display в ThinkingConfig для Python или TypeScript определяет, получаете ли вы их текст. Они независимы: можно задать effort: "low" с включенным расширенным мышлением или effort: "max" без него.

Используйте более низкий уровень effort для агентов, выполняющих простые, четко очерченные задачи (например, вывод списка файлов или запуск одного grep), чтобы снизить стоимость и задержку. Задайте effort в параметрах query() верхнего уровня для всей сессии или для отдельного субагента с помощью поля effort в AgentDefinition, чтобы переопределить уровень сессии.

Режим разрешений

Параметр режима разрешений (permission_mode в Python, permissionMode в TypeScript) определяет, запрашивает ли агент подтверждение перед использованием инструментов:

Режим Поведение Сценарий использования
"default" Вызовы инструментов, которым требуется подтверждение и которые не покрываются разрешающими правилами, вызывают ваш callback canUseTool; при отсутствии callback вызов отклоняется Интерактивные приложения с собственным callback для подтверждения
"acceptEdits" Автоматически подтверждает правки файлов и распространенные команды файловой системы (mkdir, touch, mv, cp и т. д.) внутри ваших рабочих каталогов; остальные команды Bash следуют правилам по умолчанию Вы доверяете правкам Claude и хотите ускорить итерации, например при прототипировании или работе в изолированном каталоге
"plan" Claude исследует и планирует. Правки, вносимые файловыми инструментами Claude, передаются в ваш callback canUseTool, даже если им соответствует разрешающее правило Вы хотите, чтобы Claude сначала составил план, например во время код-ревью или перед крупным изменением
"dontAsk" Никогда не запрашивает подтверждение. Выполняются инструменты, заранее разрешенные правилами разрешений, а также вызовы, которым в режиме default подтверждение не требуется, например чтение файлов внутри ваших рабочих каталогов. Все вызовы, которые в ином случае потребовали бы подтверждения, отклоняются, хотя установленный вами мод все же может подтвердить некоторые из этих вызовов. Некоторые вызовы, например чтение по сетевым путям, отклоняются, даже если вы их разрешили. Список см. в разделе Режим Don't ask Агенты без интерфейса, когда некому подтверждать вызовы
"auto" Использует классификатор на основе модели для проверки действий, таких как shell-команды и сетевые запросы, разрешая или блокируя каждое проверяемое действие. Доступность и порядок принятия решений см. в разделе Авторежим Автономные агенты, которым все же нужны защитные ограничения при использовании инструментов
"bypassPermissions" Выполняет вызовы инструментов без запроса подтверждения, включая вызовы инструментов, которые вы не указали в allowedTools. Некоторые вызовы все равно передаются в ваш callback canUseTool — они перечислены в разделе Режим Bypass permissions. В TypeScript SDK также требуется allowDangerouslySkipPermissions: true в options. Нельзя использовать при запуске от имени root в Unix. Используйте только в изолированных средах, где действия агента не могут повлиять на важные для вас системы CI, контейнеры или другие изолированные среды

Для интерактивных приложений используйте "default" с callback подтверждения инструментов, чтобы показывать запросы подтверждения. Для агентов, которые редактируют файлы на машине разработчика, используйте "acceptEdits". Оставьте "bypassPermissions" для CI, контейнеров или других изолированных сред. Подробнее см. в разделе Разрешения.

Модель

Задайте параметр model, чтобы выбрать модель, которая будет выполнять сессию. Подробнее см. в разделе Выбор модели.

Контекстное окно

Контекстное окно — это общее количество информации, доступной Claude во время сессии. Оно не сбрасывается между ходами в пределах сессии. Все накапливается: системный промпт, определения инструментов, история диалога, входные данные инструментов и выходные данные инструментов. Содержимое, которое остается неизменным на протяжении ходов (системный промпт, определения инструментов, CLAUDE.md), автоматически кэшируется с помощью кэширования промптов, что снижает стоимость и задержку для повторяющихся префиксов. Информацию о том, как пользовательский системный промпт или текст append влияет на повторное использование кэша между сессиями, см. в разделе Изменение системных промптов.

Что потребляет контекст

Вот как каждый компонент влияет на контекст в SDK:

Источник Когда он загружается Влияние
Системный промпт Каждый запрос Небольшая фиксированная стоимость, всегда присутствует
Файлы CLAUDE.md Начало сессии, через settingSources Полное содержимое в каждом запросе (но с кэшированием промптов, поэтому полную стоимость оплачивает только первый запрос)
Определения инструментов Каждый запрос для основных встроенных инструментов, таких как Bash, Read и Edit; по требованию для инструментов MCP и других встроенных инструментов, загрузку которых поиск инструментов по умолчанию откладывает Все схемы загружаются заранее в случаях, описанных в разделе Настройка поиска инструментов
История диалога Накапливается на протяжении ходов Растет с каждым ходом: промпты, ответы, входные данные инструментов, выходные данные инструментов
Описания скиллов Начало сессии, через источники настроек Краткие описания; полное содержимое загружается только при вызове

Большие выходные данные инструментов потребляют значительный объем контекста. Чтение большого файла или запуск команды с подробным выводом может использовать тысячи токенов за один ход. Контекст накапливается на протяжении ходов, поэтому более длительные сессии с множеством вызовов инструментов накапливают значительно больше контекста, чем короткие.

Автоматическое сжатие контекста

Когда контекстное окно приближается к своему лимиту, SDK автоматически сжимает диалог: он кратко резюмирует более старую историю, чтобы освободить место, сохраняя нетронутыми ваши самые последние обмены сообщениями и ключевые решения. Когда это происходит, SDK выдает в поток сообщение с type: "system" и subtype: "compact_boundary" (в Python это SystemMessage; в TypeScript это отдельный тип SDKCompactBoundaryMessage).

Сжатие контекста заменяет более старые сообщения резюме, поэтому конкретные инструкции из начала диалога могут не сохраниться. Постоянные правила следует размещать в CLAUDE.md (загружаемом через settingSources), а не в начальном промпте, потому что содержимое CLAUDE.md повторно добавляется в каждый запрос.

Вы можете настроить поведение сжатия контекста несколькими способами:

  • Инструкции по резюмированию в CLAUDE.md: механизм сжатия читает ваш CLAUDE.md как любой другой контекст, поэтому вы можете добавить раздел, указывающий, что сохранять при резюмировании. Механизм сжатия ориентируется на смысл, поэтому заголовок раздела может быть произвольным.
  • Хук PreCompact: запускайте пользовательскую логику перед сжатием контекста, например для архивирования полного транскрипта. Хук получает поле trigger (manual или auto). См. хуки.
  • Ручное сжатие контекста: отправьте /compact в качестве строки промпта, чтобы запустить сжатие по требованию. Команды, отправленные таким образом, — это обычные входные данные SDK. См. отправка команд по имени.

[accordion] Пример: инструкции по резюмированию в 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

Эффективное использование контекста

Несколько стратегий для долго работающих агентов:

  • Используйте субагентов для подзадач. Субагент возвращает только свой финальный ответ, поэтому контекст основного агента увеличивается на резюме, а не на транскрипт подзадачи.
  • Тщательно выбирайте инструменты. Каждое определение инструмента занимает место в контексте. Используйте поле tools в AgentDefinition, чтобы ограничить субагентов минимальным необходимым набором инструментов.
  • Следите за затратами на MCP-серверы. MCP Tool Search по умолчанию откладывает загрузку схем инструментов MCP и загружает их по требованию. Когда поиск инструментов отключен или переключился на предварительную загрузку, каждый MCP-сервер добавляет все свои схемы инструментов в каждый запрос, поэтому несколько серверов с множеством инструментов могут потребить значительный объем контекста еще до того, как агент выполнит какую-либо работу. Конфигурации, в которых применяется этот резервный вариант, см. в разделе Настройка поиска инструментов.
  • Используйте более низкий уровень effort для рутинных задач. Установите effort в значение "low" для агентов, которым нужно только читать файлы или выводить списки каталогов. Это снижает расход токенов и стоимость.

Подробную разбивку затрат контекста по функциям см. в разделе Понимание затрат контекста.

Сессии и непрерывность

Каждое взаимодействие с SDK создает или продолжает сессию. Захватите ID сессии из ResultMessage.session_id (доступно в обоих SDK) для возобновления позже. TypeScript SDK также выставляет его как прямое поле на инициализирующем SystemMessage; в Python он вложен в SystemMessage.data.

Когда вы возобновляете, полный контекст из предыдущих ходов восстанавливается: файлы, которые были прочитаны, анализ, который был выполнен, и действия, которые были предприняты. Вы также можете разветвить сессию, чтобы ветвиться в другой подход без изменения оригинала.

См. Управление сессией для полного руководства по возобновлению, продолжению и разветвлению паттернов. Для возобновления сессий в контейнерах без состояния или бессерверных хостах передайте адаптер session_store / sessionStore, чтобы SDK зеркалировал стенограммы на ваш собственный бэкенд и другой хост мог их возобновить. Подпроцесс Claude Code по-прежнему сначала записывает на локальный диск. См. Архитектура двойной записи для того, какая копия пережидает свежую сессию в сравнении с запуском, возобновленным из хранилища, и как сохранить локальную копию эфемерной.

[!NOTE]

В Python ClaudeSDKClient автоматически обрабатывает ID сессий на протяжении нескольких вызовов. См. справку Python SDK для деталей.

Обработать результат

Когда цикл заканчивается, ResultMessage говорит вам, что произошло, и дает вам выход. Поле subtype (доступно в обоих SDK) — это основной способ проверить состояние завершения.

Подтип результата Что произошло Поле result доступно?
success Claude нормально завершил задачу Да
error_max_turns Достигнут лимит maxTurns перед завершением Нет
error_max_budget_usd Достигнут лимит maxBudgetUsd перед завершением Нет
error_during_execution Ошибка прервала цикл (например, отмененный запрос) Нет
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.

[!NOTE]

Когда запрос заканчивается на результате ошибки:

  • Одиночный вызов 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 для аудита, блокировки или преобразования вызовов инструментов перед их выполнением.
  • Запускаете долгие или дорогие задачи? Перенесите изолированную работу на подагентов, чтобы держать ваш основной контекст стройным.
  • Развертываете как сервис? См. Размещение Agent SDK для руководства по контейнерам и бессерверным решениям, и Хранилище сессий для сохранения сессий в вашем собственном бэкенде.

Для более широкой концептуальной картины цикла агента (не специфичной для SDK) см. Как работает Claude Code. Для практического руководства по проектированию циклов в Claude Code, от циклов на основе ходов к циклам на основе целей и проактивным циклам, см. Loop engineering: getting started with loops в блоге.