Гайд · TNWS AI
Как отменить streaming run в OpenAI Agents SDK: immediate и after_turn
Сравниваем cancel() и cancel(mode="after_turn"), продолжаем читать stream_events до завершения и проверяем side effects текущего turn.
Задача и критерий готовности
Задача — остановить streaming run немедленно либо корректно после текущего turn, не бросая event stream в незавершённом состоянии. Результат считается готовым только при машинной проверке состояния session, RunState, interruption или event stream. Красивый ответ агента не заменяет доказательство.
Методы и поведение сверены 12 сентября 2026 года по официальной документации OpenAI Agents SDK. В статье нет выдуманных цен, квот и метрик.
Подтверждённый контракт
cancel()по умолчанию использует режим immediate.- Immediate останавливает сразу, отменяет tasks и очищает queues.
cancel(mode="after_turn")завершает текущий turn: LLM response, pending tool calls, session state и usage.- After_turn останавливает до начала следующего turn.
- После cancel нужно продолжать потреблять
stream_events()до завершения cancellation.
Каждый пункт проверяется отдельно. Не объединяйте доступность backend, корректность истории и качество ответа в один флаг success: это независимые слои.
Что подготовить
- отдельную тестовую базу, Redis database или временный файл;
- уникальный session_id, не совпадающий с ID реального пользователя;
- fake tool и provider stub для контроля вызовов;
- переменные окружения для ключей и строк подключения;
- журнал безопасных агрегатов и версий без содержимого переписки.
Прежде чем запускать код, определите владельца соединения и cleanup. Для hosted storage проверьте, где фактически лежат данные. Для durable state считайте payload чувствительным: он включает app context и runtime metadata.
Пошаговая настройка
- Запустите run_streamed и начните потреблять stream_events.
- При сигнале пользователя выберите immediate или after_turn осознанно.
- После вызова cancel не делайте break; дочитайте async iterator.
- С fake tool сравните: immediate не обещает завершить текущие effects, after_turn исполняет pending tool calls текущего turn.
После каждого шага записывайте наблюдаемый признак: число items, конкретный exception, наличие interruption, счётчик tool или факт завершения async iterator. Комментарий в коде не является проверкой.
Копируемый пример
import asyncio
from agents import Agent, Runner
async def main():
agent=Agent(name="worker",instructions="Выполни задачу по шагам.")
result=Runner.run_streamed(agent,"Тестовая задача T-781")
async for event in result.stream_events():
if should_stop(event):
result.cancel(mode="after_turn")
# Не break: продолжаем читать события до завершения отмены.
assert result.is_complete
asyncio.run(main())
Запускайте пример в отдельном virtualenv. Все ключи и URL берите из окружения; тестовые localhost-адреса не превращайте в production-конфигурацию автоматически. Заполнители paused, original_agent и fake counters должны быть определены вашим воспроизводимым fixture.
Реалистичный вход
Во время test stream приходит пользовательский stop-сигнал после начала текущего turn.
Ожидаемый результат
After_turn корректно завершает turn и session accounting; immediate останавливает максимально быстро. Оба потока дочитываются.
Перенесите ожидание в assert. Для недетерминированного текста проверяйте сохранённый факт через model stub либо напрямую session items. Для approval проверяйте и interruptions, и execution counter.
Негативный тест
Вызовите cancel и сразу break: тест должен обнаружить незавершённую cancellation либо некорректное состояние.
Негативная проверка меняет одно условие. Ошибка подключения не равна пустой истории, новый run не равен resume, другой session_id не является потерей данных, а отсутствие второй паузы допустимо только при подтверждённом sticky decision.
Готовый prompt для ревью
Проверь конфигурацию сценария «Как отменить streaming run в OpenAI Agents SDK: immediate и after_turn». Для каждого факта найди исполняемое доказательство. Проверь ownership соединений, cleanup, секреты, session_id, число model/tool вызовов и негативный тест. Верни таблицу PASS/FAIL; если доказательства нет, ставь FAIL.
Prompt используйте после приложения кода и очищенного лога. Он не заменяет исполнение: языковая модель может назвать комментарий гарантией или пропустить неверный cleanup.
Независимая проверка
Составьте три сценария: штатный, ошибочный и пограничный. Для каждого укажите исходное состояние, действие, ожидаемый side effect и последующее чтение. Повторите тест из второго процесса, если backend заявлен как shared.
Считайте отдельно model calls, tool executions, session writes и approval interruptions. Один счётчик не описывает весь run. Для async cleanup добавьте fixture, который проверяет закрытие даже после исключения.
В CI сохраняйте версии пакета, exit code и агрегаты. Не сохраняйте encryption key, DATABASE_URL, Redis URL с паролем, сериализованный RunState или полный dialog в открытых artifacts.
Частые ошибки
Неправильное владение ресурсом
from_url может создать клиент или engine, который нужно закрыть. Если ресурс передан извне, его жизненный цикл может принадлежать приложению. Зафиксируйте это в одном месте.
Пустое значение считают успехом
Пустая история может означать новый ID, истёкший TTL, ошибку ключа или отсутствие записи. Тест должен различать причины и не возвращать универсальное «готово».
Approval смешивают с авторизацией
Решение оператора разрешает конкретный workflow SDK, но backend всё равно обязан проверить права пользователя и допустимость операции.
Cleanup выполняется только при успехе
Соединения закрывают в finally или lifecycle hook. Отдельно моделируйте исключение Runner и убеждайтесь, что dispose/close всё равно выполнен.
Чек-лист финальной проверки
- Уникальный session_id не содержит PII.
- Версия SDK зафиксирована.
- Названия методов сверены 12 сентября 2026 года.
- Секреты приходят только из окружения.
- Есть штатный и негативный assert.
- Model calls и tool executions считаются отдельно.
- Cleanup работает после исключения.
- Resume использует RunState, а не новый prompt.
- Serialized state защищён как чувствительные данные.
- Старые items не удаляются случайно retrieval-limitом.
Ограничения
Гайд проверяет технический контракт, но не соответствие нормативным требованиям, стоимость backend, качество модели и производительность. TTL, limit и схема retention выбираются по политике проекта; нельзя объявлять пример универсальным.
Шифрование session не отменяет управление ключами. Redis не даёт durable backup автоматически. SQLite branching не заменяет production database. Sticky approval действует в границах run и не должен превращаться в бессрочное разрешение.
FAQ
Нужно ли логировать всю историю?
Нет. Сохраняйте безопасные агрегаты и идентификаторы. Полная история и RunState требуют отдельного защищённого хранилища.
Почему недостаточно финального ответа?
Он не показывает, откуда взялась память, сколько раз выполнился tool и был ли run действительно возобновлён.
Что проверять после обновления SDK?
Импорты, constructor arguments, lifecycle close/dispose, сериализацию state и порядок approval.
Можно ли использовать реальные операции в тесте?
Нет. Approval, retry и cancellation сначала проверяются fake tool с измеримым счётчиком.
Первоисточник
- Официальная документация OpenAI Agents SDK — проверено 12 сентября 2026 года.
Материал написан самостоятельно; тестовые идентификаторы не относятся к реальным пользователям.
Читайте также
Как проверять агента в терминале через REPL OpenAI Agents SDK
Запускаем run_demo_loop, проверяем многошаговый контекст и streaming, составляем сценарий ручной приёмки и отделяем REPL от автоматических тестов.
Как исправить ошибку reasoning item ID в OpenAI Agents SDK
Разбираем reasoning_item_id_policy=omit: когда удалять ID из переносимой истории, какие входы политика не меняет и как проверить исправление Responses API 400.
Как настроить lifecycle hooks в OpenAI Agents SDK для аудита вызовов
Подключаем RunHooks и AgentHooks, считаем вызовы модели и инструментов, не записываем секреты и проверяем порядок событий агентного запуска.
Комментарии
Пока тихо. Скажите первое слово