Skip to content
Stay within the configured pool
Public Preview

Model routing contract and limits

Defines the model routing contract: tenant pool boundaries, hard requirements versus soft preferences, provider request time bounds, and retry behavior.

This page covers the model routing contract, including pool boundaries, hard requirements versus preferences, routing policy fields, request variability, provider request time bounds, and failure handling.

  • Configured pool boundaries and routing policy limits.
  • Hard requirements versus soft preferences classification.
  • RoutingPolicy fields and their public meanings.
  • Provider request time bounds per phase.
  • Provider outage retries and pool failure outcome codes.

Summaries were generated by AI.

Use the typed Task and terminal-outcome contract of the SDK and Platform versions you qualify. Your application owns the instruction, response schema, deadline, external-action controls, and business acceptance; routing chooses among the available Model Routes. Understand model routing explains how a route is chosen.

Stay within the configured pool

Every model turn of a Task uses only the routes enabled in the Tenant of the Task. This is the hard outer routing boundary. A routing policy cannot add a route from another Tenant or deployment, and Duale AI does not add a default route. Duale AI also runs its own analysis with separate models, outside your pool; Scope and limits describes that use. Duale AI’s safety checks of a Task also send requests to routes in your pool, chosen by Duale AI, and your providers bill them like other model requests.

A saved change applies to new provider requests after a short delay. If Duale AI cannot read the change, it can keep using the previous configuration for longer. When a cutoff must take effect at once, revoke the provider credential or block the network path.

Request compatibility is not a second hard boundary. When no route meets every check for remaining time, context size, and requested capabilities, Duale AI uses the closest routes rather than failing. It never extends the Task deadline. Images narrow the pool only when at least one route can carry them; otherwise the Task continues without the images, as Images explains. Qualify every enabled route for every reachable workload and define the safe result when required input is unavailable.

A change to the enabled pool can change the result of every new task that reaches the tenant. Once a route is enabled, any such task can select it. Treat a material pool change as a production change.

Route settings states what each provider type accepts and how you declare it.

Separate hard requirements from preferences

Classify a requirement before you configure routing:

RequirementEnforce it throughDo not rely on
Approved provider, account, or modelA tenant pool that contains only approved routes, accounts, credentials, and model identitiesA routing preference or capability label
Region or processing locationA qualified regional deployment, endpoint and account, network, storage, telemetry, tools, terms, and accessA tenant, token, route label, or preference
Maximum spendLimits on the work your application submits, budgets, provider limits, billing controls, and stop rulescost_sensitivity
Exact model or versionStandalone routes with a pinned provider identity and version guaranteetarget_accuracy, a preset-backed route, or rolling alias
Output shape or Tool contractA strict response schema, compatible routes, Tool access, and application validationBenchmark quality alone
End-to-end response timeA realistic deadline, capacity, quota, network, and measured workflow performancespeed_preference alone
Business safety or human approvalDeterministic application controls, review gates, and operating procedurestarget_permissiveness or required_capabilities
  • Requirement
    Approved provider, account, or model
    Enforce it through
    A tenant pool that contains only approved routes, accounts, credentials, and model identities
    Do not rely on
    A routing preference or capability label
  • Requirement
    Region or processing location
    Enforce it through
    A qualified regional deployment, endpoint and account, network, storage, telemetry, tools, terms, and access
    Do not rely on
    A tenant, token, route label, or preference
  • Requirement
    Maximum spend
    Enforce it through
    Limits on the work your application submits, budgets, provider limits, billing controls, and stop rules
    Do not rely on
    cost_sensitivity
  • Requirement
    Exact model or version
    Enforce it through
    Standalone routes with a pinned provider identity and version guarantee
    Do not rely on
    target_accuracy, a preset-backed route, or rolling alias
  • Requirement
    Output shape or Tool contract
    Enforce it through
    A strict response schema, compatible routes, Tool access, and application validation
    Do not rely on
    Benchmark quality alone
  • Requirement
    End-to-end response time
    Enforce it through
    A realistic deadline, capacity, quota, network, and measured workflow performance
    Do not rely on
    speed_preference alone
  • Requirement
    Business safety or human approval
    Enforce it through
    Deterministic application controls, review gates, and operating procedures
    Do not rely on
    target_permissiveness or required_capabilities

If a workload needs one exact model version, use only standalone routes for that approved provider model and version. Detaching current fields does not make a preset-backed route a complete snapshot because other preset-owned fields can change. Keep several approved endpoints for the same version only when the account, region, credential, and endpoint boundaries permit them. Define what the application does when no approved route is available.

A configured provider model_id can refer to a rolling alias, gateway, or hosted deployment. An exact-version boundary also needs a pinned provider identity and a provider or operator version guarantee.

Set preferences inside the pool

Every RoutingPolicy field is a soft preference. A numeric value expresses relative emphasis inside the current pool. It is not a percentage target, service-level objective, route identifier, or control boundary.

The table describes the preferences you supply. Duale AI also applies its own needs for each part of the Task’s work, so a zero or omitted preference does not remove that emphasis on capability or latency. The capabilities you set, and those Duale AI infers from your message, apply to the Task’s work, including delegated parts; a part’s own needs apply only to that part.

FieldPublic meaning
target_accuracy0 or None adds no capability emphasis from you; higher values ask for stronger capability.
target_permissivenessFor sensitive but allowed requests, 0 favors cautious, qualified answers, 0.5 balances, 1 favors direct answers, and None adds no preference. It is not a safety control, and a reply that declines allowed work is not the answer (When a model declines the work).
cost_sensitivity0 or None adds no cost emphasis from you; higher values favor lower estimated cost and can trade capability for savings. It does not cap Task spend, including retries, fallback, safety checks, and Tools.
speed_preference0 adds no latency emphasis from you; higher values ask for faster responses. With None, Duale AI uses its normal latency preference. It does not replace or extend the Task deadline.
required_capabilitiesPrefers routes that rank among the stronger routes that can take the request for every listed capability, then relaxes to the closest available route when no route whose context window fits the request has all of them.
preferred_capabilitiesThe stronger a route is for the listed capability, compared with the other routes, the more it is preferred; no route is excluded.
  • Field
    target_accuracy
    Public meaning
    0 or None adds no capability emphasis from you; higher values ask for stronger capability.
  • Field
    target_permissiveness
    Public meaning
    For sensitive but allowed requests, 0 favors cautious, qualified answers, 0.5 balances, 1 favors direct answers, and None adds no preference. It is not a safety control, and a reply that declines allowed work is not the answer (When a model declines the work).
  • Field
    cost_sensitivity
    Public meaning
    0 or None adds no cost emphasis from you; higher values favor lower estimated cost and can trade capability for savings. It does not cap Task spend, including retries, fallback, safety checks, and Tools.
  • Field
    speed_preference
    Public meaning
    0 adds no latency emphasis from you; higher values ask for faster responses. With None, Duale AI uses its normal latency preference. It does not replace or extend the Task deadline.
  • Field
    required_capabilities
    Public meaning
    Prefers routes that rank among the stronger routes that can take the request for every listed capability, then relaxes to the closest available route when no route whose context window fits the request has all of them.
  • Field
    preferred_capabilities
    Public meaning
    The stronger a route is for the listed capability, compared with the other routes, the more it is preferred; no route is excluded.

Duale AI can add preferred capabilities that it infers from the Task’s latest message: the prompt of a new Task, or the user turn of a continuation. They add to the capabilities you set, never exclude a route, and are inferred again for each continuation. Set the capabilities you know the Task needs. Capability and benchmark evidence can change with the pool and published evidence; a capability label is not a certification or an allowed-use decision.

The SDK reference defines accepted values, omitted fields, and continuation overrides. For ask(), an explicit routing policy takes precedence over the capabilities= shorthand.

Task scheduling uses the separate top-level priority argument. It selects the priority class of the Task and the corresponding Task price. It does not replace speed_preference, change model ordering, or extend the deadline.

New Tasks use cost_sensitivity=0.1 when you omit that field. Explicit None or 0 removes the general preference for lower model prices; a positive value overrides the default. Continuations inherit omitted cost from their parent, and retries keep the value the Task started with. Some supporting model requests that Duale AI makes during a Task follow the preferences of Duale AI, so this preference does not apply to every model request.

What varies between two identical requests

The same policy can select different routes as the context, the pool, benchmark and speed evidence, or operating conditions change. Latency, retries, and estimated cost can also vary, including cached-input savings on routes that declare context caching. Plan for these limits:

  • Do not assume a fixed traffic split, provider requests in sequence or in parallel, or a provider request to every enabled route.
  • Output wording, reasoning, and Tool choice can differ. The Tool definitions available to a model can change between model turns.
  • The SDK result does not identify the provider, model, order of provider requests, fallback, pool version, or the reason for the choice. Documented analytics can show provider and model later, but application logic must not depend on them.
  • A continuation inherits routing fields it omits. The needs of each part of the work still apply, and inheritance does not freeze the model pool. Use the SDK reference above to override or clear individual preferences.
  • Streamed content can arrive out of order, and a retried provider request, or a step that Duale AI runs again after a safety check, can replace text already streamed. Follow Stream an answer and call model() for the terminal outcome. Stream exhaustion alone is not success.
  • A configuration change does not cancel a provider request already in progress. Stopping a Task does not undo a provider request or Tool Call that has already started, or recover consumed cost.

Keep retries, display state, and business state changes independent of route identity and streamed text. Validate completed results against your application’s business rules.

Allow time for each provider request

Duale AI applies these bounds to every provider request, including a retry and a request to another route. It does not divide them by the number of candidate routes. An endpoint in your pool must meet them; when it exceeds one, that provider request fails, and Duale AI retries within the time that remains before the Task deadline.

PhaseBoundWhat it bounds
Connection5 secondsEstablishing the provider connection, where the provider interface supports a separate connection bound.
Non-streaming response180 secondsCompleting a provider request that does not stream.
Stream startup60 secondsWaiting for the first generated content.
Stream in progress20 secondsWaiting for more generated content after generation starts.

Bound

ConnectionNon-streaming responseStream startupStream in progress
5 seconds180 seconds60 seconds20 seconds

What it bounds

ConnectionNon-streaming responseStream startupStream in progress
Establishing the provider connection, where the provider interface supports a separate connection bound.Completing a provider request that does not stream.Waiting for the first generated content.Waiting for more generated content after generation starts.

The bound follows the provider request. A streaming Task can use a provider that returns its answer all at once; that request uses the 180-second non-streaming bound, and Duale AI then delivers the answer as a single chunk.

Generated text, reasoning, and Tool Call deltas count as progress. Keep-alives and metadata do not. A stream can last longer than 60 or 180 seconds while it continues to make progress and fits within the time that remains for the Task.

These bounds limit waiting on a model provider. They do not guarantee end-to-end delivery time to your application. Use the Task deadline and terminal outcome to handle the complete request.

When less Task time remains, after the time kept to finish and return the answer, that shorter time overrides these bounds. Retries keep the original Task deadline.

Duale AI starts new model, delegated, and Tool work only before the Task deadline. Final-answer writing has a separate window, and each Task, including a continuation Task, has its own. What happens near the deadline states the timing.

Keep a Task through a provider outage

When model providers are unavailable, Duale AI retries automatically within the time available under the Task’s deadline, allowing time to finish and return the answer. A temporary failure to read an image already in the Task history, or to read your pool’s model configurations, can also retry. Retries keep the original Task deadline.

An unresolved provider outage ends with LLM_PROVIDERS_UNAVAILABLE. A temporary image-read or configuration-read failure that cannot be retried further ends with retryable INTERNAL_ERROR. If every route refuses for a reason specific to the request, the provider requests end without waiting for an outage to recover: for example, LLM_CONFIG_CONTEXT_TOO_SMALL, LLM_CONFIG_UNAVAILABLE, or CONTENT_FILTERED. A request that a safety check blocks ends with REQUEST_BLOCKED, and no other model or retry runs it.

Set the deadline from the business need. Show the Task as pending during retries and use Stop to end it. Automatic retries do not guarantee provider recovery or that delivery remains available under every retention, capacity, or deployment failure.

When a model declines the work

Duale AI does not return a reply that declines work the Task’s request allows. It withdraws that reply if it streamed and hands the work to another route in your pool. A reply that declines because the request, a Tool Result, or Duale AI states a restriction that forbids the work is the answer. To make a Task decline a kind of work, state that restriction in its request. When every route declines, the Task ends with CONTENT_FILTERED.

Handle pool failures

Task outcomes about the models in your pool have codes that start with LLM_. Task outcomes gives the meaning, the retry signal, and the next action for each code. Two of them need the configuration owner, not a retry: LLM_CONFIG_UNAVAILABLE and LLM_CONFIG_CONTEXT_TOO_SMALL mean that no route in the pool can process the request, so choose models for the work. LLM_CONFIG_CONTEXT_TOO_SMALL also ends a request that its work made too large for one model request; send a smaller request. LLM_PROVIDERS_UNAVAILABLE follows the automatic retries above.

A Task that ends with LLM_NO_PROGRESS fails instead of returning a best-effort final answer. LLM_PROVIDERS_UNAVAILABLE does not prove that every configured route ran: the Task’s deadline can end the provider requests earlier.