Enterprise DeploymentAI ArchitectureupgradedEnterprise Autonomy

Model Independence as an Architecture Principle

TS
Trevor Solis · Lead AI Engineer, Missions
September 14, 2025

Nobody sets out to build a system that depends on one model. It happens one small accommodation at a time, and each accommodation looks like good engineering on the day it is written.

Somewhere in a mature agentic system there is a function that reads, in effect, "if the confidence field is missing, treat it as medium." It has a comment above it, and the comment is honest: the model we use does not always return that field, so we default it rather than fail the run. The reviewer who approved it was right to. The alternative was an exception in production for a case that had nothing to do with the business and everything to do with a generation quirk, and shipping is a virtue. But look at what has just happened to the architecture. A rule about how confidence is interpreted — a rule that will now be inherited by every downstream decision, quoted back in an audit, and defended in a design review two years from now — exists because of a behavioural tendency of one model. The domain has acquired a fact about the model. Nobody wrote it down as such, and nobody will remember it that way.

That is the whole failure mode, and it is worth stating before the usual conversation about abstraction layers begins. Model independence is not a property you obtain by putting an interface in front of a model. It is a property you maintain by refusing to let model-specific behaviour become load-bearing anywhere except in the one place you have designated to absorb it. Once a quirk has been promoted into a business rule, it is no longer a quirk. It is a requirement, and no interface, however clean, can demote it back.

An interface relocates the call; it does not relocate the behaviour

The standard remedy is well known and mostly correct as far as it goes. You define a boundary — an LLM Gateway, in StudioX's vocabulary — through which every model call passes, so that no application code holds a provider SDK, a credential, or a wire format. Requests go in with a common shape and come out with a common shape. This is genuinely valuable, and any system without it has a much worse problem than the one under discussion, because it cannot even enumerate where it talks to a model. But teams routinely mistake this boundary for independence itself, and the mistake is understandable, since the boundary handles the part of the problem that is visible in a diagram.

What the boundary does not handle is behaviour, and behaviour is where the dependence actually accumulates. Two models can accept the same request shape and return the same response shape while differing in every way that matters to a system that acts on the output: how verbose they are when uncertain, whether they volunteer caveats, how literally they follow a negative instruction, how they behave when a tool call would be reasonable but not obviously required, how they degrade when the context is long and the relevant fact is in the middle of it. None of that is expressible as a type. All of it shows up as production behaviour, and production behaviour is what your code was written against, whether or not anyone intended it to be.

So the interface passes its own test and the system fails the real one. You can swap the model behind the gateway in an afternoon, and the swap produces a stream of small, apparently unrelated defects: a routing rule that suddenly sends everything down one branch, an approval step that fires twice as often, a summarisation task whose output now trips a length guard that nobody remembered existed. Each of these traces back to a line of code that quietly encoded an assumption about how the previous model behaved. The interface was never lying. It simply drew its boundary around the call and left the assumptions on the wrong side of it.

The test is not "can I swap it," but "what would I have to change"

A more useful way to think about this is to stop asking whether your system is model-independent and start asking a narrower, answerable question about any given piece of logic: if this behaviour were different tomorrow, would this rule still make sense? A validation that rejects an output missing a required field makes sense regardless of which model produced it — that is a statement about what the business needs. A default that silently fills that field in because one model tends to omit it does not; it is a statement about a model wearing the costume of a business rule. The two look nearly identical in a diff, which is exactly why the distinction has to be enforced deliberately rather than noticed spontaneously.

The discipline that follows is not complicated to describe. Compensating behaviour is allowed to live at the boundary, in the adapter that knows which model it is talking to, and nowhere else. If a model omits a field, the adapter for that model repairs or rejects the response before it enters the system, and the repair is labelled as a compensation, with the model it compensates for named beside it. If a model needs a differently phrased instruction to reliably produce structured output, that phrasing belongs to the adapter, not to the prompt that expresses what the task actually is. If a model requires a retry pattern that another does not, the retry lives at the boundary. What passes inward is a response the domain can treat as ordinary, and what the domain contains is only rules that would survive the model being replaced.

The same principle applies to the layer that does the deciding. In a system with a Reasoning Core — the component that plans, sequences, and adjudicates what happens next — the core should be expressible entirely in terms of the task: what evidence is required, what a sufficient answer looks like, when a human must be brought in, what an unrecoverable state is. The moment that core contains a branch whose real justification is a generation tendency, the reasoning has been contaminated with something that is not reasoning, and the contamination will not be visible from the outside. It will look like domain complexity, be defended as domain complexity, and be carried forward into the next architecture as domain complexity, long after the model that caused it is gone. This is why the discipline has to be about placement rather than about periodic cleanup: nothing about a promoted quirk announces itself later.

The cost is real, immediate, and paid by whoever holds the line

Here is the part that gets left out of most architectural advice, and it is the reason this principle is more often stated than practised. Keeping compensations at the boundary is slower than putting them where the failure appeared. The engineer debugging a broken run at the end of a release week has a two-line fix available in the file they are already looking at, and a considerably less pleasant alternative that involves opening the adapter layer, deciding whether the repair belongs there, possibly discovering that the adapter has no natural place for it, and explaining in review why a two-line problem became a structural change. The cheap fix works. It is not wrong in any way the tests can see. And it is indistinguishable, at the moment of writing, from ordinary defensive programming.

Multiply that by every such moment across a couple of years of shipping and you have the actual mechanism by which model independence is lost. Not a decision, not a debate, not a document anyone can point to — an accumulation of individually defensible accommodations, each made under time pressure by someone who could not see the aggregate. The principle is rarely abandoned loudly, because nobody ever proposes abandoning it; it simply stops being paid for, one review at a time, until someone tries a substitution and discovers that the system has quietly become a system about one model. That is why the discipline needs an owner and an explicit place to live rather than a shared intention. A team that has designated the gateway as the only legal home for compensating behaviour, and treats a compensation appearing anywhere else as a defect in its own right, is doing something structurally different from a team that merely agrees model independence is desirable.

None of which means the accommodations should not exist. They should, because models do behave differently and pretending otherwise produces brittle systems that fail on the first unusual response. The question is never whether to compensate but whether the compensation is contained and visible, which is also how the broader shift toward autonomy is usually described in the literature on the autonomous enterprise: the durable systems are the ones where the parts that can change are separated from the parts that must not. Every compensation at the boundary is a small, catalogued liability you can read in one place. Every compensation in the domain is an untracked one that has changed the meaning of your business rules.

The mental model worth carrying is that model independence is not an architecture you build but a boundary you keep paying to hold, and the payment is made in exactly the moments when it is least convenient. The useful question in a design review is not whether the system has an abstraction layer, because almost every system does. It is a harder and more revealing one: which of these rules exist because the business requires them, and which exist because a model behaved a certain way on a Tuesday, and can anyone still tell the difference?

Discussion

No comments yet — start the conversation.

Join the discussion

See StudioX run.

Put autonomous AI workers to work on your own systems and knowledge.