The Assistants API Stops Answering on 26 August
Four days left, and only one part of this migration has a deadline you cannot move: your threads become unreadable the moment the endpoints go. The code can wait a week. The export cannot.
On 26 August 2026, OpenAI removes the Assistants API endpoints. Not deprecated and still answering. Removed. /v1/assistants, /v1/threads, /v1/runs, every path your code still calls.
I first wrote this in July, when there was a month of runway. There are four days. That changes which half of the work matters. The code migration is a week of ordinary engineering and you can do it in September if you have to, because your users will simply see errors until you ship. The export is different. After the 26th, the thread contents are unreachable through the API whatever OpenAI’s internal retention says, and there is no tool coming to get them out for you.
So if you read one section of this, read the export one, and run it today.
Nobody is exporting your threads
OpenAI is explicit about this in the migration guide: “We will not provide an automated tool for migrating Threads to Conversations.” The suggested path is to read messages out of each thread and write them into a conversation yourself.
msgs = client.beta.threads.messages.list(thread_id=old_thread_id, order="asc")
items = [{"role": m.role, "content": m.content[0].text.value} for m in msgs.data]
conv = client.conversations.create(items=items)
That version flattens everything. Tool calls, file citations, annotations, run metadata: none of it survives a content[0].text.value extraction. Which is fine for most chat products, where all you need is enough context for the model to keep going. It is not fine if anyone might ask you for the record later, and the distinction is not one you get to revisit after Wednesday.
With four days left I would not agonize over the choice. Dump the raw API responses to disk first, unparsed, one JSON file per thread. That takes an afternoon to write and it preserves the option to decide properly in September. Parsing cold storage is a normal Tuesday. Recovering from an endpoint that returns 404 is not.
Budget for rate limits if you have tens of thousands of threads. Listing messages thread by thread is a lot of requests, and the window does not stretch to accommodate your retry backoff.
What replaces what
The replacement is two APIs, not one. Responses handles execution, Conversations handles state. Assistants folded both jobs into one object graph, which is why this feels less like a rename and more like taking apart something that used to arrive assembled.
| Assistants | Replacement | What changed |
|---|---|---|
| Assistant | Prompt | Model, instructions, tools, but managed through the dashboard |
| Thread | Conversation | A stream of items rather than only messages |
| Run | Response | No polling, you get output items back directly |
| Run step | Item | Generalized: messages, tool calls, and outputs are all items |
| Message | Item | The same object type as everything else now |
Five object types with distinct lifecycles became two ideas. You send input items, you get output items back. Tool calls, reasoning traces, file search results all arrive as typed entries in one list. That is genuinely simpler, and it is also why find-and-replace will not do it.
The polling loop goes away
If you wrote against Assistants you have some version of this in your codebase:
run = client.beta.threads.runs.create(thread_id=t.id, assistant_id=a.id)
while run.status in ("queued", "in_progress"):
time.sleep(0.5)
run = client.beta.threads.runs.retrieve(thread_id=t.id, run_id=run.id)
Plus the requires_action branch, where you run your functions, call submit_tool_outputs, and go back to polling. Everyone built a state machine around that. Everyone’s state machine had a subtle bug in it.
In Responses the call returns when it returns:
resp = client.responses.create(
model="gpt-5.1",
conversation=conv.id,
input=[{"role": "user", "content": "What changed in Q3?"}],
tools=[{"type": "file_search", "vector_store_ids": [vs.id]}],
)
Function calling still costs a round trip. The model emits a function_call item, you execute it, you send a function_call_output item back. But that is a request and a response, not a poll against an object with seven statuses. Deleting the state machine is the best part of this migration.
Retention is the part your compliance team will notice
State has three shapes now, and they are not equivalent.
The documented behavior is that response objects are saved for 30 days by default, and that conversation objects and the items in them are not subject to that TTL. So the migration that feels most natural, swapping threads for conversations one to one, quietly moves your retention posture from “OpenAI holds this for 30 days” to “OpenAI holds this until we say otherwise.” Threads behaved the same way, so you are not worse off than you were. You are worse off than whatever anyone wrote down after reading the Responses default.
The third row is the interesting one. Assistants never offered it. You hold the history yourself, pass it as input every time, and nothing persists on OpenAI’s side. For regulated workloads that trade is usually right, and you pay for it in tokens.
Which brings up the billing detail people get wrong: chaining with previous_response_id does not make prior turns free. All previous input tokens in the chain are billed as input tokens. Prompt caching may hit the repeated prefix, automatically, without a guarantee. Model the spend against your real conversation lengths before you promise anyone a number.
Tools carry over, the meters look different
file_search and vector stores come across. So does code_interpreter, and web_search, plus things Assistants never had: computer use, image generation, remote MCP servers. You attach the tool to the response instead of to the assistant.
Check the meters against your current bill, because the shapes differ. File search is $0.10 per GB of vector storage per day with the first GB free, plus $2.50 per 1,000 tool calls. Code interpreter is priced per 20-minute session and scales with container memory: $0.03 at 1 GB, $0.12 at 4 GB, up to $1.92 at 64 GB. Both figures came off the OpenAI pricing page on 22 August 2026.
Storage billed daily means abandoned vector stores cost money for as long as they exist. If your Assistants setup created a store per user session and never cleaned up, this week is a good excuse to find out what you are paying to keep alive.
The gaps the guide does not lead with
Feature parity is the official line and it is mostly true. Two exceptions are worth knowing before you scope the work.
Prompt objects are dashboard-first. You could create assistants programmatically, which meant per-tenant provisioning at runtime, versioning in code, management through Terraform. Prompt creation currently runs through the dashboard. If your product spins up assistants per customer, the replacement is to inline instructions and tools into each response call instead. That works. It also moves configuration out of a managed object and into your application, which is a different architecture than the one you have.
Truncation control is thinner. Assistants managed conversation length for you. Now you decide what history to send and when to summarize, which is real work on long-running conversations and real token cost when you get it wrong.
Azure: same date, different destination, and a tool that helps
The common assumption is that Microsoft runs its own calendar and you get extra runway. You do not. Microsoft’s answer is that the Assistants API “is deprecated and will be retired on August 26, 2026,” the same day, with Microsoft Foundry Agents as the destination.
Unlike OpenAI, Microsoft ships a migration tool. It rewrites code constructs: agent definitions, thread creation, message creation, run creation. It does not move state, and the docs say so plainly: past runs, threads, and messages stay behind. Which means the Azure story has the same four-day export problem as the OpenAI one, wrapped in better tooling for the part that was never urgent.
One naming trap worth clearing up in planning meetings, because it burns an hour every time: Foundry agents (classic) retire on 31 March 2027. That is a different product on a different clock. If someone tells you they have until 2027, check which one they are actually running.
If you use a third-party host that emulated the Assistants wire format, get their timeline in writing. Some will keep the surface alive past August as a differentiator. That is a fine bridge and a bad destination.
Is Responses even where you want to land?
Fair question, and this is the second forced migration OpenAI has handed developers in short order. If you are rewriting anyway, it is worth an afternoon asking whether you want to be this exposed to one vendor’s roadmap.
Routing through a gateway is one answer. LiteLLM, Portkey, or OpenRouter give you one interface across providers, so the next deprecation is a config change rather than a sprint, and you pay in an extra hop plus some lag on brand-new capabilities. Moving to a framework is the other. LangGraph, Pydantic AI, and Mastra abstract state and tool orchestration so provider changes hit one adapter. Heavier upfront, and you have traded vendor lock-in for framework lock-in, which is a trade rather than an escape.
My read: if your Assistants usage is chat plus file search, go straight to Responses and finish in a week. If you built real orchestration on top of runs and tool outputs, you are rewriting that layer regardless, so spend two extra days deciding whether it should sit behind an abstraction this time.
What four days buys
Not the migration. The migration takes as long as it takes and the endpoints failing is a bad afternoon, not a lost quarter.
What it buys is the data. Grep for beta.threads, beta.assistants, and submit_tool_outputs. Count your threads. Write the dumbest possible exporter that writes raw JSON to disk, run it tonight, and check that the files have content in them before you go to bed. The clever version can be written any time. The source data cannot.