# Prompts API and Agent Builder end Nov 30: export and rehost

URL: https://infro.io/blog/prompts-api-and-agent-builder-end-nov-30-export-and-rehost
Author: INFRO Editorial (https://infro.io/blog/editorial)
Publisher: INFRO
Published: 2026-10-28
Last modified: 2026-10-28
Last reviewed: 2026-10-28 (next review due 2026-11-27)
Topic: Architecture and migration
Format: Guide

> The Prompts API and Agent Builder are scheduled to end on 30 November 2026, with the same date as the Evals platform. [^infro-evals] Treat prompts as files in your repository, call models through one thin layer with a route name instead of a model id, and replay recorded inputs through old and new paths before cutting over.

Key takeaways:
- The reusable prompts API and Agent Builder share the 30 November 2026 shutdown date with the Evals platform, so a team using all three has one deadline.
- Move prompt text, model, parameters and variables into versioned files in your repository, and give each file a content hash so you can prove what shipped.
- Call models through one thin function that takes a route name, so the vendor and model live in configuration rather than in application code.
- Rebuild an Agent Builder workflow as ordinary code with explicit step, time and token limits, one function per node.
- Cut over only after a replay test passes on recorded real inputs, then ramp traffic with a weighted split and keep the old path until the last day.

## What is ending, and what the date leaves you

OpenAI's reusable prompt objects and the v1/prompts API, Agent Builder and the Evals platform share one shutdown date: 30 November 2026.[1] INFRO's timeline lists the three as a single shutdown entry and shows it 34 days out on 27 October.[2] Today is 28 October, so you have 33 days. The Evals half of this is covered in [OpenAI Evals shuts down: export your evals and rebuild them in CI](https://infro.io/blog/openai-evals-shutdown-migration); evals turn read-only on 31 October, three days from now.[3]

For prompts, the advice quoted in that article is to move their content into your application code.[1] That sentence is the whole official migration path as far as INFRO's pages report it, and it leaves out most of the work: where the text lives, how you version it, how you call the model afterwards, and how you know the new path behaves like the old one. This guide covers those parts, and the workflows built in Agent Builder.

One limit on what follows. OpenAI's own pages would not load when this was written, so the exact export calls for hosted prompts and any code export in Agent Builder are not described here. Check OpenAI's current reference for those, and use the plan below for everything after the export.

## Inventory before you export

You cannot migrate what you have not found. Start with a list of every place that depends on the hosted objects, because the dependency is often a string id buried in code or in a no-code tool.

1. Search every repository and config store for the ids of stored prompts and for calls that reference a stored prompt by id and version.
2. List every production path that runs an Agent Builder workflow, including scheduled jobs and anything a non-engineer wired up.
3. For each prompt, record the owner, the model it was pinned to, its variables, which version production uses, and whether any evals reference it.
4. Check your provider usage for traffic that does not appear in your own logs, since a prompt id can be called from a tool you do not run.

Write the result as a table, one row per prompt or workflow. The row that matters most is "which version is live". Hosted prompts keep a version history, and the live version is often not the newest, so exporting only the latest text ships an untested edit.

> **Note: Pull the history, not only the head**
> Export every version you might need to roll back to, not just the live one. A prompt you cannot revert is a prompt you cannot safely change, and after 30 November there is no hosted copy to revert to.

## Prompts as versioned files

A hosted prompt is four things that belong together: text, a model choice, sampling and output parameters, and the variables the text expects. Keep all four in one file so a change to any of them is one reviewable diff. A plain Markdown file with a header works in any language and any code review tool.

```yaml
---
id: support-triage
version: 3
route: support-triage      # a route name, not a model id
max_tokens: 400
variables: [customer_name, ticket_text]
source: exported from hosted prompt, live version on 2026-10-28
---
You are a support triage assistant for $customer_name.
Classify the ticket below as one of: billing, bug, access, other.
Reply with the label only.

Ticket:
$ticket_text
```

Three choices in that file are deliberate.

- **A route name instead of a model id.** The file says what job it does, and configuration says which model serves it. When a model is retired, the file does not change. This is the same reasoning as in [model aliases vs pinned snapshots](https://infro.io/blog/model-aliases-vs-pinned-snapshots): the pin belongs in one place you can audit.
- **Declared variables.** The loader refuses to render if a variable is missing or unexpected, so a template typo fails in CI, not in a customer's session.
- **A `source` line.** Record where the text came from and which hosted version it was, so a reviewer can tell exported text from text someone later edited.

Version files by adding `v4.md` beside `v3.md` instead of editing in place, and let the application read a small pointer file naming the live version. Rollback is then a one-line change, and a trace can record exactly which version answered.

## A thin layer between code and the provider

Put one function between your application and the model API. It loads the file, renders it, sends it, and tags the request. Nothing else in the codebase should know a provider's SDK or a prompt's text.

```python
import hashlib, os, pathlib
from string import Template
import yaml
from openai import OpenAI

client = OpenAI(
    base_url="https://api.infro.io/v1",
    api_key=os.environ["INFRO_API_KEY"],
)

def load(prompt_id: str, version: int):
    path = pathlib.Path("prompts") / prompt_id / f"v{version}.md"
    raw = path.read_text()
    _, header, body = raw.split("---", 2)
    meta = yaml.safe_load(header)
    return meta, body.strip(), hashlib.sha256(raw.encode()).hexdigest()[:12]

def run(prompt_id: str, version: int, **variables):
    meta, body, digest = load(prompt_id, version)
    if set(variables) != set(meta["variables"]):
        raise ValueError(f"variables for {prompt_id}: {meta['variables']}")
    text = Template(body).substitute(**variables)  # raises on a missing name
    return client.chat.completions.create(
        model=meta["route"],
        max_tokens=meta.get("max_tokens"),
        messages=[{"role": "user", "content": text}],
        extra_body={"metadata": {
            "workflow": prompt_id,
            "prompt_version": str(version),
            "prompt_hash": digest,
        }},
    )
```

The base URL change is the only provider-specific line. INFRO's chat completions endpoint is wire-compatible with OpenAI's, so an SDK that speaks the OpenAI protocol works by changing the base URL.[4] A route is a name your application sends as `model`, and it resolves to an ordered list of your own provider connections and the model each should serve, which keeps the vendor and model choice in configuration.[5] The request log records the model, the connection that served it, timings, usage and estimated provider cost.[6] If you tag requests with `workflow` and a prompt version, as above, you can later ask which prompt version produced a bad answer or a cost spike. Routes read `feature`, `workflow` and `step` from metadata, so the same tags can drive routing rules.[5]

You do not need a gateway for the files or the loader. The reason to route through one now is that the cutover below depends on being able to move a share of traffic without a deploy.

## Rebuilding an Agent Builder workflow

A hosted visual workflow hides its control flow. Rebuild it as code you can read, and take the opportunity to add the limits the canvas may not enforce.

1. **Draw the graph first.** For each node on the canvas, write one line: its input, its output, the model and prompt it uses, the tools it can call, and the condition for the next node. Screenshots of the canvas go into the repository next to the code.
2. **One function per node.** Each takes typed input and returns typed output. Model calls go through the `run` function above, so each node's prompt is a versioned file.
3. **Make branching explicit.** A branch node becomes an `if` on a structured output field. Ask the model for JSON with a schema and validate it, rather than parsing prose.
4. **Bound the loop.** Set a maximum step count, a wall-clock limit and a token ceiling for the whole run, and fail closed when any is hit. [Bounding AI agent loops](https://infro.io/blog/bound-ai-agent-loops) covers the four limits.
5. **Carry a run id.** Pass one id through every node call as `session_id` metadata so a whole run groups in the request log.
6. **Re-register tools.** Tools that ran as hosted connectors need a new home: your own functions, or MCP servers. Re-check each tool's credentials and permissions instead of copying them across.

If you would rather use an agent SDK than hand-written loops, INFRO's agent endpoints accept OpenAI's Responses shape and Anthropic's Messages shape, for agent SDKs as well as coding agents.[7] You point the SDK at the gateway by changing the base URL and the key.[8] That keeps routing, budgets and the request log on the agent's calls, but it does not reproduce a hosted canvas. Whichever runtime you pick, the graph you wrote in step 1 is the spec.

## The cutover test

The risk in this migration is not the export. It is a prompt that renders slightly differently, a parameter that is silently dropped, or a model that answers a little differently, with nothing erroring. Test for those three, in this order.

**Render check.** For each prompt, render it with a fixed set of variables and assert the messages are what you expect. This catches whitespace, a lost system message and variable typos. It needs no model call.

**Parameter check.** Some models refuse parameters that others accept. INFRO's chat endpoint does not send a model a parameter it refuses, and lists what it dropped in the `X-INFRO-Params-Dropped` response header; examples in its docs include `temperature`, `top_p` and `top_k` on Claude 4.7 and later.[4] Assert on that header in the test, so a migrated prompt that relied on a low temperature is a visible finding and not a silent behaviour change.

**Replay check.** Collect real inputs, run each through the old hosted path and the new one, and compare. Do not compare text for equality. Compare what your application depends on: the label, the JSON fields, the tool called, the length bound.

```python
import json

def agree(old: dict, new: dict) -> bool:
    return old["label"] == new["label"]

def replay(cases, run_old, run_new, threshold=0.98):
    disagreements = []
    for case in cases:
        old, new = run_old(case), run_new(case)
        if not agree(old, new):
            disagreements.append({"case": case, "old": old, "new": new})
    rate = 1 - len(disagreements) / len(cases)
    json.dump(disagreements, open("disagreements.json", "w"), indent=2)
    return rate >= threshold
```

Read every disagreement by hand before you touch the threshold. A disagreement is either the new path being wrong or the old path having been wrong for a year, and only a person can tell which. Run the replay while the hosted path still answers: after 30 November there is no old side to compare against, so record old outputs now if you cannot run both later.

> **Example: Illustrative numbers**
> A team replays 500 recorded tickets through the old and new paths. The labels agree on 487, a rate of 97.4%, below a 98% bar. Reading the 13 disagreements, 9 are tickets the old path mislabeled and 4 are a lost instruction caused by a template typo. They fix the typo, correct the 9 labels in the reference set, and re-run. These figures are made up to show the process.

## Ramping traffic and keeping a way back

Once the replay passes, move traffic in steps and watch the request log between each one. A weighted route is built for this: it picks the first target at random in proportion to weight, then still fails over through the others, and the docs name a gradual migration as a use.[5] A first target can be the new model on your own connection, with the previous choice as a fallback target.

Failover only applies before the response starts: INFRO retries a request that fails before the first token on the next connection.[9] It does not catch a worse answer. For quality, use your replay set as a recurring check, and watch the signals you already track, such as answer length, error mix and latency by prompt version. [From direct OpenAI calls to a gateway](https://infro.io/blog/migrate-direct-openai-to-gateway-canary) has the full canary runbook.

A schedule that fits the time left:

| Window | What happens |
| --- | --- |
| By 31 Oct | Inventory done; Evals exported; hosted prompt edits frozen |
| By 4 Nov | Every prompt and its versions exported into files; render and parameter checks in CI |
| By 11 Nov | Workflows rebuilt; replay passing on recorded inputs |
| 11 to 20 Nov | Traffic ramp: a small share, then half, then all, with a day at each step |
| 20 to 29 Nov | Old path left in place but unused; remove hosted ids from code |
| 30 Nov | Hosted prompts and Agent Builder stop; delete the dead references |

Table: A working schedule; the dates are a suggestion, not OpenAI's.

Do not remove the old path the day you finish the ramp. Keep it until the shutdown so a rollback is a config change.

## Where a gateway helps, and where it does not

A gateway does not export your prompts or rebuild your workflow; that work is yours. What it gives this migration is a route name that decouples files from models, a request log that tags every call with its prompt version, weighted targets for the ramp, and failover to a second connection if the first has a bad hour. With INFRO, those run over provider accounts you already hold, your provider bills you directly, and INFRO charges a subscription with 0% markup on model spend.[7] INFRO also records vendor shutdown dates and warns organizations still sending a retiring model, which helps with the next deadline after this one.

It does not judge answer quality: that is what the replay set is for. And it does not replace the prompt files. The files are the source of truth, and the gateway is the place that source gets called from.

## Checklist for this week

- [ ] Every stored prompt id and workflow found, with an owner and a live version
- [ ] Hosted edits frozen; the repository is the only place to change a prompt
- [ ] Every version you might roll back to exported into a file with a `source` line
- [ ] One function sends all prompt calls; no SDK calls with prompt text elsewhere
- [ ] Render and parameter checks run in CI
- [ ] Old outputs recorded for a replay set while the hosted path still works
- [ ] Each Agent Builder graph written down and rebuilt with step, time and token limits
- [ ] Traffic ramp scheduled with a rollback that needs no deploy

## Questions

### What if a prompt is edited in the dashboard during the migration?

Freeze edits in the hosted editor the day you export, and make the repository the only place a change is made. Otherwise the file and the hosted copy drift, and you will not know which one production was tested against.

### Do I need a gateway to do this migration?

No. The prompt files and a replay test work with direct provider calls. A gateway helps with the cutover because a route name lets you shift a share of traffic and roll back without a deploy.

## Sources

1. OpenAI Evals shuts down: export your evals and rebuild them in CI — INFRO. https://infro.io/blog/openai-evals-shutdown-migration (accessed 2026-10-28)
2. AI updates timeline: model releases, prices and shutdowns — INFRO. https://infro.io/ai-updates (accessed 2026-10-28)
3. AI API changes in October 2026: what to act on, and when — INFRO. https://infro.io/blog/ai-api-changes-october-2026 (accessed 2026-10-28)
4. Chat completions — INFRO Docs. https://infro.io/docs/api/chat-completions (accessed 2026-10-28)
5. Routes — INFRO Docs. https://infro.io/docs/routes (accessed 2026-10-28)
6. Request traces — INFRO Docs. https://infro.io/docs/observability/traces (accessed 2026-10-28)
7. INFRO Documentation: overview — INFRO Docs. https://infro.io/docs (accessed 2026-10-28)
8. Claude Code & Codex — INFRO Docs. https://infro.io/docs/coding-agents (accessed 2026-10-28)
9. Failover & fallbacks — INFRO Docs. https://infro.io/docs/features/fallbacks (accessed 2026-10-28)
