Гайд · TNWS AI
Как вручную создать task_span для запуска Runner
Создаём task_span вокруг нестандартного запуска, проверяем имя задачи, parent_id и отсутствие второго автоматического task span.
Практическая задача
В этом гайде решается задача: пометить один верхнеуровневый вызов собственного runner-адаптера как отдельную задачу. Используется официальный интерфейс task_span(name). Материал нужен, когда стандартной автоматической трассировки Runner недостаточно или требуется строго проверить tracing context. Если обычный Runner уже создаёт тот же span, ручное дублирование запрещено: оно искажает дерево и длительность.
Факты проверены 12 сентября 2026 года (проверены сигнатура, параметры, контекстный жизненный цикл, экспорт и негативные сценарии; при обновлении зависимости контракт, обработку исключений и изоляцию параллельных контекстов нужно проверить повторно) по руководству OpenAI Agents SDK по tracing и официальному API reference. task_span принимает имя и представляет один верхнеуровневый вызов Runner; при обычном Runner такой span создаётся автоматически. Изменяемые цены, тарифы и неподтверждённые лимиты не используются. Версию пакета берите из lock-файла своего проекта.
Проверяемый результат
Критерий готовности — конкретное поле, parent_id, состояние contextvar, результат export или событие processor. Внешний dashboard полезен для просмотра, но не заменяет assert. Перед внедрением создайте baseline trace и сохраните только технические идентификаторы и типы spans.
Для примеров используйте staging и искусственные данные. Не помещайте в metadata, input, output и имя span реальные персональные данные, токены или полный ответ внутренней системы. Динамический ID клиента не должен становиться именем span: высокая кардинальность ухудшает анализ.
Пошаговая реализация
- Создайте виртуальное окружение, установите openai-agents и зафиксируйте зависимость.
- Откройте верхнеуровневую trace через context manager либо подготовьте ручной lifecycle с обязательным finally.
- Создайте нужный span/helper только в той области, которую он должен измерять.
- Передайте параметры строго по API reference. Не придумывайте дополнительные поля в типизированном helper.
- Выполните операцию и проверьте бизнес-результат независимо от tracing.
- Проверьте tracing-контракт: trace_id, span_id, parent_id, span_data или export.
- Запустите негативный сценарий и убедитесь, что он даёт отличимый результат.
- Проверьте два параллельных workflow: их текущие контексты не должны смешиваться.
- Для собственного processor добавьте force_flush и shutdown в жизненный цикл worker.
- Перед релизом выполните поиск тестового секретного маркера по сериализованным событиям.
Готовый код
from agents import custom_span, task_span, trace
with trace("manual_runner_adapter") as tr:
with task_span("classify_ticket") as task:
with custom_span("adapter_call") as child:
assert child.parent_id==task.span_id
assert task.trace_id==tr.trace_id
result="delivery"
print(task.span_id,result)
Код содержит машинно проверяемые утверждения. В CI не заменяйте assert печатью. Если пример использует ConsoleSpanExporter, оставляйте его только в тестовой среде: вывод всей trace может содержать больше данных, чем разрешает production-политика.
Пример входа и ожидаемого результата
Вход: Ручной adapter классифицирует тикет в delivery внутри task classify_ticket.
Ожидаемый результат: Task принадлежит trace manual_runner_adapter, а adapter_call вложен непосредственно в task.
Проверяйте структуру, а не случайные значения или длительность. Для ID важны формат, уникальность и сохранение связи; для context helper — тот же объект внутри области и None снаружи; для очереди — факт flush и отдельный учёт отброшенных элементов.
Негативный тест
Не оборачивайте обычный Runner.run вторым task_span без отключения автоматического: тестовый processor должен обнаружить дубликат task spans.
Негативный тест показывает границу API: helper не проверяет бизнес-маршрут, монотонность turn или безопасность данных за приложение. Ошибка tracing не должна подменять основной результат, но нарушение обязательной политики конфигурации должно останавливать деплой.
Встраивание в production
Сосредоточьте tracing-настройки в одном bootstrap-модуле. Глобальные processors нельзя регистрировать на каждом HTTP-запросе. Локальные trace и spans создавайте рядом с операцией, но через небольшую обёртку предметной области, которая фильтрует разрешённые поля.
Contextvars автоматически помогают с async concurrency, однако новый поток или задача, созданная особым способом, требует отдельного теста переноса контекста. Не храните current trace в глобальной переменной. Всегда обрабатывайте None: функция может быть вызвана вне instrumented workflow или tracing может быть отключён.
Для ручного start/finish применяйте try/finally. Для processor задайте bounded queue, быстрые callbacks и явные метрики delivered, retried, dropped. Не объявляйте «потерь нет», если измеряется только число успешных экспортов. Для сериализации оставляйте include_tracing_api_key=False.
Копируемый шаблон ревью
Операция: task_span(name)
Причина ручной настройки: <конкретная причина>
Ожидаемый parent: <trace/span>
Проверяемые поля: <список>
Вход без PII: <значение>
Ожидаемый результат: <точная структура>
Негативный тест: <сценарий>
Поведение при исключении: <finish/reset/shutdown>
Результат вне контекста: <None или другое>
Секретный маркер отсутствует в export: <да>
Параллельная изоляция: <пройдена>
Источник: https://openai.github.io/openai-agents-python/ref/tracing/
Чек-лист финальной проверки
- Сигнатура сверена с документацией 12 сентября 2026 года (проверены сигнатура, параметры, контекстный жизненный цикл, экспорт и негативные сценарии; при обновлении зависимости контракт, обработку исключений и изоляцию параллельных контекстов нужно проверить повторно).
- Нет дубликата автоматического span Runner.
- Context manager или finally гарантирует завершение.
- parent_id соответствует ожидаемому родителю.
- ID создан официальным helper или самим SDK.
- Имена стабильны и не содержат пользовательские ID.
- Input/output не раскрывают секреты и реальные PII.
- Позитивный критерий проверяется assert.
- Негативный сценарий отличим от успеха.
- Вне контекста корректно обрабатывается None.
- Параллельные workflow изолированы.
- Flush и shutdown включены там, где нужны.
FAQ
Почему лучше использовать with?
Context manager автоматически выполняет start и finish и корректно восстанавливает текущий контекст при исключении. Ручной lifecycle нужен только при реальной callback-границе.
Можно ли передавать собственный span_id?
Да, параметр предусмотрен, но используйте gen_span_id, чтобы получить корректный формат. Произвольный внешний ID предварительно валидируйте.
Что возвращают get_current_trace и get_current_span вне контекста?
Они возвращают None. Это нормальное состояние, а не исключение; вызывающий код обязан его обработать.
Нужно ли вызывать flush после каждого запроса?
Нет. BatchTraceProcessor экспортирует в фоне. Flush нужен, когда короткоживущая задача требует немедленной доставки перед завершением процесса или job.
Можно ли хранить tracing API key в to_json?
Метод имеет специальный флаг, но по умолчанию ключ исключён именно для защиты от случайного сохранения. Для обычного транспорта оставляйте значение False.
Читайте также
Как генерировать group_id через gen_group_id в Agents SDK
Генерируем group_id официальным helper, связываем две trace одного диалога и проверяем формат и корреляцию.
Как генерировать корректные trace_id и span_id в Agents SDK
Используем gen_trace_id и gen_span_id, проверяем префиксы, длину, уникальность и передаём ID в ручную trace/span.
Как настроить очередь BatchTraceProcessor в Agents SDK
Настраиваем max_queue_size, max_batch_size, schedule_delay и export_trigger_ratio у BatchTraceProcessor и проверяем flush.
Комментарии
Пока тихо. Скажите первое слово