ModelBeatbeta

Models and routing

The models ModelBeat can serve, what "auto" does, and how to pin a specific model.

The model field does more work here than on a single-provider API. It accepts either auto, which lets ModelBeat choose, or the id of a specific model, which pins the request to it.

model: "auto" is the point

r = client.chat.completions.create(
    model="auto",
    messages=[{"role": "user", "content": "summarise this changelog"}],
)

ModelBeat picks the cheapest model that can actually serve the request, then tells you which one it used in routing_info. Selection gates on four things at once:

  • output cap. A model whose max_output_tokens is below your max_tokens is excluded.
  • context window. A model whose input limit is below your prompt is excluded.
  • capabilities. An image in the request excludes text-only models.
  • quality floor. A code or reasoning task hint requires quality tier 3 or above.

Among what survives, cost decides. That is why a small request lands on the cheapest rung and a 32,000-token output request does not.

If nothing survives the gates you get a 400 with a reason such as no_eligible_candidate. See Errors.

Pinning a specific model

Name it instead of auto:

r = client.chat.completions.create(
    model="claude-sonnet-4-5",
    messages=[{"role": "user", "content": "..."}],
)

A pin is not an absolute guarantee, and the two ways it can be refused behave differently:

  • Your policy forbids the model. You get a 400 with pin_not_permitted. Nothing is served and nothing is charged.
  • The model cannot clear the hard gates, meaning it is retired, unrecognised, or ineligible for the request (output cap, context window, capabilities). The router falls through to auto and serves a different model. This is not silent: the response carries x-modelbeat-routing-notice: requested_ineligible, and routing_info.model names what actually answered. See Routing transparency.

A pin is not a guarantee

If you need a pinned model to be honoured or to fail, never substituted, check x-modelbeat-routing-notice and treat its presence as an error in your own code.

The catalogue

Every model runs on Amazon Bedrock in us-west-2. Prices are USD per 1,000 tokens.

ModelInOutMax outputContextTierLatencyCapabilities
nova-micro0.0000350.000145,000128,0001fastjson, function calling
nova-2-lite0.000330.0027564,0001,000,0002fastjson, function calling, vision
claude-haiku-4-50.0010.00564,000200,0003fastjson, function calling, vision
claude-sonnet-4-50.00330.016564,000200,0004standardjson, function calling, vision
claude-opus-4-50.00550.027564,000200,0005slowjson, function calling, vision

Two things worth reading off that table:

  • nova-micro is text-only. It has no vision capability, deliberately, so it can never win an image request, even though it is by far the cheapest.
  • nova-micro caps output at 5,000 tokens. Ask for more and it is gated out, which is the single most common reason a cheap request moves up a rung.

The catalogue is served from the registry and refreshes without a gateway restart, so this table can change. routing_info on your own response is always authoritative.

Fallbacks

If the chosen model fails, ModelBeat retries down a short fallback chain rather than failing the request. When that happens the response says so:

"routing_info": {
  "provider": "bedrock",
  "model": "claude-haiku-4-5",
  "is_fallback": true,
  "primary_provider": "bedrock",
  "primary_model": "claude-sonnet-4-5"
}

The hold placed against your balance covers the chosen model and its fallbacks, so a fallback never costs more than was reserved. See Costs.

What is not supported

/v1/embeddings and /v1/async/* are present on the gateway but outside the supported surface. See Limits.

Listing models programmatically

models = client.models.list()
for m in models.data:
    print(m.id)

GET /v1/models is authenticated (requires a valid API key) and returns the current catalog. It is rate-limited but never metered, so no balance is consumed. The response matches the OpenAI shape, so any stock OpenAI SDK works unchanged.

On this page