Switching models mid-session costs nothing

· This page is written in English. The terms it explains are the ones people search for in English, and a translated term of art is a changed term.

And that is a design decision, not a feature. Most agent tooling is written against one vendor and adapted to others afterwards. The order sounds like an implementation detail. It is the whole thing.

Adapting afterwards means the first vendor's assumptions are already load bearing by the time the second one arrives. They are in the conversation store, in how a tool call is represented, in how a streamed response is parsed — and none of those are places anyone thinks to look a year later. What you notice is only the symptom: changing provider means a migration, and a migration in the middle of a session means you do not change provider.

Where the assumption hides

The obvious place to look is the HTTP call, and the obvious place is wrong. Any two vendors' endpoints are a weekend of work apart. The expensive part is what you did with the answer.

Take one detail. Most vendors key a tool result by the id of the call that produced it. Gemini keys it by the function's name. If your conversation store holds tool results the way vendor A described them, then supporting Gemini is not a new HTTP client — it is a change to the shape every transcript you have ever written is already in.

That is the whole problem in miniature. There is no adapter that fixes it, because the information was thrown away at write time.

Neutral history

The alternative is to decide, before the first provider is written, that history belongs to none of them.

OHarness stores session transcripts in a shape defined by the engine (packages/engine/src/core/types.ts), not in any vendor's format. A tool result carries toolName as well as toolCallId — not because the engine needs both, but because Gemini needs the name and everyone else needs the id, and the neutral form has to be able to render into either.

A vendor's wire format is produced at the moment a request goes out and discarded when the response is folded back in. Nothing persists in it.

So switching provider mid-session converts nothing. Not because the conversion is fast, but because there is no old shape to convert from.

What this buys, concretely

A model is a thing with pricing, capacity, a rate limit, and a bad week. When those are someone else's decisions and you have one model, they become your decisions. The point of a replaceable backend is not novelty — it is that the day a provider changes its terms is a day you can have an opinion about.

It also makes the boring case work. Draft with something cheap, switch to something expensive for the part that is hard, drop to a model on your own machine when the network is bad or the code should not leave the building. Those are the same session.

The part that is not free

Honesty about the trade: the neutral format is a commitment. Every capability that differs across vendors — reasoning effort, prompt caching, parallel tool calls, image support — has to be expressed as a flag on the model rather than assumed from the provider, because sending the wrong shape is a 400 rather than a degraded answer. That is a real cost, paid once, in a place where it is visible.

The alternative is to pay it repeatedly, in the dark, for as long as the project lives.

---

OHarness is an open source agent harness, MIT licensed. It speaks natively to Anthropic, OpenAI and Google Gemini, to any OpenAI-compatible endpoint, and to local runtimes such as Ollama, LM Studio and vLLM. The architecture reference describes how the layering is enforced rather than merely intended, and what an agent harness is covers the surrounding idea.