Миграция с 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
AssistantPrompt
ThreadConversation
RunResponse
Run stepItem

Это не только новое название. 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:

ОбластьЧто найтиПочему важно
Assistantsid, instructions, tools, model, metadataОснова для Prompt migration
Threadsгде создаются, как хранятся, как привязаны к user/accountСостояние и privacy boundary
Runsкто запускает, какие статусы обрабатываютсяExecution semantics
Run stepsкакие events попадают в UI/logsObservability и streaming
File searchкакие vector stores доступныRetrieval parity
Function callingсхемы, retries, side effectsНадежность и безопасность
Code interpreterгде используются sessions и файлыCost и data handling
Streamingкто читает SSE/eventsClient 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расчет стоимости, scoringfail-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-turnFollow-up учитывает ограниченияПотеря контекста
Long multi-turnСтабильность на длинной историиСброс поведения, странные summary
File searchИспользуются релевантные источникиMissing grounding
Forbidden sourceЗапрещенные документы не используютсяCross-tenant risk
Tool timeoutControlled fallbackRetry storm
Tool side effectНет повторного действия при retryДубли в CRM/тикетах
Streaming happy pathUI получает ordered eventsBroken 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

РискВлияниеВероятностьМитигатор
Миграция началась слишком поздноCriticalMediumДата freeze, canary deadline, владелец cutover
State strategy выбрана неявноHighHighDesign doc по workload
Retrieval качество упалоHighMediumSide-by-side evals и source-level checks
Streaming consumers сломалисьHighMediumContract tests для events
Tool вызывает повторный side effectHighMediumIdempotency key и retry policy
Стоимость вырослаMediumHighBudget alerts и per-workload attribution
Prompt изменен без approvalMediumMediumPrompt versioning и release gate
Rollback не проверенCriticalMediumRollback 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.