Поток событий сеанса
Отправляйте события, получайте ответы в режиме потоковой передачи, а также прерывайте или перенаправляйте сеанс во время выполнения.
Взаимодействие с Claude Managed Agents основано на событиях. Вы открываете поток, чтобы следить за сеансом, отправляете события, чтобы управлять им, и отвечаете ему, когда он приостанавливается в ожидании ввода.
Типы событий
События передаются в двух направлениях: вы отправляете события агенту, а сеанс отправляет события обратно вам.
- События, которые вы отправляете: события
user.*запускают сеанс и направляют его по мере выполнения. Событияsystem.messageдобавляют контекст системного уровня. - События, которые вы получаете: события сеанса, события интервалов (span events) и события агента сообщают о состоянии сеанса и ходе работы агента.
Строки типов событий следуют соглашению об именовании {domain}.{action}. Полный каталог см. в разделе Типы событий справочника.
Типы событий вебхуков определены отдельно, и некоторые их имена отличаются от имён в потоке. Например, вебхуки используют session.status_idled вместо session.status_idle.
Потоковая передача событий
Получайте события сеанса в режиме «streaming» (потоковая передача), чтобы видеть обновления в реальном времени по мере работы агента. Поток доставляет только события, созданные после его открытия, поэтому открывайте поток до отправки событий, чтобы избежать состояния гонки.
# Сначала откройте поток, затем отправьте сообщение пользователя
with client.beta.sessions.events.stream(session.id) as stream:
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [{"type": "text", "text": "Summarize the repo README"}],
},
],
)
for event in stream:
match event.type:
case "agent.message":
for block in event.content:
if block.type == "text":
print(block.text, end="")
case "session.status_idle":
break
case "session.error":
error_message = event.error.message if event.error else "unknown"
print(f"\n[Error: {error_message}]")
breakСеанс сообщает об ошибках через событие session.error. Его поля описаны в разделе Типы событий.
Текст ответа агента поступает в виде буферизованных событий agent.message, каждое из которых создаётся только после завершения породившего его запроса к модели. Чтобы отображать текст, пока модель ещё генерирует его, см. Предварительный просмотр ответов с помощью дельт событий.
Переподключение без пропуска событий
Чтобы переподключиться к существующему сеансу без пропуска событий, объедините новый поток с историей событий:
- Откройте новый поток.
- Получите полную историю событий, чтобы заполнить набор уже просмотренных идентификаторов событий.
- Читайте живой поток, пропуская события, которые уже были возвращены в списке истории.
with client.beta.sessions.events.stream(session.id) as stream:
# Поток открыт и буферизуется. Получите историю перед чтением живых событий.
history = client.beta.sessions.events.list(session.id)
seen_event_ids = {past_event.id for past_event in history}
# Читаем живые события, пропуская уже увиденные
for event in stream:
if event.type == "event_start" or event.type == "event_delta":
# Превью дельт не включены для этого соединения.
continue
if event.id in seen_event_ids:
continue
seen_event_ids.add(event.id)
match event.type:
case "agent.message":
for block in event.content:
if block.type == "text":
print(block.text, end="")
case "session.status_idle":
breakОтправка событий
Отправьте событие user.message, чтобы начать или продолжить работу агента:
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [
{
"type": "text",
"text": "Analyze the performance of the sort function in utils.py",
},
],
},
],
)Каждое событие в истории сеанса содержит временную метку processed_at, которая устанавливается, когда обработка события завершается. У отправленных вами событий processed_at имеет значение None, пока событие ещё стоит в очереди за более ранними событиями. Исключения — user.define_outcome, user.custom_tool_result и user.tool_result: они обрабатываются при получении и возвращаются с уже заполненным processed_at.
Ответ, когда сеанс переходит в режим ожидания
Событие session.status_idle означает, что агент остановился и ожидает ввода. Его поле stop_reason.type указывает причину:
stop_reason.type | Почему сеанс остановился | Что делать |
|---|---|---|
end_turn | Агент завершил свой ход, или вы его прервали. | Отправьте user.message, когда у вас появится новая работа для агента. |
requires_action | Один или несколько вызовов инструментов требуют вашего ответа, например вызов пользовательского инструмента или запрос подтверждения. | Ответьте на каждый блокирующий вызов инструмента. |
budget_reached | Отслеживаемая прейскурантная стоимость сеанса достигла его бюджета. | Измените или удалите бюджет. |
Никакое отправленное вами событие не возобновляет сеанс, приостановленный из-за достижения бюджета. Работа, приостановленная бюджетом, возобновляется автоматически, когда вы меняете бюджет на значение выше израсходованной прейскурантной стоимости или удаляете его. При возобновлении работы сеанс создаёт событие workflow_run.status_running для каждого запуска рабочего процесса, приостановленного бюджетом. Запуск, приостановленный прерыванием, остаётся приостановленным; см. Возобновление сеанса, достигшего бюджета. События, отмечающие приостановку, и события, которые сеанс по-прежнему принимает, описаны в разделе Когда сеанс достигает бюджета.
Ответ на вызовы инструментов, приостанавливающие сеанс
Сеанс приостанавливается, когда агент вызывает пользовательский инструмент, а также когда вызов инструмента требует вашего подтверждения согласно политике разрешений. Обе приостановки проходят по одной и той же последовательности:
- Сеанс создаёт вызов инструмента в виде события
agent.custom_tool_use,agent.tool_useилиagent.mcp_tool_use. - Сеанс приостанавливается с событием
session.status_idle, у которогоstop_reason.typeравноrequires_action. Идентификаторы блокирующих событий находятся в массивеstop_reason.event_ids. - Для каждого идентификатора блокирующего события отправьте событие
user.custom_tool_resultилиuser.tool_confirmation. Результату пользовательского инструмента не обязательно ждать шага 2. - Когда все блокирующие события разрешены, сеанс возвращается в состояние
running.
В многоагентном сеансе блокирующие события субагента дублируются в основной поток. См. Разрешения инструментов и пользовательские инструменты.
Возврат результата пользовательского инструмента
Событие agent.custom_tool_use содержит имя инструмента и входные данные. Выполните инструмент в своей системе. Затем отправьте событие user.custom_tool_result, передав идентификатор события в параметре custom_tool_use_id вместе с содержимым результата.
Вы можете отправить результат сразу после поступления события agent.custom_tool_use, не дожидаясь session.status_idle. Сеанс всё равно создаст session.status_idle с причиной остановки requires_action для этого вызова, и ваш клиент может его проигнорировать. Повторный результат для того же вызова принимается и ни на что не влияет.
Когда вы переподключаетесь к приостановленному сеансу, stop_reason.event_ids в последнем событии session.status_idle перечисляет вызовы, на которые нужно ответить.
В следующем примере на каждый вызов отвечают по мере его поступления:
with client.beta.sessions.events.stream(session.id) as stream:
for event in stream:
match event.type:
case "agent.custom_tool_use":
# Выполнить инструмент
result = call_tool(event.name, event.input)
# Отправить результат обратно
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.custom_tool_result",
"custom_tool_use_id": event.id,
"content": [{"type": "text", "text": result}],
},
],
)
case "session.status_idle":
if event.stop_reason and event.stop_reason.type == "end_turn":
breakЕсли у агента открыты запуски рабочих процессов, вызов пользовательского инструмента может поступить, пока сеанс остаётся в состоянии running. Событие ожидания requires_action поступает только тогда, когда ни один из потоков сеанса не работает. Не ждите его: отвечайте на каждый вызов, когда поступает его событие agent.custom_tool_use. Как это сделать, показано в примере из раздела Отслеживание запуска.
Подтверждение вызова инструмента
Отправьте событие user.tool_confirmation, передав идентификатор события в параметре tool_use_id. Установите result в значение "allow" или "deny". О том, какие вызовы ожидают подтверждения и как объяснить отказ, см. в разделе Ответ на запросы подтверждения.
В следующем примере одобряются все ожидающие вызовы:
with client.beta.sessions.events.stream(session.id) as stream:
for event in stream:
if event.type == "session.status_idle" and (stop_reason := event.stop_reason):
match stop_reason.type:
case "requires_action":
for event_id in stop_reason.event_ids:
# Одобряем ожидающий вызов инструмента
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.tool_confirmation",
"tool_use_id": event_id,
"result": "allow",
},
],
)
case "end_turn":
breakПредыдущий пример одобряет каждый вызов после того, как сеанс переходит в режим ожидания. Если у агента открыты запуски рабочих процессов, вызов инструмента может ожидать вашего подтверждения, пока сеанс остаётся в состоянии running. Не ждите события ожидания: когда поступает событие agent.tool_use или agent.mcp_tool_use, у которого evaluated_permission равно ask, ответьте на него. Пример из раздела Отслеживание запуска отвечает таким образом на вызовы пользовательских инструментов, а во введении к нему описано, как добавить подтверждения.
Возобновление сеанса в режиме ожидания
Сеансы сохраняются между взаимодействиями. Чтобы возобновить сеанс, отправьте ему событие user.message как обычно:
# Возобновляем ранее созданную сессию, отправив ей новое событие user.message.
# В продакшене передавайте сохранённый ID сессии, которую нужно возобновить.
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [
{
"type": "text",
"text": "Now run the tests against the changes you made earlier.",
},
],
},
],
)История разговора сохраняется, если сеанс не был явно удалён. Когда сеанс переходит в режим ожидания, для его песочницы создаётся контрольная точка. Контрольная точка сохраняет полное состояние песочницы, включая файловую систему, установленные пакеты и все файлы, созданные агентом.
Прерывание агента
Отправьте событие user.interrupt, чтобы остановить агента во время выполнения, а затем отправьте событие user.message, чтобы перенаправить его:
# Агент в данный момент анализирует файл...
# Прерываем с новым направлением:
client.beta.sessions.events.send(
session.id,
events=[
{"type": "user.interrupt"},
{
"type": "user.message",
"content": [
{
"type": "text",
"text": "Instead, focus on fixing the bug in line 42.",
},
],
},
],
)Вызов возвращается сразу после постановки событий в очередь. Затем прерывание вступает в силу в следующем порядке:
- Агент применяет прерывание. До этого момента
processed_atпрерывания остаётсяNone, а сеанс остаётся в состоянииrunning. Генерируемый ответ модели останавливается немедленно, но применение прерывания может занять больше времени, пока выполняются вызовы инструментов. - Событие
user.interruptпоявляется в потоке, и прерванный ход завершается событиемsession.status_idle. - Агент начинает следующий ход с
user.message, которое вы отправили после прерывания.
Значение stop_reason.type у события ожидания — end_turn, то же, что и у хода, завершившегося самостоятельно. Если открыты запуски рабочих процессов, прерывание не завершает ни один из них. Выполняющийся запуск может удерживать сеанс в состоянии running, поэтому событие session.status_idle на шаге 2 может не поступить. См. Прерывание сеанса с открытыми запусками.
Получение списка прошлых событий
Получите полную историю событий сеанса:
events = client.beta.sessions.events.list(session.id)
for event in events.data:
print(f"[{event.type}] {event.processed_at}")Передайте фильтр types, чтобы получить только определённые типы событий:
events = client.beta.sessions.events.list(
session.id,
types=["agent.tool_use", "agent.tool_result"],
)
for event in events.data:
print(f"[{event.type}] {event.processed_at}")Отправка системных сообщений
На поддерживаемой модели отправьте событие system.message, чтобы предоставить агенту привилегированный контекст системного уровня. Контекст применяется к сопутствующему ходу и ко всем последующим ходам. Используйте его, когда агенту нужны обновлённые указания системного уровня в середине сеанса, например другая роль, пересмотренные ограничения или контекст, полученный во время выполнения.
Поле content события принимает от 1 до 1000 текстовых элементов. Содержимое добавляется к системному контексту сеанса как ход role: "system". Оно не заменяет «system prompt» (системная подсказка) верхнего уровня, которую задаёт поле system в определении агента.
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "system.message",
"content": [
{
"type": "text",
"text": "The user's current timezone is America/New_York.",
},
],
},
],
)Поддерживаемые модели
system.message поддерживается следующими моделями:
- Claude Fable 5.1
- Claude Mythos 5.1
- Claude Fable 5
- Claude Mythos 5
- Claude Opus 5.5
- Claude Opus 5
- Claude Opus 4.8
- Claude Sonnet 5.5
- Claude Haiku 5.5
Если основная модель агента не поддерживает внедрение системного контекста в середине разговора, событие отклоняется с ошибкой валидации model_does_not_support_mid_conversation_system. Модели субагентов не проверяются, поскольку system.message попадает только в основной поток.
Системные сообщения при ожидающем вызове инструмента
Пока сеанс находится в режиме ожидания с причиной остановки requires_action, system.message должно следовать за событием результата инструмента в том же запросе. Если отправить его отдельно или вместе с user.message, оно будет отклоняться, пока ожидающие события инструментов не будут разрешены.
Следующие шаги
Отображайте текст ответа агента, пока модель ещё генерирует его.
Проверяйте сеанс в Claude Console и просматривайте использование токенов и прейскурантную стоимость.
Получайте уведомления о важных событиях без опроса.
Найдите любой тип события, который сеанс может отправить или получить.
Was this page helpful?