Гайд · TNWS AI
Как зашифровать историю EncryptedSession в OpenAI Agents SDK
Оборачиваем SQLAlchemySession в EncryptedSession, задаём ключ и TTL, проверяем чтение до срока и пропуск просроченных элементов.
Задача и критерий готовности
Задача — прозрачно шифровать сохраняемые session items и автоматически исключать элементы после TTL. Результат считается готовым только при машинной проверке состояния session, RunState, interruption или event stream. Красивый ответ агента не заменяет доказательство.
Методы и поведение сверены 12 сентября 2026 года по официальной документации OpenAI Agents SDK. В статье нет выдуманных цен, квот и метрик.
Подтверждённый контракт
- EncryptedSession оборачивает любую совместимую session implementation.
- Шифрование основано на Fernet.
- Уникальные ключи сессий выводятся через HKDF.
- TTL приводит к тихому пропуску старых элементов.
- Один и тот же encryption_key нужен для последующего чтения; ключ нельзя хранить рядом с базой.
Каждый пункт проверяется отдельно. Не объединяйте доступность backend, корректность истории и качество ответа в один флаг success: это независимые слои.
Что подготовить
- отдельную тестовую базу, Redis database или временный файл;
- уникальный session_id, не совпадающий с ID реального пользователя;
- fake tool и provider stub для контроля вызовов;
- переменные окружения для ключей и строк подключения;
- журнал безопасных агрегатов и версий без содержимого переписки.
Прежде чем запускать код, определите владельца соединения и cleanup. Для hosted storage проверьте, где фактически лежат данные. Для durable state считайте payload чувствительным: он включает app context и runtime metadata.
Пошаговая настройка
- Сгенерируйте и сохраните ключ в secret manager, а не в коде.
- Создайте underlying session и оберните её EncryptedSession с осознанным TTL.
- Запишите тестовый item и прочитайте тем же ключом.
- В тесте с управляемыми часами перейдите за TTL и подтвердите, что элемент пропущен.
После каждого шага записывайте наблюдаемый признак: число items, конкретный exception, наличие interruption, счётчик tool или факт завершения async iterator. Комментарий в коде не является проверкой.
Копируемый пример
import asyncio, os
from agents.extensions.memory import EncryptedSession, SQLAlchemySession
async def main():
base=SQLAlchemySession.from_url("ticket-781",url="sqlite+aiosqlite:///secure.db",create_tables=True)
session=EncryptedSession(session_id="ticket-781",underlying_session=base,encryption_key=os.environ["SESSION_KEY"],ttl=600)
await session.add_items([{"role":"user","content":"Тикет T-781"}])
items=await session.get_items()
assert len(items)==1
await base.engine.dispose()
asyncio.run(main())
Запускайте пример в отдельном virtualenv. Все ключи и URL берите из окружения; тестовые localhost-адреса не превращайте в production-конфигурацию автоматически. Заполнители paused, original_agent и fake counters должны быть определены вашим воспроизводимым fixture.
Реалистичный вход
Один обезличенный item записывается с TTL 600 секунд.
Ожидаемый результат
До TTL item читается; после искусственного сдвига времени отсутствует. Ключ в логе не появляется.
Перенесите ожидание в assert. Для недетерминированного текста проверяйте сохранённый факт через model stub либо напрямую session items. Для approval проверяйте и interruptions, и execution counter.
Негативный тест
Попробуйте читать другим ключом: ошибка не должна преобразовываться в пустую «успешную» историю.
Негативная проверка меняет одно условие. Ошибка подключения не равна пустой истории, новый run не равен resume, другой session_id не является потерей данных, а отсутствие второй паузы допустимо только при подтверждённом sticky decision.
Готовый prompt для ревью
Проверь конфигурацию сценария «Как зашифровать историю EncryptedSession в OpenAI Agents SDK». Для каждого факта найди исполняемое доказательство. Проверь 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, считаем вызовы модели и инструментов, не записываем секреты и проверяем порядок событий агентного запуска.
Комментарии
Пока тихо. Скажите первое слово