OpenAI Prompt Objects and Agent Builder shut down November 30: what you lose and where each piece can live
OpenAI retires reusable prompt objects (v1/prompts) and Agent Builder on November 30, 2026. Copying the text into code is the easy part; hosted editing, rollback and hosted tools each need a new owner. This post reads the code behind each option and runs the parts that work offline.
OpenAI shuts down reusable prompt objects (v1/prompts, the pmpt_ IDs) and Agent Builder on November 30, 2026. Its migration guides give the same instruction for both: take what you built in the dashboard and put it in code. For a prompt object that means copying a block of text. The dashboard did three other jobs around that text. Someone could edit the prompt without a deploy, the edit applied to the next request, and the previous version was one click away. OpenAI's support account said in September that it has no timeline for a hosted replacement, so each of those jobs needs an owner on your side, and you have five weeks to pick one.
OpenAI says move the text, and its staff have no timeline for a hosted editor
The deprecations page lists both shutdowns on the same date and says ChatKit remains available. Evals, which I covered in its own post, goes read-only on October 31 and shuts down on the same November 30. The prompt-object guide lists what changes: the content moves into source, variables become typed function arguments, the messages go in input, versioning moves to git, and static content goes first so that prompt caching still hits, the same prefix rule behind a low cache hit rate. It says rollout and experimentation can be managed "through your own config or feature flags." That describes the code change accurately, but it does not say who edits the prompt afterwards.
Developers asked exactly that in the forum thread on June 4, the day after the announcement. One wrote that stored prompts let them "make small fixes to the prompt without redeploying, and also rollback to previous versions". Another listed "application independent, rapid prompt development, model optimizations and hotfixing" as the advantage that a move into the codebase does not keep. On September 9 an OpenAI support account replied: "We hear the loss of hosted editing and quick rollback, and we'll pass that feedback along. We don't have a timeline for an equivalent hosted replacement." Two days earlier, in a thread asking for prompt CRUD endpoints, the same account had said the migration guide "doesn't add the hosted management APIs you requested."
Agent Builder lost the same things. A workflow there was published as a versioned snapshot, and the Agent Builder page says you could pass an older version in your API calls. The migration guide offers an export as Agents SDK code and says up front that the process "does not convert your workflow graph or guarantee that every behavior transfers unchanged."
The text moves cleanly, and the dashboard's other jobs do not
A forum participant who compared the tokens billed for a prompt ID against its contents posted what the object holds: instructions, model, reasoning effort, temperature, top-p, tool choice and tools, which is the parameter set you would send with any request. The same participant says you cannot retrieve a prompt by ID over the API. So copy from the dashboard while it is open, and copy every version you might want to return to, not only the latest. OpenAI does not say whether old versions stay readable after November 30, and I would assume they do not.
Where the text goes next is a decision about who edits it and how fast. My view is that if only engineers change your prompts, git and a deploy is a fair trade, and arguably better than the dashboard, because the prompt gets reviewed together with the code that parses its output. Where support or product staff tune wording daily, expect them to ask for a small store with an edit page, which a forum reply suggests building on your own database, or to file tickets for one-line deploys. The last two rows below use an AIVAX gateway, which the next two sections explain.
| Where the text lives | A change ships by | Rollback | What to watch |
|---|---|---|---|
| Your repository | Pull request and deploy | Revert and deploy | Every wording change needs a release. |
| Your own database or config service | An edit in an admin page you build | Restore a stored version, if you keep versions | You own the editor, the history and the access control. |
| A file in git that an AIVAX gateway fetches as a remote instruction source | Merge to the file's branch; applies when the gateway's cached copy expires (600 seconds by default) | Revert the commit; live after the cache expires | A failed fetch silently removes the text, and the URL must be readable without credentials. |
The gateway's own systemInstruction | A PATCH to the gateway | None built in; keep the JSON in git and PATCH it back | No version history on the AIVAX side. |
OpenAI's Assistants migration guide still walks you through turning each assistant into a prompt object, with a note that prompt objects are being deprecated. If you followed it, the Assistants post covers the state side of that move.
An AIVAX gateway gives you an editing surface and no history
This is AIVAX's blog and the gateway is our product, so weigh this section with that in mind. An AI gateway stores the model, systemInstruction, userPromptTemplate, remote instruction sources (URLs whose text is appended to the instruction), tools and RAG collections behind a name. Your application sends the gateway's slug as model to https://inference.aivax.net/v1/chat/completions. The slug is the gateway's name plus the last four characters of its ID, such as support-bot:50c3, and a public API key needs the full ID instead. The docs describe the use case as behavior that is "changed without redeploying the calling application." A gateway is not a drop-in for the Responses API, and I found no way to reference a pmpt_ ID from one, so the text has to come out of the dashboard first.
A gateway can be read back. GET /api/v1/ai-gateways/<id> returns its configuration, and when I serialized that response with the JSON settings the server configures at startup, the apiKey field (your own provider key, when the gateway uses one) came back in clear. Strip it before the file goes near git, and look at the headers of any source or MCP entry for tokens too. The API reference lists the edit as PATCH /api/v1/ai-gateways/<id>, and the two calls make a rollback you build yourself:
GW="https://inference.aivax.net/api/v1/ai-gateways/$GATEWAY_ID"
AUTH="Authorization: Bearer $AIVAX_API_KEY"
curl -fsS -H "$AUTH" "$GW" | jq '.data.parameters | del(.apiKey)' > support.json
jq '{parameters: .}' support.json |
curl -fsS -X PATCH -H "$AUTH" -H "Content-Type: application/json" -d @- "$GW"
AIVAX keeps no history of its own. I found no revision, version or rollback in the gateway controller, repository, model or migrations, so the file above is the history. Omitting a key from the PATCH does not remove it from the gateway, so restoring a file from before you added a key will not take that key away. From reading the code, the gateway is loaded from the database on each request with no cache in between, so a PATCH should apply on the next one. That covers editing without a deploy and applying immediately, the first two jobs; the third, rollback, is the git file.
The PATCH merge is shallow, and I ran the product's own merge function on four bodies to see what that means. A top-level key you send replaces the stored one. Sending systemInstructionsSources with one entry left exactly that one entry; the previous two were gone, so send the complete list. The same replacement applies one level down. In the nested queryStrategyParameters object I set rewriteContextSize to 7 and concatenateContextSize to 9, and both default to 3. A body that sent only "queryStrategyParameters": {"rewriteContextSize": 5} came back as 5 and 3, because the 9 reverted to its default. And a misspelled key, foo in my test, was dropped by the merge without an error, so read the gateway back after every PATCH and compare it with the file.
Hosting the prompt text in git works, but a failed fetch silently leaves it empty
The third table row is the closest thing to the hosted editor. A gateway accepts systemInstructionsSources, a list of URLs it fetches as text and appends after the base instruction. This is the part of support.json that holds one:
{
"systemInstructionsSources": [
{
"name": "support-policy",
"url": "https://prompts.example.com/support/policy.md",
"cacheDuration": 60
}
]
}
I set cacheDuration to 60 so that a bad edit stays live for at most a minute; the default is 600. I fed this path a fake HTTP handler and counted what happened. A 200 response is cached for cacheDuration seconds, so the second request inside the window makes no fetch. A 500, a 404, a thrown connection error, a URL that points at localhost or a private address, and a body over the limit all produce the same result: the request goes on without the text. The limit is 5 MB in the docs and 5,242,880 bytes in the code; I sent 6 MiB, and a 4 MiB body came through whole. The model sees the source's name as a Markdown heading, # support-policy, followed by nothing. This matches the pipeline docs, which say a source that cannot be read "contributes no text and the request itself does not fail."
What the docs leave out is how long the failure lasts. The empty result is cached like a good one. With the default 600 seconds, a host that returns a 500 once and recovers a second later still leaves the gateway without its prompt for ten minutes. There is also no stale-if-error: when the cached copy expires while the host is down, the good prompt is replaced by the empty one. I found no log line or error field for a failed fetch, so the first sign you get is the model behaving differently.
The cache lives in each server process's memory, so processes that serve the same gateway can disagree until their copies expire, and the docs do not say how many there are. The headers field on a source is accepted but, in the code I tested, it only separates cache entries; the fetch does not send it, while the same field is sent when AIVAX connects to an MCP server. A source behind authentication therefore fails like any other error and becomes the empty prompt, so the file has to be readable by anyone with the URL. If the account has a hook key, the fetch carries an X-Request-Nonce header that your server can verify, which I confirmed in process, but the docs describe that header for workers and protocol functions, so treat it as undocumented here.
My recommendation follows from that. Keep the rules the product cannot work without in the gateway's own systemInstruction, which is always present, and host only the part people edit often. After each merge, have CI ask the gateway a question whose answer exists only in the file. And choose cacheDuration as your rollback delay: 0 fetches on every request and makes your host part of the request path, while 600 means a bad edit and its fix are each live for up to ten minutes.
Agent Builder code moves to another provider only until it reaches a hosted tool
The node reference shows where a workflow's pieces sit. A file-search node retrieves from vector stores "you've created in the OpenAI platform", so exporting code does not move the documents; leaving OpenAI means re-ingesting them, for example into an AIVAX collection that you attach to a gateway. If/else and While nodes become ordinary control flow in your code. The human-approval node becomes the SDK's own approval flow, which pauses the run in your process, and AIVAX's guide to approvals covers the design side.
I did not export a real workflow. To see what happens when Agents SDK code is pointed at another provider, I wrote an agent by hand and ran it against a local stub of the Chat Completions endpoint. This is the code, with AsyncOpenAI aimed at the gateway and a function tool running in your own process; tracing is switched off for a reason explained below.
import os
from agents import (Agent, AsyncOpenAI, OpenAIChatCompletionsModel, Runner,
function_tool, set_tracing_disabled)
set_tracing_disabled(True)
client = AsyncOpenAI(
base_url="https://inference.aivax.net/v1",
api_key=os.environ["AIVAX_API_KEY"],
)
model = OpenAIChatCompletionsModel(model="support-bot:50c3", openai_client=client)
@function_tool
def get_order_status(order_id: str) -> str:
return f"Order {order_id} shipped"
agent = Agent(name="Support", model=model, tools=[get_order_status])
print(Runner.run_sync(agent, "Where is order 1042?").final_output)
openai-agents 0.24.0 made two POST /v1/chat/completions requests and never called /v1/responses. The model string arrived unchanged, the key went out as a bearer token, and the tool call came back to the process that ran the agent, which executed the function and sent the result as a tool message. With no instructions on the Agent, the request carried no system message from the client; with instructions, the SDK sends a system message.
The tool list is what breaks. When I gave the same agent a WebSearchTool or a FileSearchTool, the run failed before any request was sent: "Hosted tools are not supported with the ChatCompletions API." The SDK's tools documentation lists web search, file search, code interpreter, hosted MCP and image generation as tools for its Responses model only. Code that uses them cannot simply have its base_url changed. You replace each one with a function tool or an MCP server you run, or you stay on OpenAI's Responses API and keep them. The function-tools post covers the other Chat Completions limit you may meet on the way.
Tracing is the second thing that does not follow the model. The SDK docs say tracing is on by default, that generation and function spans capture inputs and outputs unless trace_include_sensitive_data is turned off, and that the exporter authenticates with OPENAI_API_KEY. I removed set_tracing_disabled(True) and ran the agent with and without a dummy OPENAI_API_KEY. Without it, the SDK printed one line saying it was skipping trace export. With it set, the SDK tried to reach api.openai.com three times, and each attempt failed because my proxy setting refused it. The failures were logged as non-fatal, and the run took about 9 seconds instead of 3 or 4. By the SDK's documentation, someone who moves off OpenAI and still has that variable exported would be sending prompts and tool outputs to OpenAI's trace dashboard unless they disable tracing or set a tracing key on purpose.
ChatKit is a separate question, and AIVAX does not answer it. OpenAI's ChatKit guide keeps two paths: your own server with the ChatKit Python SDK, and the Agent Builder-hosted integration that works only during the transition window. An AIVAX gateway can serve a chat client, but it is not a ChatKit server. The forum thread on the Agent Builder deprecation shows what the self-hosted path costs. One developer who served several clients from the hosted backend called migrating it "economically unviable"; another measured 20 concurrent cold starts of a FastAPI ChatKit server on a Lambda container, with initialization between 2.5 and 3.4 seconds. Those are one developer's numbers on one platform.
The order I would work in
- Search your code and deployment config for
pmpt_and forprompt:in Responses calls, and copy every version that matters out of the dashboard. - Export each Agent Builder workflow while the product is still open. I would not expect an export option to survive its shutdown.
- Decide the owner of each prompt with the table above, because a prompt that support edits weekly and one that changes twice a year do not need the same answer.
- Run the exported code against the provider you plan to use, and read the failure about hosted tools now, not on November 30.
- If a gateway will hold any of it, put its JSON in git first and test a PATCH on a copy.
- If you have evals on OpenAI's platform, save their datasets and graders before October 31.
Read on 2026-10-26: OpenAI's deprecations page, the prompt-object and Agent Builder migration guides, the Agent Builder, node-reference and ChatKit pages, the Agents SDK tracing and tools documentation, and the forum threads quoted above; the AIVAX gateway, authentication and pipeline docs, the API reference and the server code behind them. I ran the product's remote-instruction fetch with a fake HTTP handler (text/plain only; redirects and the real 30-second timeout were not exercised), the JSON serialization of a gateway view, and the PATCH merge function, all in process, and the Agents SDK against a local stub of Chat Completions. I made no call to a live AIVAX account, to OpenAI or to a model provider, so the curl commands come from the endpoint definitions, the git round trip is untested, and I did not time how fast an edit takes effect. The unknown-key result comes from the merge function alone, not from a saved gateway. I did not export a real Agent Builder workflow, test the approval flow against a gateway, or capture the body of the trace request.