Models & Aliases
Every request to GPROXY carries a model name. The route it takes from that string to an actual upstream call is one canonical pipeline:
permission → rewrite → alias → executeEach stage either passes the request through unchanged or rewrites the
target (provider, model_id) before handing it to the next stage. All four
stages run inside the handler layer — the SDK GproxyEngine::execute step
only does the final upstream call.
The unified models table
Section titled “The unified models table”Since v1.0.5, real models and aliases live in the same models table. The
distinction is a single column:
alias_of = NULL— a real model entry. It has a provider, a model id, and optionally pricing metadata.alias_of = Some(id)— an alias pointing at another row’s id in the same table.
This table is what the admin API and the console read from and write to.
The engine rebuilds its in-memory alias lookup (HashMap<String, ModelAliasTarget>) from this table at startup and on reload.
Defining aliases
Section titled “Defining aliases”In the seed TOML:
[[model_aliases]]alias = "chat-default"provider_name = "openai-main"model_id = "gpt-4.1-mini"enabled = trueAt runtime, use the Models tab in the provider workspace of the embedded
console. Seed-time [[model_aliases]] rows are imported into the unified
models table on startup.
Alias resolution at request time
Section titled “Alias resolution at request time”When a client sends "model": "chat-default", the pipeline:
- Permission check — does the user have a permission row whose
model_patternmatches the alias name? - Rewrite rules — channel-level rewrite rules can rewrite the alias to a different string before alias lookup.
- Alias resolution — the alias is looked up in the unified
modelstable and resolved to a concrete(provider, model_id)pair. - Execute — the engine prepares and issues the upstream request using the resolved pair.
Non-stream responses have their "model" field rewritten back to the alias
the client sent. Streaming chunks are rewritten per chunk in the engine.
From the client’s perspective, the alias is a real model — it just happens
to price and route to something else.
Pulling upstream models
Section titled “Pulling upstream models”The console’s Models tab has a Pull Models button, which calls
POST /admin/models/pull. That endpoint fetches the upstream’s real
model_list for a provider and returns the ids. The console imports them
into the local models table as real entries (alias_of = NULL) with no
pricing, which an admin can then edit.
This gives you the “seed from upstream, customize locally” workflow without having to hand-edit TOML.
model_list / model_get routing
Section titled “model_list / model_get routing”How the model-list endpoints behave depends on the routing template configured for the route:
*-onlypresets (chat-completions-only,response-only,claude-only,gemini-only) defaultmodel_listandmodel_getto the Local implementation. Requests are answered entirely from the localmodelstable and never hit upstream.*-like/ pass-through presets still call upstream formodel_list, but GPROXY merges the upstream response with the localmodelstable: real local models that aren’t in the upstream response are appended, and aliases mirror their target entry.model_getchecks the local table first and falls through to upstream only on miss.
GproxyEngine::is_local_dispatch(...) lets handlers decide this before
calling engine.execute.
Pricing and aliases
Section titled “Pricing and aliases”Billing tries to price a request against the alias name first and falls
back to the resolved real model name if no alias-level pricing exists.
This means admins can set different prices for the same real model under
different aliases — for example, to mark up a premium-gpt4 alias while
keeping chat-default at cost.
See Pricing & Tool Billing for the full
ModelPrice shape, billing mode selection, and how tool call counts are
charged per actual invocation.