Гайд · TNWS AI

Как настроить RedisSession в OpenAI Agents SDK для нескольких workers

5 мин

Подключаем RedisSession.from_url, проверяем общую историю между workers, корректно закрываем принадлежащий сессии клиент и тестируем terminal-состояние.

Задача и критерий готовности

Задача — хранить историю агента в общем Redis, чтобы разные процессы продолжали одну сессию по стабильному session_id. Результат считается готовым только при машинной проверке состояния session, RunState, interruption или event stream. Красивый ответ агента не заменяет доказательство.

Методы и поведение сверены 12 сентября 2026 года по официальной документации OpenAI Agents SDK. В статье нет выдуманных цен, квот и метрик.

Подтверждённый контракт

  • RedisSession предназначен для общей низколатентной памяти между workers или services.
  • Установка расширения выполняется пакетом openai-agents[redis].
  • RedisSession.from_url(session_id, url=...) создаёт Redis client и владеет им.
  • После close() такая сессия terminal: дальнейшие операции поднимают RuntimeError.
  • Повторные и конкурентные close безопасны; при переданном внешнем redis_client владение остаётся у приложения.

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

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

  • отдельную тестовую базу, Redis database или временный файл;
  • уникальный session_id, не совпадающий с ID реального пользователя;
  • fake tool и provider stub для контроля вызовов;
  • переменные окружения для ключей и строк подключения;
  • журнал безопасных агрегатов и версий без содержимого переписки.

Прежде чем запускать код, определите владельца соединения и cleanup. Для hosted storage проверьте, где фактически лежат данные. Для durable state считайте payload чувствительным: он включает app context и runtime metadata.

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

  1. Создайте отдельный Redis database для теста и стабильный session_id.
  2. Запишите первый turn одним экземпляром RedisSession, затем прочитайте продолжение другим worker-процессом.
  3. Закрывайте from_url-сессию в finally.
  4. После close вызовите get_items и потребуйте RuntimeError, чтобы подтвердить ownership contract.

После каждого шага записывайте наблюдаемый признак: число items, конкретный exception, наличие interruption, счётчик tool или факт завершения async iterator. Комментарий в коде не является проверкой.

Копируемый пример

import asyncio
from agents import Agent, Runner
from agents.extensions.memory import RedisSession

async def main():
    agent=Agent(name="support",instructions="Помни номер тикета.")
    session=RedisSession.from_url("ticket-781",url="redis://localhost:6379/0")
    try:
        await Runner.run(agent,"Номер обращения T-781",session=session)
        result=await Runner.run(agent,"Какой номер я называл?",session=session)
        print(result.final_output)
    finally:
        await session.close()
    try:
        await session.get_items()
        raise AssertionError("ожидался RuntimeError")
    except RuntimeError:
        pass

asyncio.run(main())

Запускайте пример в отдельном virtualenv. Все ключи и URL берите из окружения; тестовые localhost-адреса не превращайте в production-конфигурацию автоматически. Заполнители paused, original_agent и fake counters должны быть определены вашим воспроизводимым fixture.

Реалистичный вход

Worker A сохраняет T-781, worker B с тем же session_id спрашивает номер.

Ожидаемый результат

Второй worker получает историю; после close операции owned-сессии завершаются RuntimeError.

Перенесите ожидание в assert. Для недетерминированного текста проверяйте сохранённый факт через model stub либо напрямую session items. Для approval проверяйте и interruptions, и execution counter.

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

Используйте разные session_id — история не должна пересекаться. Не считайте это отказом Redis.

Негативная проверка меняет одно условие. Ошибка подключения не равна пустой истории, новый run не равен resume, другой session_id не является потерей данных, а отсутствие второй паузы допустимо только при подтверждённом sticky decision.

Готовый prompt для ревью

Проверь конфигурацию сценария «Как настроить RedisSession в OpenAI Agents SDK для нескольких workers». Для каждого факта найди исполняемое доказательство. Проверь 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 с измеримым счётчиком.

Первоисточник

Материал написан самостоятельно; тестовые идентификаторы не относятся к реальным пользователям.

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

Комментарии

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