Migrating from OpenAI Assistants to Responses after the shutdown
OpenAI shut down the Assistants API on August 26, 2026. Map threads, runs and file search to Responses, recover saved history, and decide who owns state.
To migrate from OpenAI Assistants to Responses, rebuild conversation state from messages your application saved, replace Runs with Responses, and configure file_search with explicit vector store IDs. OpenAI shut down the Assistants API on August 26, 2026; its Thread-message retrieval calls no longer work. Conversations can own the new history, or your application can retain it and send the required context on each request.
That distinction matters because an Assistants integration bundled configuration, server-side history and execution into a small set of persistent objects. A hurried migration can reproduce the same coupling under new names without deciding who should own state, tools, retries, retention and observability.
An Assistants migration is an architecture migration: inventory each responsibility, choose where it should live, then move traffic. The point of doing that work is to make the next provider, model or API transition smaller than this one.
Map the objects, then divide the responsibilities
The official mapping is a useful starting point: an Assistant becomes prompt or request configuration — model, instructions, tools and defaults; a Thread becomes a Conversation, the durable interaction state; a Run becomes a Response, one execution against current input and state; and a Run step becomes an Item, which can be a message, tool call, tool output or other event.
This mapping is not a complete migration plan. It says what OpenAI objects replace the old objects, but it does not decide which parts your application should continue to delegate to a provider.
Separate the workload into five concerns: configuration (model selection, instructions, tool definitions, schemas and generation controls), state (messages, tool calls, tool results, files, metadata and retention), execution (streaming, background work, cancellation, retries and tool loops), capabilities (file search, code execution, functions, MCP and other provider tools), and operations (usage, traces, errors, evaluation, authorization and rollback).
For each concern, record the current Assistants behavior, the target owner and the evidence that proves parity. This prevents a successful text response from hiding a broken tool loop or missing conversation history.
Choose a target state model deliberately
Responses supports more than one way to continue an interaction. The choice affects retention, portability and how much state your application owns.
Provider-managed Conversations
A Conversation stores a durable stream of Items. Unlike a Thread, it can contain messages, tool calls, tool outputs and other typed data rather than only messages. A Response can attach new input and output Items to that Conversation.
This is the closest conceptual replacement for Threads. It fits when you want OpenAI to persist the interaction and when provider-native tools and item semantics are central to the product.
The trade-off is deliberate provider coupling. Your application stores a Conversation identifier and depends on OpenAI's item model, retention behavior and migration surface.
Chained Responses
A request can use previous_response_id to continue from an earlier Response without creating a Conversation object. This is useful for short-lived chains or workflows that do not need a separately managed durable conversation.
It is not free context. OpenAI's conversation-state guide says previous input tokens in the chain are still billed as input tokens. Its data-controls reference documents at least 30 days of Responses application-state retention by default or with store: true, with exceptions for particular modes and data controls. Conversations and their Items persist until deleted. Choose the storage policy explicitly; a response chain is not your application archive.
Application-managed history
Your application can store the canonical interaction and send the required input on each request. This gives you direct control over retention, redaction, model switching and provider portability.
It also makes you responsible for context assembly, truncation, compaction, replaying tool state and avoiding duplicate execution. Reasoning-capable and tool-using models may return opaque or signed state that must survive the next turn, so "store the text messages" is no longer a sufficient design.
Do not choose among these models based only on which requires the fewest code changes. Choose based on data ownership, provider portability, tool semantics and operational capability.
Do not blindly migrate Assistants into another temporary object
The official guide still describes creating reusable Prompt objects from Assistants in the dashboard. It also warns that those Prompt objects are deprecated. OpenAI's deprecation schedule lists November 30, 2026 as the shutdown date for v1/prompts. Treat the conversion instructions as a transition path, not a durable configuration design. The prompt-object and Agent Builder shutdown post covers where that configuration can live instead.
That warning changes the migration decision.
If your workload needs provider-managed prompt versioning during a short transition, the conversion path can still be useful. If you are designing the durable target, first ask whether configuration should live in:
- version-controlled application configuration;
- request-level
instructions, model and tool declarations; - a provider-independent AI gateway;
- or a provider Prompt object whose lifecycle you accept explicitly.
Do not introduce a second migration merely because the dashboard offers an automatic conversion. The durable abstraction is the configuration contract — instructions, tools, model policy and schema — not the identifier of the object that stores it today.
How do you migrate Threads after the Assistants shutdown?
Start new chats on the replacement path, then backfill active history from your own saved messages or pre-shutdown exports. The official migration guide explicitly labels its Thread-reading example as a pre-sunset workflow: openai.beta.threads.messages.list no longer works.
Do not build a recovery job around that removed call. If you have only Thread IDs, the documented migration path cannot reconstruct their messages. Record the gap, tell users what history is missing, and provide a controlled restart experience instead of inventing conversation history.
A Thread backfill must transform content. Threads stored messages; Conversations store typed Items. User text becomes input text, assistant text becomes output text, and image or file content must be converted to the target item shape. Tool calls and results need their identifiers and ordering preserved where they are part of the history you intend to continue.
Before writing a backfill job, classify the Thread history you retained: active conversations that users are likely to resume; record-only history that must remain readable without model continuation; expired data eligible for deletion under the product retention policy; and exceptional conversations containing unsupported content, incomplete Runs or tool state that requires manual handling.
Migrate active conversations first. Keep an immutable mapping from the old Thread ID to the new Conversation ID, plus migration status, item counts and a content hash or other reconciliation evidence. Preserve your saved source records during reconciliation, subject to your retention policy.
Replace Run polling and tool handoffs explicitly
A Run looked like one server-managed process attached to a Thread. A Response is simpler at the top level — input Items go in and output Items come back — but the application must still account for the execution lifecycle.
Inventory every Run behavior your product relies on:
- queued and in-progress status polling;
- streaming events;
- cancellation;
- expiration and timeout behavior;
requires_actiontool handoffs;- parallel tool calls;
- incomplete or failed terminal states;
- usage recorded at completion;
- background execution and webhook delivery.
Then map each behavior to Responses, background mode, streaming or application logic. A synchronous test that returns final text does not prove parity with an asynchronous Run workflow.
OpenAI's function-calling flow returns function_call Items; your code executes the function and supplies function_call_output with the matching call_id. Do not replace requires_action polling with a request that ignores these output Items.
Tool loops deserve their own state machine. Persist the Response or Item identifier, tool-call identifier, validated arguments, execution result and retry status before sending tool output back to the model. Use application-level idempotency for tools with side effects. A retried model request must not send the same email, charge the same order or modify the same record twice. The tool-call idempotency guide explains how to distinguish a retried business operation from a genuinely new one.
Treat each tool capability as its own migration
For OpenAI Responses, configure the hosted file_search tool in tools with vector_store_ids. Creating a Conversation does not select a knowledge base. Resolve the authorized stores for the current user or tenant in your application; do not assume an old Thread's tool_resources carries over.
Verify that each required store and file still exists, is accessible and has finished indexing. Keep original documents for anything that must be re-ingested. Check answer citations and request include: ["file_search_call.results"] when you need the retrieved evidence for comparison. Moving retrieval to external RAG requires its own ingestion and relevance validation, not a rename of OpenAI vector store IDs.
"Supports tools" is too broad to be an acceptance criterion.
Function calling requires schemas, argument validation, authorization, idempotency and result replay. File search requires a plan for files, vector stores, indexing state, citations and deletion. Code execution requires sandbox, file and timeout behavior. MCP introduces server authentication, tool discovery and a separate trust boundary. Computer use adds action authorization and a visual execution loop.
Build a capability matrix for every Assistant. At minimum, record these transitions and their parity evidence:
- Instructions: from Assistant configuration to a Prompt, request or gateway; validate with golden behavior tests.
- Functions: from Assistant tools to Responses functions or gateway tools; validate tool selection and side effects. If you stay on Chat Completions with a reasoning model, read why function tools with
reasoning_effortreturn a 400 first. - Retrieval: from file search and vector stores to Responses file search or external RAG; measure retrieval quality and verify citations.
- Code execution: from Code Interpreter to a Responses tool or owned sandbox; test files, timeouts and failures.
- Conversation state: from a Thread to a Conversation or application store; test resume behavior and ordering.
- Run lifecycle: from Runs and Run steps to Responses, Items and explicit orchestration; test streams, retries and terminal states.
Do not mark a capability complete because the target has a feature with a similar name. Test the behavior your product actually depends on.
Delegate configuration to a gateway, keep state in the application
AIVAX AI Gateways centralize model selection, provider connection, instructions, RAG collections, skills, tools, MCP sources, moderation, workers and generation controls. Applications call a gateway through the OpenAI-compatible /v1/chat/completions endpoint, setting model to its full ID or, with a private API key, its slug. Public keys require the full gateway ID.
This makes a gateway a useful target for the configuration and capability responsibilities that previously lived in an Assistant. It can reduce provider-specific model routing and keep instructions, retrieval, tools and safety controls out of each application request.
It is not a drop-in implementation of the OpenAI Responses or Conversations APIs, and AIVAX does not expose a public /v1/responses endpoint. Your application still sends the message history. A conversation_token adds only what that history cannot carry: the calls and results of server-side tools from earlier turns, which AIVAX restores before the model runs. That state expires after an hour without use. Use one token per conversation, never a value users choose: the token is not a credential, but anyone who can call your account with it continues that conversation's stored context. idempotency_key is a deprecated alias and must match conversation_token when both are sent.
If you choose the AIVAX route, use an application-owned state model:
- Store the canonical conversation and tool state in your application.
- Send the relevant OpenAI-compatible message history to the gateway.
- Send the same
conversation_tokenin every request of a conversation, and send back each assistant message'saivx_id(recommended; without it, AIVAX matches turns by tool call IDs, then by text). - Configure model policy, instructions, RAG and tools in the gateway.
- Keep side-effect authorization and idempotency in application code.
- Validate the gateway with the same task and tool-loop tests used for the old Assistant.
This route trades provider-managed conversation state for a more portable application contract. It is appropriate when portability and centralized AI operations matter more than direct access to Responses-native state and tools.
If your product depends heavily on OpenAI Conversations, hosted file search, background Responses or provider-specific Items, migrate to Responses first. A gateway should not be inserted where it would hide required semantics.
Cut over new traffic before backfilling history
A safe migration separates forward traffic from historical data.
Start by recovering the inventory: Assistant configuration, Thread mappings, tool schemas and Run behavior from source control, saved records and pre-shutdown exports. Check vector stores and file dependencies through the supported APIs, mark missing records explicitly — do not assume a fresh Assistants export is available — and establish task-level regression cases from real, sanitized workloads.
Then build one complete execution path on the target, including tools and failures, with correlation IDs that connect application requests, model calls, tool executions and final outcomes.
Replay and compare against captured baselines and deterministic fixtures rather than attempting live Assistants calls. Compare task outcome, tool choice, retrieval evidence, latency, usage and error behavior where your saved records support it. Do not compare text equality; model outputs are non-deterministic.
Route new conversations to the target first. For existing sessions, restore verified history or return a controlled migration or restart experience, and do not route users back to removed Assistants endpoints as a rollback strategy.
Backfill only the conversations that need continuity: reconcile item counts and supported content, record exceptions, and preserve the old-to-new identifier mapping.
Remove legacy dependencies last. Delete Assistants client calls, polling jobs, webhook handlers and feature flags only after traffic, logs and dependency scans show no remaining use, and retain migration evidence according to your audit and data-retention requirements.
Validate outcomes, not object creation
A migration test suite should exercise complete user goals. At minimum, cover:
- a single-turn answer;
- a multi-turn conversation resumed after process restart;
- one read-only tool call;
- one side-effecting tool call with a forced retry;
- parallel or sequential tool calls if supported;
- file input and retrieval with source verification;
- streaming interruption and recovery;
- cancellation or timeout;
- context growth near the model limit;
- malformed tool arguments;
- provider 429 and transient 5xx responses;
- an old conversation with unsupported content;
- usage and cost attribution;
- deletion and retention behavior.
Grade the final task outcome, the evidence used and the safety of the execution path. Endpoint status and object IDs are implementation checks, not proof that the assistant still works.
AIVAX Agentic Tests can evaluate bounded, multi-turn goals through an AI Gateway with a simulated user and a separate LLM judge. The multi-turn testing walkthrough shows how to define a goal and inspect the conversation evidence. They are useful for the gateway route because the evaluation follows the conversation outcome across turns rather than scoring one response in isolation. They do not replace deterministic tool authorization, migration reconciliation or provider contract tests.
Use this migration to reduce the next one
The Assistants shutdown exposes a common architecture problem: product behavior was attached to a provider's storage and execution objects rather than expressed as explicit application contracts.
Before cutover, record who owns configuration, conversation state, tool execution and retention.
Responses and Conversations are the closest OpenAI migration path. An application-owned history plus an AI Gateway is a portability-oriented alternative. Document any Responses-native behavior the gateway route cannot preserve.
AIVAX behavior described here reflects the platform's OpenAI-compatible inference API and its documentation as of November 5, 2026.