Skip to main content
A router evaluates models in two stages. First Router Core filters out candidates that can’t handle the request. Then your policy picks one.

Declare Pi Models

Use pi.model() for models in Pi AI’s catalog:
The ID uses provider/native-model-id form. Pi fills in capabilities and reasoning levels from its catalog. The second argument overrides defaults or adds metadata for custom policies.

Declare Custom Models

For models outside Pi’s catalog, declare capabilities manually:
Standalone declarations need the satisfies RouterModel ascription — without it, reasoningEfforts infers as string[] and fails to type-check when passed to createRouter. Objects written inline inside models: [...] are contextually typed and don’t need it. When omitted: provider defaults to the prefix before /, api defaults to the executor name, reasoning efforts default to ["off"], all capabilities default to false.

Eligibility

Router Core removes candidates that can’t satisfy the request’s:
  • image input
  • declared tools or tool-call history
  • structured response format
  • streaming mode
  • requested reasoning effort
A policy can’t choose an ineligible model. If nothing remains, the request fails with no_eligible_models.

Reasoning Efforts

Provider-independent levels: off, minimal, low, medium, high, xhigh, max — ordered from none to highest. Pi maps each label to the provider’s native control. OpenAI callers can constrain selection with reasoning_effort. Anthropic callers use output_config.effort and thinking. Without a request constraint, the policy may select any effort the candidate exposes.