Гайд · TNWS AI

Как создать ветку диалога через AdvancedSQLiteSession

5 мин

Сохраняем turns, создаём branch от выбранного хода, проверяем независимое продолжение и записываем usage через store_run_usage.

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

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

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

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

  • AdvancedSQLiteSession предоставляет branching, usage analytics и structured queries.
  • Конструктор принимает session_id, db_path и create_tables.
  • Usage результата сохраняется методом store_run_usage(result).
  • Ветка создаётся create_branch_from_turn(turn_number).
  • Номер turn нужно получить из фактической истории, а не угадывать по количеству сообщений.

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

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

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

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

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

  1. Создайте файл базы в тестовом каталоге и отдельный session_id.
  2. Выполните минимум два turns и сохраняйте usage каждого result.
  3. Получите доступные turns и выберите подтверждённый номер.
  4. Создайте branch и продолжите её отличающимся вводом, затем сравните обе истории.

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

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

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

async def main():
    s=AdvancedSQLiteSession(session_id="ticket-781",db_path="conversations.db",create_tables=True)
    a=Agent(name="support",instructions="Отвечай по текущей ветке.")
    first=await Runner.run(a,"Тикет T-781: ошибка оплаты",session=s)
    await s.store_run_usage(first)
    second=await Runner.run(a,"Клиент просит возврат",session=s)
    await s.store_run_usage(second)
    branch=await s.create_branch_from_turn(2)
    assert branch is not None
    print(branch)

asyncio.run(main())

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

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

Исходная ветка после T-781 выбирает возврат, альтернативная — диагностику платежа.

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

Обе ветки имеют общий префикс до выбранного turn и разные продолжения; исходная история не переписана.

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

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

Укажите несуществующий turn. Операция не должна молча создавать ветку от конца.

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

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

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

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

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

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

Комментарии

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