Миграция с Assistants API на Responses API

24 мин

TL;DR: миграция с Assistants API на Responses API уже не опциональная задача. OpenAI объявил deprecation Assistants API и срок отключения: 26 августа 2026. Целевой стек: Responses API + Conversations API. Если production-система все еще завязана на Assistants, Threads и Runs, нужен план миграции с проверкой поведения, а не просто замена SDK-вызовов.

Большая ошибка - относиться к этой миграции как к техническому переименованию endpoint. В реальной системе меняется несколько контуров сразу:

  • управление состоянием диалога;
  • модель объектов и жизненный цикл исполнения;
  • streaming events и потребители этих событий;
  • retrieval scope и способ подключения file search;
  • tool calling contracts, права, timeouts и retry policy;
  • наблюдаемость, бюджет и rollback.

Если сейчас в коде есть client.beta.assistants.*, client.beta.threads.*, runs.create, старые обработчики run steps или неявная логика file search, миграцию надо рассматривать как архитектурный cutover.

1) Факты и даты

Ключевые даты:

  1. 11 марта 2025: OpenAI выпустил Responses API как новый API для agentic workflows.
  2. 26 августа 2025: OpenAI объявил deprecation Assistants API.
  3. 26 августа 2026: заявленная дата отключения Assistants API.

В официальной документации OpenAI направление миграции сформулировано явно: Assistants API заменяется связкой Responses API + Conversations API. В migration guide также описана новая модель объектов:

Было в Assistants API Становится в Responses/Conversations
Assistant Prompt
Thread Conversation
Run Response
Run step Item

Это не только новое название. Prompt становится управляемой конфигурацией поведения, Conversation хранит поток items, а Response становится единицей выполнения, в которой модель может вернуть сообщения, reasoning, tool calls и tool outputs.

2) Что на самом деле меняется в архитектуре

Конфигурация поведения

В Assistants API конфигурация часто жила в Assistant: инструкции, модель, tools, metadata. В новом целевом контуре эту роль берет на себя Prompt.

Практический вывод: надо отдельно решить, кто владеет prompt-конфигурацией.

Минимальный контракт:

  • prompt id и версия;
  • владелец изменения;
  • changelog;
  • approval path для production;
  • список tools, которые разрешены этому prompt;
  • тестовые сценарии, которые должны проходить перед раскаткой.

Если prompt меняется через dashboard без версионирования и approval, production-поведение становится неуправляемым. Это тот же класс риска, что и выкладка модели без model registry.

Состояние диалога

В старом контуре состояние было завязано на Thread. В новом контуре есть два базовых подхода:

  1. Client-managed state: цепочка через previous_response_id или собственное хранение контекста.
  2. Server-managed state: использование Conversation как серверного контейнера состояния.

Выбор нельзя оставлять случайным.

Client-managed state лучше подходит, если:

  • нужны строгий replay и аудит в собственной базе;
  • есть compliance-требования к хранению;
  • состояние надо синхронизировать с бизнес-объектами приложения.

Conversations API лучше подходит, если:

  • есть длинные пользовательские диалоги;
  • надо снизить объем локальной state-логики;
  • система допускает серверное хранение conversation items у провайдера.

Самый опасный вариант: часть flows живет через previous_response_id, часть через Conversation, часть через локальные messages, а правила выбора нигде не описаны.

3) Почему endpoint replacement ломает production

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

  1. State regression. Follow-up запросы теряют ограничения, потому что новый контур иначе собирает историю.
  2. Retrieval regression. Раньше file search мог подтягивать данные из assistant-level и thread-level контекста, а теперь scope надо задавать явно.
  3. Streaming regression. Клиентские SSE-парсеры, progress UI и async workers ждут старые события.
  4. Tool regression. Старые функции были терпимы к неявным аргументам, новый tool loop требует строгого контракта.
  5. Observability gap. Старые dashboards строились вокруг runs и run steps, а новые события не попадают в те же поля.

Правильный вопрос для миграции: не “ответил ли endpoint”, а “сохранилось ли поведение системы”.

4) Инвентаризация перед миграцией

Перед изменением кода нужно собрать карту текущего использования Assistants API.

Минимальный inventory:

Область Что найти Почему важно
Assistants id, instructions, tools, model, metadata Основа для Prompt migration
Threads где создаются, как хранятся, как привязаны к user/account Состояние и privacy boundary
Runs кто запускает, какие статусы обрабатываются Execution semantics
Run steps какие events попадают в UI/logs Observability и streaming
File search какие vector stores доступны Retrieval parity
Function calling схемы, retries, side effects Надежность и безопасность
Code interpreter где используются sessions и файлы Cost и data handling
Streaming кто читает SSE/events Client compatibility

Хороший результат инвентаризации - таблица “старый объект -> новый объект -> владелец -> тест паритета”.

5) Prompt migration: не переносить хаос

Если старый Assistant был смесью persona, policy, routing hints, tool descriptions и временных hotfix-инструкций, переносить это как есть опасно. Миграция - нормальный момент, чтобы разделить ответственность.

Практический шаблон:

Prompt package
- role: что система должна делать
- policy: что запрещено и когда нужен отказ
- tool contract: какие tools доступны и зачем
- output contract: структура ответа
- retrieval contract: какие источники можно использовать
- escalation contract: когда передавать человеку или backend workflow
- eval suite: какие сценарии блокируют релиз

Важная граница: prompt не должен быть единственным security control. Права доступа, allowlist tools, tenant boundary, лимиты и approval gates должны жить в коде и инфраструктуре.

6) State strategy: выбрать явно

Вариант A: client-managed state

Схема:

user request
  -> app state store
  -> responses.create(input, previous_response_id or reconstructed context)
  -> persist response id + normalized output

Плюсы:

  • проще replay;
  • проще forensic-анализ после инцидента;
  • можно держать собственные retention rules;
  • легче связывать состояние с бизнес-сущностями.

Риски:

  • приложение отвечает за полноту и порядок контекста;
  • выше шанс state drift;
  • надо отдельно контролировать context window и summarization.

Вариант B: server-managed state через Conversations

Схема:

user request
  -> conversation id
  -> responses.create(conversation, input)
  -> items stored in conversation

Плюсы:

  • меньше локальной state-логики;
  • удобнее для длинных диалогов;
  • модель объектов ближе к intended replacement для Threads.

Риски:

  • сильнее зависимость от внешнего lifecycle;
  • надо отдельно описать retention и deletion;
  • сложнее полная локальная реконструкция поведения, если логи неполные.

Решение должно быть на уровне workload. Например: support chat может идти через Conversations, а batch workflow для классификации - через stateless Responses.

7) Retrieval migration: где чаще всего падает качество

В RAG-сценариях основная опасность - silent degradation. Ответы выглядят уверенно, но начинают использовать не те документы или теряют часть контекста.

Минимальный план:

  1. Зафиксировать текущий retrieval scope для каждого assistant/thread flow.
  2. Сопоставить старые источники с explicit vector_store_ids.
  3. Определить, где file search должен быть доступен, а где запрещен.
  4. Настроить диагностический режим с включением retrieval results в rollout logs.
  5. Собрать fixed eval set: вопросы, ожидаемые источники, forbidden sources, edge cases.
  6. Сравнить качество grounded answer до и после cutover.

Тесты должны проверять не только финальный текст. Нужны сигналы:

  • relevant source hit rate;
  • missing source rate;
  • forbidden source usage;
  • answer faithfulness;
  • latency;
  • tokens and cost per answered task.

Если команда не может объяснить, какие источники были доступны конкретному production-ответу, migration readiness еще нет.

8) Tool calling: контракт важнее названия функции

Responses API ожидает явное описание tools в запросе или через prompt-конфигурацию. Это хороший момент, чтобы убрать неявные side effects.

Минимальный tool contract:

tool_name
purpose
input_schema
output_schema
timeout_ms
retry_policy
idempotency_key
auth_scope
tenant_boundary
side_effect_class
approval_required
observability_fields
fallback_behavior

Классы tools:

Класс Пример Политика отказа
Read-only поиск по базе знаний, lookup профиля чаще fail-soft
Derived computation расчет стоимости, scoring fail-closed при влиянии на решение
External write создание тикета, отправка письма approval или строгий workflow
Browser/computer use действия в UI отдельные права, запись трассы, подтверждение

Ключевой принцип: model output не должен сам выдавать себе права. Модель предлагает tool call, система проверяет policy и только потом исполняет.

9) Streaming migration: обновить consumers

Streaming часто ломается не в backend wrapper, а в потребителях:

  • frontend progress UI;
  • mobile client;
  • async job worker;
  • audit logger;
  • tracing collector;
  • moderation pipeline;
  • billing meter.

Проверить надо:

  1. порядок events;
  2. partial output handling;
  3. tool call deltas;
  4. disconnect cleanup;
  5. cancellation;
  6. timeout behavior;
  7. повторное подключение;
  8. стоимость незавершенных сессий.

Отдельный тест: пользователь закрывает соединение во время tool call. Система должна остановить лишнюю работу или явно довести ее до безопасного состояния.

10) Parity test matrix

Без таблицы паритета миграция остается верой в то, что “вроде отвечает”.

Сценарий Ожидаемый результат Сигнал проблемы
Single-turn без tools Семантически тот же ответ Сильный drift по смыслу
Short multi-turn Follow-up учитывает ограничения Потеря контекста
Long multi-turn Стабильность на длинной истории Сброс поведения, странные summary
File search Используются релевантные источники Missing grounding
Forbidden source Запрещенные документы не используются Cross-tenant risk
Tool timeout Controlled fallback Retry storm
Tool side effect Нет повторного действия при retry Дубли в CRM/тикетах
Streaming happy path UI получает ordered events Broken progress UI
Streaming disconnect Работа останавливается безопасно Cost leak
Cost budget Стоимость в допустимом диапазоне Token/tool spike
Security boundary Нет чужих данных Authz regression
Rollback Старый путь доступен до cutover Нет рабочего fallback

Паритет надо мерить на fixed dataset. Ручная проверка 5 примеров не ловит state и retrieval regressions.

11) Приоритеты миграции

P0: блокеры до широкого трафика

  • нет новых production flows на Assistants API;
  • все активные Assistants сопоставлены с Prompts;
  • state strategy выбрана для каждого workload;
  • retrieval scope задан явно;
  • streaming consumers обновлены;
  • есть parity suite;
  • есть rollback path;
  • on-call dashboards видят новый контур.

P1: высокий риск, если пропустить

  • tool contracts с timeout, retry, idempotency;
  • policy enforcement вне prompt;
  • long conversation evals;
  • cost budgets;
  • tenant boundary tests;
  • incident runbook с новыми object names.

P2: оптимизация после стабилизации

  • tuning retrieval result count;
  • payload minimization;
  • prompt version governance;
  • standardized SDK wrapper;
  • cost attribution по prompt/tool/workload.

12) Rollout pattern

Практичный график для команды, у которой есть production-трафик:

  1. T-90 дней: архитектура миграции зафиксирована, inventory закрыт, parity suite заморожен.
  2. T-60 дней: shadow traffic на Responses path, без влияния на пользователя.
  3. T-45 дней: canary на низкорисковых flows.
  4. T-30 дней: основная доля трафика на Responses, Assistants path остается rollback fallback.
  5. T-14 дней: rollback drill и incident simulation.
  6. T-7 дней: freeze старого контура, запрет новых Assistants dependencies.
  7. T-0: удаление legacy path, мониторинг 72 часа.

Если миграция начинается за неделю до дедлайна, это уже incident response, а не engineering plan.

13) Минимальный wrapper для нового контура

Не стоит размазывать responses.create() по всему приложению. Лучше сделать один integration layer, который держит contract.

type GenerateResponseInput = {
  workload: "support" | "sales_assistant" | "internal_qa";
  userId: string;
  tenantId: string;
  input: string;
  conversationId?: string;
  previousResponseId?: string;
  traceId: string;
};

type GenerateResponseResult = {
  responseId: string;
  outputText: string;
  usedTools: string[];
  retrievalSourceIds: string[];
  costEstimate: {
    inputTokens: number;
    outputTokens: number;
  };
};

Этот wrapper должен делать:

  • выбор prompt id;
  • проверку tenant boundary;
  • сбор tools allowlist;
  • установку timeout;
  • логирование trace id;
  • нормализацию output;
  • запись response id;
  • сбор метрик.

14) Что логировать после миграции

Минимальный telemetry contract:

trace_id
tenant_id
user_id_hash
workload
prompt_id
prompt_version
conversation_id
previous_response_id
response_id
model
tools_allowed
tools_called
tool_latency_ms
tool_error_code
retrieval_store_ids
retrieval_result_count
input_tokens
output_tokens
total_latency_ms
finish_reason
fallback_used
policy_decision

Без этих полей сложно ответить на базовые production-вопросы:

  • почему ответ изменился;
  • какой prompt был активен;
  • какие источники попали в retrieval;
  • какой tool вызвал задержку;
  • где выросла стоимость;
  • можно ли воспроизвести инцидент.

15) Risk register

Риск Влияние Вероятность Митигатор
Миграция началась слишком поздно Critical Medium Дата freeze, canary deadline, владелец cutover
State strategy выбрана неявно High High Design doc по workload
Retrieval качество упало High Medium Side-by-side evals и source-level checks
Streaming consumers сломались High Medium Contract tests для events
Tool вызывает повторный side effect High Medium Idempotency key и retry policy
Стоимость выросла Medium High Budget alerts и per-workload attribution
Prompt изменен без approval Medium Medium Prompt versioning и release gate
Rollback не проверен Critical Medium Rollback drill до широкого трафика

16) Когда миграция готова

Миграцию можно считать готовой, если:

  • все production flows переведены на Responses/Conversations или явно исключены;
  • новые Assistants dependencies запрещены в CI;
  • parity suite проходит;
  • retrieval evals показывают приемлемый delta;
  • streaming consumers прошли тесты disconnect/cancel;
  • dashboards и alerts работают на новых object names;
  • есть документированный rollback;
  • on-call понимает, как расследовать инцидент в новом контуре.

Итоговый артефакт - не PR с заменой SDK. Итоговый артефакт - управляемый execution path с понятными объектами, проверенным поведением и рабочим откатом.

17) Связанные материалы

Источники

FAQ

Когда OpenAI Assistants API перестанет работать?

В официальной документации OpenAI указан срок отключения Assistants API: 26 августа 2026 года. Рабочую миграцию стоит завершать заранее, чтобы оставить время на parity tests, canary, rollback drill и обновление runbook.

Что заменяет Assistants API в production-интеграциях?

Целевой стек: Responses API плюс Conversations API. Prompts заменяют Assistants как конфигурацию поведения, Conversations заменяют Threads для состояния, Responses заменяют Runs как единицу выполнения.

Главный риск миграции в чем?

Главный риск не в замене endpoint. Чаще ломаются состояние диалога, retrieval scope, streaming consumers, tool contracts и наблюдаемость. Поэтому миграцию надо проверять сценариями паритета, а не ручным eyeballing.

Можно ли оставить старый и новый стек параллельно?

Да, на этапах shadow, canary и rollback readiness. Как постоянная архитектура dual stack опасен: растет стоимость, расходятся контракты, усложняется incident response.