Softotic
Back to insights
30 August 202617 min readOpenAIResponses APIAI AgentsNode.jsAPI Migration

OpenAI Assistants API Is Gone: How to Migrate to Responses API in 2026

OpenAI shut down the Assistants API on August 26, 2026. This migration guide explains how to move Assistants, Threads and Runs to Responses and Conversations without building on another deprecated object.

OpenAI Assistants API Is Gone: How to Migrate to Responses API in 2026

OpenAI's Assistants API was officially sunset on August 26, 2026 and is no longer available. If a production application still depends on Assistants, Threads or Runs, this is no longer a future deprecation task: the integration needs to move to the Responses API and, where persistent server-side conversation state is required, the Conversations API.

The migration is not a simple endpoint rename. OpenAI now separates configuration, conversation state and execution differently, and your application takes more explicit responsibility for orchestration. There is another trap as well: OpenAI's migration guide maps Assistants to reusable Prompt objects, but those Prompt objects are themselves scheduled to shut down on November 30, 2026.

The durable migration is therefore:

text
Assistant configuration
→ application-owned configuration

Threads
→ Conversations or application-owned history

Runs
→ Responses

Run steps
→ Response/Conversation items

This guide shows what changed, what can still be migrated after the shutdown, and how to avoid finishing one forced migration only to schedule another.

Is the OpenAI Assistants API still available?

No.

OpenAI's current Assistants migration guide states that the Assistants API was officially sunset on August 26, 2026 and is no longer available.

OpenAI's deprecations page lists the same shutdown date and gives the recommended replacement as:

  • Responses API
  • Conversations API

This distinction matters because older articles and code examples may still describe the shutdown as an upcoming deadline.

As of August 31, 2026, code built around patterns such as:

js
openai.beta.assistants
openai.beta.threads
openai.beta.threads.runs

should be treated as legacy migration code, not a supported production architecture.

What replaces Assistants, Threads and Runs?

OpenAI's migration guide publishes this conceptual mapping:

Assistants APICurrent directionEngineering consequence
AssistantsPrompts in the migration guideConfiguration is separated from execution
ThreadsConversationsConversation state becomes a stream of items, not only messages
RunsResponsesModel execution moves to Responses
Run stepsItemsMessages, tool calls and outputs share a more general item model

The table is useful, but following it mechanically creates a problem.

Do not automatically migrate Assistants into long-lived Prompt objects

OpenAI's own migration guide warns that reusable Prompt objects are also deprecated.

OpenAI's deprecations page says:

  • reusable Prompt deprecation was announced on June 3, 2026
  • the __INLINE_CODE_0__ API and reusable Prompt objects are scheduled to shut down on November 30, 2026
  • the recommended migration is to move reusable prompt content into application code

So this path has a very short shelf life:

text
Assistant
→ reusable Prompt
→ migrate again before November 30

For a new migration started after the Assistants shutdown, a more durable architecture is usually:

text
Application repository/config store
├── model policy
├── instructions
├── tool definitions
└── output contract
        ↓
Responses API

That is not a workaround. OpenAI's current text-generation documentation explicitly supports passing high-level behaviour through the __INLINE_CODE_0__ parameter, while the Responses API accepts tool definitions directly in the request.

A durable Node.js configuration pattern

Instead of creating one persistent Assistant object per agent, keep the agent contract in application-owned configuration.

For example:

js
// agents/support-agent.js
export const supportAgent = {
  model: 'gpt-5.6',
  instructions: `
    You are the support assistant for our SaaS.
    Answer from approved product knowledge.
    Never invent account or billing state.
    Use tools when live account data is required.
  `,
  tools: [
    {
      type: 'function',
      name: 'get_account_status',
      description: 'Get the current account status for an authenticated user.',
      parameters: {
        type: 'object',
        properties: {
          userId: { type: 'string' }
        },
        required: ['userId'],
        additionalProperties: false
      },
      strict: true
    }
  ]
}

Then pass that contract into Responses:

js
import OpenAI from 'openai'
import { supportAgent } from './agents/support-agent.js'

const openai = new OpenAI()

export async function createSupportTurn({ conversationId, text }) {
  return openai.responses.create({
    model: supportAgent.model,
    instructions: supportAgent.instructions,
    tools: supportAgent.tools,
    conversation: conversationId,
    input: [
      {
        role: 'user',
        content: text
      }
    ]
  })
}

The exact model and tools should match your production requirements. The architectural point is that configuration is versioned with the code or configuration system that depends on it.

This gives you normal software controls:

  • Git history
  • code review
  • environment promotion
  • automated tests
  • rollback
  • tenant-specific configuration
  • feature flags

It also avoids making November's Prompt-object shutdown your next emergency.

Threads become Conversations, but the state model is broader

An Assistants Thread stored messages.

The current conversation-state documentation says a Conversation is a long-running object with a durable identifier that can be reused across sessions, devices or jobs.

Conversations store items, which can include:

  • messages
  • tool calls
  • tool outputs
  • other response data

A basic Node.js flow looks like:

js
const conversation = await openai.conversations.create()

const response = await openai.responses.create({
  model: 'gpt-5.6',
  conversation: conversation.id,
  instructions: 'Answer questions about the product accurately.',
  input: [
    {
      role: 'user',
      content: 'How do I change my subscription?'
    }
  ]
})

console.log(response.output_text)

Store the Conversation ID against your own user/session/domain record rather than passing it around anonymously.

For example:

text
users
  id

ai_conversations
  id
  user_id
  provider
  provider_conversation_id
  created_at
  archived_at

That keeps OpenAI's identifier as an integration detail instead of turning it into your application's primary business identity.

Should you use Conversations or __INLINE_CODE_0__?

OpenAI supports two main server-managed continuation patterns with Responses.

Use a Conversation when the dialogue is a durable product object

Choose Conversations when the state should survive across:

  • sessions
  • devices
  • background jobs
  • multiple application requests

Examples include:

  • customer-support assistants
  • long-running onboarding assistants
  • persistent research workspaces
  • account-bound AI conversations

OpenAI says Conversation objects and their items are not subject to the default 30-day Response-object TTL.

Use __INLINE_CODE_0__ for simpler response chains

OpenAI also supports chaining Responses by passing the prior response ID:

js
const first = await openai.responses.create({
  model: 'gpt-5.6',
  input: 'Explain our refund policy.'
})

const second = await openai.responses.create({
  model: 'gpt-5.6',
  previous_response_id: first.id,
  input: 'Summarise that in two bullets.'
})

This is useful when you need continuity without creating a separate Conversation object.

However, OpenAI's documentation notes two important details:

  1. Response objects are stored for 30 days by default, unless storage is disabled or the response is attached to a Conversation.
  2. Even when using __INLINE_CODE_0__, previous input tokens in the chain are still billed as input tokens.

So choose the state model intentionally rather than using __INLINE_CODE_0__ as a permanent conversation database.

What happened to the Run lifecycle?

Assistants applications often looked like this:

text
Create message
→ create Run
→ poll Run status
→ requires_action?
→ submit tool outputs
→ continue polling
→ read messages

Responses removes the old Run object.

OpenAI's migration guide says Runs become Responses and that tool-call loops are explicitly managed.

That changes application responsibility.

Your orchestration layer now needs to know how to:

  • inspect response items
  • identify function calls
  • execute approved application functions
  • send tool outputs back
  • handle retries/timeouts
  • enforce limits on tool loops
  • record tool failures

For a function tool, the high-level flow becomes:

text
User input
    ↓
Responses API
    ↓
Function call requested?
├─ no → return answer
└─ yes
    ↓
Validate arguments
    ↓
Authorise action
    ↓
Execute application function
    ↓
Send function-call output
    ↓
Responses API
    ↓
Final answer / another permitted tool call

This explicit loop is a feature from an architecture perspective: your application can put authorization, auditing, timeouts and budget controls around tool execution.

It is also code that must be tested. Do not treat it as a one-line endpoint migration.

What happens to old Thread history after the shutdown?

This is now one of the most important migration questions because August 26 has already passed.

OpenAI's current migration guide says to start new chats with Conversations and Responses and to preserve earlier conversation history using messages already stored by your application.

The guide also states that the old Assistants API call for retrieving Thread messages no longer works after sunset.

That means your recovery options depend on what you retained before the shutdown.

If your application already stored message history

You can map that history into a new Conversation or reconstruct the context your product actually needs.

A sensible migration job should preserve:

text
internal user/conversation ID
old Thread ID for audit/reference
message role
message text/content
message timestamp
new Conversation ID
migration status

Do not make migration depend only on a provider ID.

If your database stored only Thread IDs

Do not write a migration script that assumes it can still call the legacy Thread-message endpoint. OpenAI's current guide explicitly says that retrieval call no longer works.

First inventory what conversation content exists in your own:

  • application database
  • event logs
  • analytics/event pipeline
  • support transcripts
  • backups
  • data exports retained before shutdown

Only migrate data you can actually verify and are permitted to retain.

Do not fabricate missing conversation history or silently pretend a new empty Conversation contains the old context.

Should you migrate every historical conversation?

Usually not.

A forced API migration is a good moment to decide what history still has product value.

Use a retention decision such as:

Conversation typeSuggested migration decision
Active customer conversationMigrate required context
Recently active support threadMigrate if continuity matters
Closed historical threadArchive in your own system rather than rehydrate automatically
Test/development threadUsually discard
Orphaned Thread with no ownerInvestigate before migration
Data beyond your retention policyDelete rather than migrate

Migration should respect your privacy and retention policy, not turn every historical test chat into permanent production state.

File search, vector stores and tools need a separate inventory

Many Assistants integrations were more than conversations.

Before declaring the migration complete, inventory every Assistant resource dependency:

text
Assistant
├── instructions
├── model selection
├── function tools
├── file search
├── vector stores/files
├── code execution workflows
└── application-side metadata

The Responses API supports built-in tools and function calling, but your application contract has changed.

For each tool, verify:

  1. the current Responses API schema
  2. authentication and authorization
  3. tool-call argument validation
  4. timeout behaviour
  5. retry/idempotency behaviour
  6. audit logging
  7. error messages returned to the model
  8. rate and spend limits

Do not port a function definition and assume the surrounding security model migrated with it.

Migration mistake 1: rebuilding on deprecated Prompt objects

The most avoidable mistake in late August 2026 is finishing the Assistants migration by creating a large dependency on reusable Prompt objects.

OpenAI's own migration guide now warns against adopting them for long-lived integrations, and OpenAI's deprecations page schedules them to shut down on November 30, 2026.

For most application-owned agents, prefer:

text
Versioned instructions in your repository/config service
+
versioned tool schemas
+
Responses API request

If you have a specific reason to use a short-lived Prompt object during transition, document the November deadline and the second migration explicitly.

Migration mistake 2: treating Conversations as your user database

A Conversation ID is an external provider resource.

It should not replace your own:

  • user ID
  • account ID
  • tenant ID
  • case/ticket ID
  • authorization model
  • retention policy

Your database should decide who is allowed to access a conversation.

OpenAI should receive the conversation reference only after your application has authenticated and authorised the request.

Migration mistake 3: trusting tool calls without authorization

A model requesting a function does not mean the user is authorised to perform it.

Bad pattern:

text
model calls cancel_subscription
→ backend executes it

Better:

text
model calls cancel_subscription
→ validate schema
→ authenticate actor
→ check account ownership/role
→ require confirmation if needed
→ execute idempotently
→ audit
→ return tool result

Treat model tool calls as requested actions, not trusted commands.

Migration mistake 4: comparing only text output

A migration can produce plausible answers while still breaking the product.

Test at least:

  • conversation continuity
  • tool selection
  • tool arguments
  • permission failures
  • file/retrieval behaviour
  • structured outputs
  • streaming behaviour
  • latency
  • token usage
  • error recovery
  • cancellation/timeouts
  • duplicate/retry behaviour around external tools

The correct success criterion is not:

text
"The response looks similar."

It is:

text
"The new workflow preserves the product's required behaviour and controls."

A practical post-sunset migration plan

Because the Assistants endpoint is already gone, a team starting now should work in this order.

Step 1: find every legacy dependency

Search the codebase for patterns such as:

text
beta.assistants
beta.threads
threads.runs
assistant_id
thread_id
run_id
requires_action
submit_tool_outputs

Also search infrastructure, workers, serverless functions and scheduled jobs, not only the main API server.

Step 2: classify each old Assistant

For each Assistant, record:

  • business purpose
  • model
  • instructions
  • tools
  • file/vector dependencies
  • tenants/users depending on it
  • whether configuration was dynamic

Then rebuild the configuration in code/configuration you own rather than making reusable Prompts the long-term destination.

Step 3: choose conversation ownership

For each flow decide:

text
Durable provider-managed state?
→ Conversations

Short response chain?
→ previous_response_id

Strict application-owned history/control?
→ store context yourself and send required input

You do not need one state strategy for every AI feature.

Step 4: port tool orchestration

Implement and test the explicit function-call loop.

Add:

  • authorization
  • validation
  • maximum tool iterations
  • timeouts
  • retry policy
  • idempotency for consequential actions
  • structured logging

Step 5: recover only history you actually have

Map application-stored history into new conversations where continuity matters.

Keep a migration table so retries are safe:

text
legacy_thread_id
new_conversation_id
migration_status
last_attempt_at
error

Step 6: replay production-like fixtures

Since the old API is already unavailable, you cannot rely on live side-by-side execution against Assistants.

Use retained fixtures and expected outcomes:

text
input
expected policy behaviour
expected tool call or no tool call
expected structured fields
expected authorization result

Evaluate behaviour, not wording equality.

Step 7: deploy with observability

Monitor:

  • Responses API error rate
  • latency
  • tool-call failure rate
  • average tool iterations
  • token usage
  • conversation creation/reuse failures
  • missing migrated history
  • user fallbacks/escalations

Keep provider request IDs in structured logs where appropriate so production failures can be investigated.

A reference architecture after Assistants

A durable SaaS integration can look like:

text
Web / mobile client
        ↓
Application API
        ↓
Authentication + tenant authorization
        ↓
AI orchestration service
        ├── agent config from source control/config store
        ├── conversation mapping
        ├── tool authorization
        ├── retries / limits
        └── observability
        ↓
OpenAI Responses API
        ↕
Conversations API
        ↓
Approved tools
├── CRM
├── billing
├── product database
└── knowledge retrieval

The important ownership boundary is clear:

OpenAI runs the model and supported AI primitives.

Your application owns business identity, authorization, configuration lifecycle and consequential actions.

That boundary makes the next API change much cheaper to absorb.

Should new OpenAI projects use Chat Completions or Responses?

For new agent-style integrations, OpenAI recommends the Responses API.

OpenAI originally introduced Responses as the future direction for applications that combine models with built-in tools and multi-step workflows. It supports direct instructions, tools and state-management options without the old Assistants/Threads/Runs lifecycle.

Chat Completions is a different API and should not be confused with the Assistants shutdown.

If your product already has a simple, stable Chat Completions integration and does not need Responses-specific capabilities, evaluate migration on its own merits rather than treating August 26 as its deadline.

The deadline applied to Assistants API, not every OpenAI API integration.

A migration acceptance checklist

Before calling the migration complete:

  • No production code calls Assistants/Threads/Runs endpoints.
  • Agent instructions/configuration have a deliberate long-term home.
  • The design does not accidentally depend on reusable Prompts past November 30, 2026.
  • New persistent chats use Conversations where appropriate.
  • Conversation IDs are mapped to authenticated application identities.
  • Tool schemas are current for Responses.
  • Tool execution is authorised independently of model output.
  • Consequential tools are idempotent where needed.
  • Historical context is migrated only from verifiable retained data.
  • Missing legacy history has an explicit product fallback.
  • Function-call loops have limits, retries and logs.
  • Token usage and latency are monitored after release.
  • Response retention and conversation retention choices match product policy.
  • Production fixtures cover expected AI behaviour and failure modes.

If several boxes remain open, the code may compile while the migration is still operationally incomplete.

FAQs

When did OpenAI shut down the Assistants API?

OpenAI officially sunset the Assistants API on August 26, 2026. Its current migration documentation states that the API is no longer available and recommends Responses API plus Conversations API.

What replaces an OpenAI Thread?

For durable server-side conversation state, the current replacement is the Conversations API. Conversations store a stream of items that can include messages, tool calls and tool outputs.

What replaces an OpenAI Run?

Runs are replaced by Responses. The Responses API handles model execution, while application code takes explicit responsibility for orchestration such as function-tool loops and retries.

Should I migrate an Assistant to a reusable Prompt object?

Not as an unexamined long-term design. OpenAI's migration guide maps Assistants to Prompts but also warns that reusable Prompt objects are deprecated. OpenAI schedules those objects and the __INLINE_CODE_0__ API to shut down on November 30, 2026 and recommends moving reusable prompt content into application code.

Can I still fetch old Thread messages after August 26?

OpenAI's current migration guide says the Assistants API call used to retrieve Thread messages no longer works and tells developers to use messages already stored by their application when preserving earlier history.

Do Responses retain conversation history forever?

Not exactly. OpenAI says normal Response objects are stored for 30 days by default, while Conversation objects and their items are not subject to that 30-day TTL. Choose the state model and your own retention policy deliberately.

Conclusion

The Assistants API migration is now a recovery and architecture task, not a deadline reminder.

The old stack is gone:

text
Assistants
Threads
Runs
Run steps

The durable replacement is not simply another set of renamed OpenAI objects.

A safer long-term model is:

text
Application-owned configuration
        ↓
Responses API
        ↕
Conversations where durable state is needed
        ↓
Application-owned authorization and tools

That design avoids two expensive mistakes: depending on an API that has already shut down, and moving directly onto reusable Prompt objects that OpenAI is also retiring on November 30, 2026.

If your SaaS, chatbot or AI workflow still needs to be moved from the old Assistants architecture, Softotic's AI and machine learning service can help redesign the agent and tool layer, while custom software development can handle the surrounding conversation, authorization and backend integration architecture.

Sources and references