Миграция с Assistants API на Responses API
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) Факты и даты
Ключевые даты:
- 11 марта 2025: OpenAI выпустил Responses API как новый API для agentic workflows.
- 26 августа 2025: OpenAI объявил deprecation Assistants API.
- 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. В новом контуре есть два базовых подхода:
- Client-managed state: цепочка через
previous_response_idили собственное хранение контекста. - Server-managed state: использование
Conversationкак серверного контейнера состояния.
Выбор нельзя оставлять случайным.
Client-managed state лучше подходит, если:
- нужны строгий replay и аудит в собственной базе;
- есть compliance-требования к хранению;
- состояние надо синхронизировать с бизнес-объектами приложения.
Conversations API лучше подходит, если:
- есть длинные пользовательские диалоги;
- надо снизить объем локальной state-логики;
- система допускает серверное хранение conversation items у провайдера.
Самый опасный вариант: часть flows живет через previous_response_id, часть через Conversation, часть через локальные messages, а правила выбора нигде не описаны.
3) Почему endpoint replacement ломает production
Поверхностная миграция обычно проходит локально и ломается на реальном трафике. Типовые причины:
- State regression. Follow-up запросы теряют ограничения, потому что новый контур иначе собирает историю.
- Retrieval regression. Раньше file search мог подтягивать данные из assistant-level и thread-level контекста, а теперь scope надо задавать явно.
- Streaming regression. Клиентские SSE-парсеры, progress UI и async workers ждут старые события.
- Tool regression. Старые функции были терпимы к неявным аргументам, новый tool loop требует строгого контракта.
- 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. Ответы выглядят уверенно, но начинают использовать не те документы или теряют часть контекста.
Минимальный план:
- Зафиксировать текущий retrieval scope для каждого assistant/thread flow.
- Сопоставить старые источники с explicit
vector_store_ids. - Определить, где file search должен быть доступен, а где запрещен.
- Настроить диагностический режим с включением retrieval results в rollout logs.
- Собрать fixed eval set: вопросы, ожидаемые источники, forbidden sources, edge cases.
- Сравнить качество 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.
Проверить надо:
- порядок events;
- partial output handling;
- tool call deltas;
- disconnect cleanup;
- cancellation;
- timeout behavior;
- повторное подключение;
- стоимость незавершенных сессий.
Отдельный тест: пользователь закрывает соединение во время 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-трафик:
- T-90 дней: архитектура миграции зафиксирована, inventory закрыт, parity suite заморожен.
- T-60 дней: shadow traffic на Responses path, без влияния на пользователя.
- T-45 дней: canary на низкорисковых flows.
- T-30 дней: основная доля трафика на Responses, Assistants path остается rollback fallback.
- T-14 дней: rollback drill и incident simulation.
- T-7 дней: freeze старого контура, запрет новых Assistants dependencies.
- 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) Связанные материалы
- Агент или workflow: как выбрать архитектуру без хайпа
- MLOps для RAG-агента поддержки в 2026: релизы, безопасность и стоимость
- MLOps для production ML: 7 релизных гейтов для управляемой выкладки
- Как встроить вызовы инструментов в поиск и не ломать отбор кандидатов
Источники
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.