The Model You Requested Is Not Always the Model That Ran
I found a small but expensive ambiguity while building APX: the model selected in APX was easy to mistake for the model that an external coding runtime would actually run. That sounds obvious once stated. APX can talk t
I found a small but expensive ambiguity while building APX: the model selected in APX was easy to mistake for the model that an external coding runtime would actually run.
That sounds obvious once stated. APX can talk to its own configured engine, then delegate coding work to Codex or Claude Code. Those CLIs have their own configuration, their own supported model flags, and their own defaults. But a UI label is persuasive. If it says one model, people reasonably expect the next coding run to use it.
That expectation was not a contract. In one case, a session requested a model that did not belong to the external runtime, the CLI returned a 400, and the useful questionβwhat exactly did APX ask it to run?βhad no clear answer.
So I changed the boundary rather than trying to hide it. My rule is now: a requested model, a model passed to a runtime, and a model that actually ran are different facts. Record each one honestly.
inherit needed a precise meaning
APX supports agent model selection. External coding runtimes are different programs. Before this change, model: inherit could look like a promise that an external CLI would inherit APX's selected model. It is not.
The documented default is narrower: an unpinned runtime uses its own configured default. Codex reads its own configuration; Claude Code reads its own configuration. APX supplies the work and can capture the result, but it should not quietly claim control it does not have.
I kept that default. Changing it silently would have been worse than the original ambiguity: existing setups could start spending from, or behaving like, a different model without an intentional choice.
Instead, APX now makes the choice explicit in three ways:
- A single runtime call can name that runtime's native model and, where supported, its reasoning effort.
- Runtime configuration can pin a model and effort for future calls.
- A runtime can opt in to following APX's selected model, but only when that provider is native to that runtime.
The ordering is deliberate: a direct call beats a runtime configuration, a runtime configuration beats the optional APX inheritance setting, and otherwise the CLI default wins. That makes the value's origin inspectable instead of accidental.
Never pass one model vocabulary into another program
The implementation detail that mattered most was refusing to treat model identifiers as interchangeable strings. An APX engine selection can include a provider, a model, and an effort. An external CLI may accept only a bare model id, may accept a separate effort flag, or may accept neither.
APX now splits that information before it reaches a runtime adapter. The Codex adapter can receive a model flag and a reasoning-effort setting; the Claude Code adapter can receive a model but not that effort setting. Other runtimes declare that they do not accept a model from APX.
That declaration prevents two bad outcomes. First, APX does not hand a provider-prefixed identifier to a CLI that cannot understand it. Second, it does not silently drop a requested flag and run something else. If a caller asks Codex to run an Anthropic model, or asks a runtime that has no APX model option to take one, the call fails before a process starts.
I prefer that failure. It is specific, cheap, and actionable. A silent fallback might finish successfully while violating the reason the person selected a model in the first place.
βEffectiveβ cannot mean guessed
There is another boundary that was tempting to blur. A runtime can accept a model pin, but APX does not receive a universal, trustworthy report from every CLI saying which model ultimately executed the request.
So the result now returns a small model record: requested, passed, effort, source, and effective. When APX pinned a model, effective reports that pin. When it did not, the result says runtime default (not reported by the CLI).
That last string is intentionally plain. It does not pretend APX observed something it did not observe. It tells the person where the remaining uncertainty lives: inside the runtime's own configuration and reporting.
APX also writes the requested model and source into the runtime session record. A session should not become a mystery later, especially when it is resumed. The same resolution path applies to ordinary runtime calls and to agent-to-agent runtime replies, so a configured pin does not disappear just because the conversation arrived through a different route.
The tests were about the seam, not just the parser
I did not want this to be a nice resolver with no operational proof. The tests cover the precedence rules, provider mismatch errors, unsupported effort errors, and the unpinned default. They also run a fake Codex executable and inspect the arguments it receives for both a new run and a resumed one.
That distinction caught the real risk: a value can be resolved correctly and still be lost at the adapter boundary. The sandbox behavior remains separate too. A resumed Codex session inherits its sandbox from the first turn; adding a model pin must not accidentally rewrite that unrelated rule.
What I am keeping from this
Agent tooling creates lots of plausible-looking state: selected engines, model labels, project defaults, agent overrides, and external commands. The hard part is not collecting settings. It is preserving the line between a preference and an action that another program accepted.
My practical rule now is simple: if one system asks another system to use a model, keep four answers available. What was requested? What was actually passed? Why was that value chosen? What can the caller truly know about the result?
That is less magical than a single model label. It is also much easier to debug, audit, and trust.
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.