Гайд · TNWS AI

Как считать токены и запросы через Usage в OpenAI Agents SDK

7 мин

Как получить requests, input_tokens, output_tokens и request_usage_entries в OpenAI Agents SDK, проверить многошаговый run и подготовить корректный журнал потребления.

Задача и применимость

Этот гайд решает конкретную задачу: получить фактическое потребление многошагового запуска агента по данным провайдера, разложить его по запросам и не путать токены с денежной стоимостью. Материал рассчитан на разработчика, который уже умеет запускать Python, но хочет получить воспроизводимую интеграцию, а не демонстрацию «ответ пришёл — значит всё готово». Ниже есть рабочий каркас, реалистичный контрольный пример, негативные сценарии и критерии приёмки.

Сведения сверены с официальной документацией 12 сентября 2026 года. В статье намеренно нет неподтверждённых цен, обещаний доступности из конкретной страны и результатов чужих тестов. Такие параметры зависят от аккаунта, региона, модели и даты. Перед production-развёртыванием повторите smoke-тест из своего окружения.

Что подтверждено официально

  1. После Runner.run(...) агрегированное потребление доступно в result.context_wrapper.usage.
  2. Документированные поля: requests, input_tokens, output_tokens, total_tokens.
  3. Список request_usage_entries хранит данные отдельных модельных запросов внутри одного run, включая вызовы, приведшие к tools или handoffs.
  4. При Sessions каждый Runner.run() возвращает usage только своего запуска, хотя сохранённая история может повторно попасть во вход и увеличить input tokens.
  5. ModelSettings(preserve_raw_usage=True) сохраняет дошедший до адаптера provider payload в response.raw_usage, но не запрашивает его у провайдера и не агрегирует автоматически.

Первоисточник: официальная документация. Это ссылка на интерфейс, использованный в примере, а не на пересказ стороннего блога. Сохраните дату проверки в change log проекта: при обновлении SDK сравнение станет быстрее.

Что подготовить

Нужны Python-окружение, официальный SDK, ключ нужного сервиса в переменной окружения и небольшой тестовый набор. Ключ нельзя вставлять в браузерный JavaScript, мобильное приложение, публичный notebook или репозиторий. Если код выполняется на сервере, выдайте процессу минимально необходимые права и предусмотрите отзыв секрета.

Подготовьте минимум три кейса: обычный, граничный и запрещённый. Для каждого запишите ожидаемую структуру, обязательные значения и допустимый отказ. Такой набор полезнее одной «красивой» демонстрации: он обнаруживает неверный endpoint, неподходящую модель, потерю аргументов и тихое обрезание входа.

Пошаговая настройка

  1. После каждого Runner.run присвойте u = result.context_wrapper.usage; снимайте метрики до уничтожения объекта результата.
  2. Запишите requests, input_tokens, output_tokens и total_tokens вместе с внутренним run_id, моделью и временем.
  3. Пройдите по u.request_usage_entries и сохраните порядковый номер. Это покажет, сколько модельных обращений породил один пользовательский запрос.
  4. Проверьте инвариант input_tokens + output_tokens == total_tokens для конкретного backend; при несовпадении храните исходные значения, а не исправляйте их.
  5. Денежную стоимость считайте отдельным модулем по версии прайс-листа и типам токенов. Не умножайте все токены на одну ставку.
  6. Для сессии проведите два хода и сравните usage каждого результата отдельно. Не суммируйте повторно один и тот же checkpoint.
  7. Если используете сторонний adapter, проверьте реальный ответ. Документация предупреждает, что некоторым streaming Chat Completions backend нужен ModelSettings(include_usage=True).
  8. Настройте сигнал аномалии по собственному базовому диапазону: резкий рост requests часто указывает на цикл инструментов.

Не объединяйте все проверки в один логический флаг. Отдельно фиксируйте транспортный успех, корректность схемы, бизнес-валидацию и качество содержимого. Тогда по журналу видно, сломался ли HTTP, изменился ли SDK, модель выбрала неверное действие или постусловие не выполнено.

Копируемый шаблон

result = await Runner.run(agent, "Проверь статус заказа A-104")
u = result.context_wrapper.usage
record = {
    "requests": u.requests,
    "input_tokens": u.input_tokens,
    "output_tokens": u.output_tokens,
    "total_tokens": u.total_tokens,
    "per_request": [
        {"input": x.input_tokens, "output": x.output_tokens}
        for x in u.request_usage_entries
    ],
}
print(record)

Переменные модели и провайдера специально вынесены в окружение там, где их доступность может меняться. Подставляйте только модель, которая видна вашему проекту и подходит задаче по официальной карточке. Если пример вызывает внешнее действие, замените обработчик на stub до завершения тестов.

Реалистичный пример входа и ожидаемого результата

Вход: Один пользовательский запрос вызывает модель, затем get_order, затем модель формирует финальный ответ.

Ожидаемый результат: requests отражает все модельные обращения в run, а request_usage_entries содержит отдельные записи. Итоговые токены берутся из API-метрик, но сумма в рублях не выводится без актуального прайс-листа.

Сохраните этот кейс как regression fixture. Сравнивать весь текст побуквенно обычно не нужно: проверяйте обязательные сущности, типы, порядок побочных эффектов и запретные утверждения. Если результат недетерминирован, выполните несколько прогонов и рассматривайте любое нарушение инварианта как дефект интеграции.

Проверка по уровням

1. Транспорт

Проверьте код ответа, таймаут и идентификатор запроса, если провайдер его возвращает. Ошибки авторизации и неверные параметры не следует повторять с backoff: сначала исправьте конфигурацию. Для временных 429/5xx используйте ограниченное число повторов с jitter и идемпотентностью.

2. Контракт

Убедитесь, что обязательные поля присутствуют и имеют документированные типы. Логируйте только безопасную выжимку: имя операции, модель, длительность, статус и размеры. Не записывайте ключи, полный пользовательский текст, документы или персональные данные «для отладки».

3. Смысл

Проверяйте числа, даты, отрицания, идентификаторы и связь вывода с входом. Плавный русский текст не доказывает правильность результата. Там, где предусмотрен отказ, он должен быть явным: пустой массив или пустая строка не равны успешной обработке.

4. Побочные эффекты

Если инструмент меняет данные, сначала валидируйте право пользователя и состояние ресурса, затем используйте идемпотентный ключ. После таймаута перепроверьте фактический статус до повтора. Так сеть не превратит один запрос в две оплаты, две рассылки или два удаления.

Негативные тесты

  1. Удалите ключ из окружения: приложение должно завершиться понятной ошибкой до отправки пользовательских данных.
  2. Укажите несуществующую модель: ошибка не должна превращаться в пустой «успешный» ответ.
  3. Передайте вход без обязательного значения и проверьте, что слой приложения его отклоняет.
  4. Имитируйте таймаут после отправки запроса. Повтор допускается только после проверки идемпотентности.
  5. Подмените тип одного поля в mock-ответе: контрактный тест обязан сработать.
  6. Запустите запрещённый или чужой идентификатор: интеграция не должна выполнять действие только потому, что его предложила модель.

Рабочая приёмка

Минимальная приёмка состоит из журнала теста, сохранённой версии зависимостей и таблицы «вход → инварианты → результат». Для каждой ошибки определите владельца: транспорт обслуживает platform-команда, схему — разработчик интеграции, бизнес-правила — продуктовый сервис, качество — владелец данных. Это предотвращает ситуацию, когда некорректный ответ неделями считают «особенностью нейросети».

Перед расширением трафика добавьте метрики количества запросов, отказов, повторов, пустых результатов и ручных отклонений. Не публикуйте выдуманные пороги: базовую линию получите на своей контрольной выборке, а затем зафиксируйте её в runbook. Любое изменение модели или SDK прогоняйте через тот же набор.

Чек-лист финальной проверки

  • Использована официальная документация, проверенная 12 сентября 2026 года.
  • Секрет хранится в переменной окружения и не попадает в клиентский код или логи.
  • Модель/провайдер доступны именно в рабочем аккаунте.
  • Обычный пример возвращает обязательные поля и значения.
  • Граничный и запрещённый примеры дают контролируемый результат.
  • Числа, даты, идентификаторы и отрицания сверяются с источником.
  • Повтор запроса ограничен и безопасен для побочных эффектов.
  • Версия SDK зафиксирована, а контрактный тест запускается в CI.
  • Пользователь видит понятную ошибку вместо ложного успеха.

Ограничения

  • Usage — телеметрия токенов, не готовый счёт. Цена зависит от модели, вида токенов и актуального тарифа.
  • Сторонний адаптер может не передать все usage-поля. Нулевое значение надо отличать от отсутствующего, если это важно.
  • Повторно поданная история сессии влияет на input tokens следующего run.

Кроме перечисленного, результат зависит от выбранной модели и входных данных. Не переносите вывод одного smoke-теста на весь поток. Для чувствительных решений используйте человеко-машинный процесс: модель предлагает или извлекает данные, код проверяет контракт, а уполномоченный сервис или сотрудник подтверждает действие.

FAQ

Как понять, что интеграция действительно работает?

Используйте контрольный вход и ожидаемый результат из гайда, затем выполните негативный тест. Для темы «получить фактическое потребление многошагового запуска агента по данным провайдера, разложить его по запросам и не путать токены с денежной стоимостью» успехом считается не HTTP 200 сам по себе, а прохождение проверок структуры, содержания и отсутствия побочного эффекта при ошибке.

Можно ли сразу использовать пример в production?

Нет. Пример показывает подтверждённый интерфейс API, но в production нужны секреты в хранилище, таймауты, ограничение повторов, авторизация, журнал решений и тесты на данных вашего домена.

Почему в статье нет фиксированной цены?

Цены, квоты и доступность меняются. На 12 сентября 2026 года в этом руководстве используются только интерфейсы из официальной документации; стоимость проверяйте непосредственно в кабинете и актуальном прайс-листе перед запуском.

Что делать, если поле ответа отличается?

Сначала зафиксируйте версию SDK и сырой ответ без секретов. Затем сверяйте его с официальной документацией и типами установленной версии. Не маскируйте несовместимость универсальным try/catch, который возвращает пустой результат.

Официальный первоисточник

Частые вопросы

Как понять, что интеграция действительно работает?

Используйте контрольный вход и ожидаемый результат из гайда, затем выполните негативный тест. Для темы «получить фактическое потребление многошагового запуска агента по данным провайдера, разложить его по запросам и не путать токены с денежной стоимостью» успехом считается не HTTP 200 сам по себе, а прохождение проверок структуры, содержания и отсутствия побочного эффекта при ошибке.

Можно ли сразу использовать пример в production?

Нет. Пример показывает подтверждённый интерфейс API, но в production нужны секреты в хранилище, таймауты, ограничение повторов, авторизация, журнал решений и тесты на данных вашего домена.

Почему в статье нет фиксированной цены?

Цены, квоты и доступность меняются. На 12 сентября 2026 года в этом руководстве используются только интерфейсы из официальной документации; стоимость проверяйте непосредственно в кабинете и актуальном прайс-листе перед запуском.

Что делать, если поле ответа отличается?

Сначала зафиксируйте версию SDK и сырой ответ без секретов. Затем сверяйте его с официальной документацией и типами установленной версии. Не маскируйте несовместимость универсальным try/catch, который возвращает пустой результат.

Читайте также

Комментарии

Пока тихо. Скажите первое слово