
What virtual models do
A virtual model is a model you define, instead of one a provider advertises. GoModel picks the kind from whether you give it a target:- A redirect (an alias) is a stable name that points to a concrete provider
model. Your app sends the name in the
modelfield, and GoModel resolves it before sending the request upstream. - An access policy has no target. It gates an existing model selector by
user_path— or disables it entirely — without adding a new name. See User Path for access control.
Models -> New virtual model.
Fill Target model to make a redirect; leave it empty to make an access
policy on the Source selector.
GoModel does not persist empty, ineffective access policies, whether saved from
the dashboard or through the admin API. If a saved policy has no target, user
paths, description, or slowdown and its enabled state matches the inherited/default
access state, GoModel removes the stored row. It retains an otherwise empty
policy when that row still overrides a disabled default or an inherited
user-path restriction.
Add artificial model latency
Set Slowdown on a concrete model or redirect to add a fraction of measured inference time. Active values range from0.1 to 10; for example, 0.5
adds 50%, so a response that takes 2 seconds upstream is returned after about
3 seconds. Set 0 to explicitly disable slowdown, including slowdown inherited
from a concrete model. Leaving the field empty leaves the setting unspecified.
Delays honor request cancellation.
For Chat Completions and Responses API SSE streams, GoModel drains the upstream
in the background and releases each read chunk on the scaled timeline. This
preserves the provider’s relative chunk timing while delayed chunks accumulate
in memory. A large factor on a long or high-volume stream can therefore use
substantial memory. Realtime WebSocket sessions are not slowed.
When an alias and its concrete target both have a slowdown, the alias value
wins. An alias without its own value inherits the selected target model’s
slowdown; set the alias to 0 to override that inheritance. This also applies
to load-balanced virtual models after a target is selected.
The rest of this page covers redirects.
Use stable names
You can expose names likeregular and smarter instead of provider-specific
model IDs.
regular->anthropic/claude-sonnet-4-6smarter->anthropic/claude-opus-4-6
Load balance across models
A redirect can point at several target models and spread requests across them. Add more than one target in the editor (Add target) and pick a strategy:- Round-robin (default) rotates requests evenly across the targets. Set a
per-target weight to bias the share — a target with weight
2receives twice the traffic of a target with weight1. - Lowest cost routes every request to the cheapest currently-available target, ranked by the model registry’s input + output per-token price. When a target has no registry pricing it is skipped while a priced target exists; if none are priced, the first listed target is used.
session_affinity: false) to
restore stateless balancing — see
Session Keeping.
smart at both openai/gpt-4o and anthropic/claude-sonnet-4-6
with the round-robin strategy to split load, or at a premium and a budget model
with the cost strategy to always take the cheaper one.
Rename or repoint a redirect
Open a redirect in the dashboard and edit its Source to rename it. GoModel moves the definition to the new name in one step — the old name stops resolving, so update any app still sending it. Renaming onto a name that already belongs to another virtual model is rejected; renaming onto a concrete model name shadows that model (see Shadow a model). Redirects that shadow a model can be edited the same way — use the model row’s Edit redirect action. Virtual models declared as code keep theirsource
fixed in configuration; rename them by editing the declaration.
Define virtual models as code
Operators who manage configuration as infrastructure-as-code can declare virtual models inconfig.yaml or the VIRTUAL_MODELS environment variable instead of
the dashboard. Declarative entries are applied at startup, override any
admin-store row with the same source, and are shown read-only in the dashboard
(a Config badge). Edit the configuration to change them.
In config.yaml:
config.yaml entries with a matching source:
source, a single target (shorthand) or a targets list,
strategy (round_robin or cost), session_affinity (default true; see
Session Keeping), user_paths, description,
slowdown (0 disables inherited slowdown; active factors range from 0.1 to
10), and enabled.
Leave the targets empty to declare an access policy on the source selector. An
invalid declaration (unknown strategy, missing or self-referential target, or a
target provider that matches no configured provider — a typo) fails startup
with a clear error listing the registered provider names.
Two lenient exceptions keep valid setups booting:
- A target
providerthat is declared underproviders:but did not register — typically because its credentials are unset in this environment — only logs a warning; the target stays unavailable until the credentials resolve. Aconfig.yamlshared across environments still boots everywhere. - Whether a target model exists is never checked at startup: the model catalog loads asynchronously, so availability is a runtime concern and an unavailable target is simply skipped at resolve time.
Expose only redirects
To hide provider models fromGET /v1/models, set:
/v1/models
instead of the full provider model list. The setting is also listed in
.env.template.
Shadow a model
A redirect can “shadow” a model by using the same name as an existing model and pointing it somewhere else. This lets you override a requested model without changing application code. For example:- source:
anthropic/claude-opus-4-6 - target model:
anthropic/claude-sonnet-4-6
anthropic/claude-opus-4-6, while GoModel routes the
request to anthropic/claude-sonnet-4-6.
A/B testing
Redirects are useful for short model experiments. Move a redirect from one target to another, then compare app behavior, latency, and usage. For example, pointsmarter at Opus for one test and Sonnet for another. You can
also shadow opus-4-6 with sonnet-4-6 to check whether the same app flow still
works.