Skip to main content
An executor runs a selected candidate. Use one when your provider is not in Pi’s catalog, your application has a private gateway, or you need a specialized SDK.

Completion executor

The executor receives the normalized RouterRequest, the selected candidate, the validated decision, and an abort signal. A completion can contain text, tool calls, reasoning, and hosted tool calls. Its finish reason is stop, length, or tool_calls.

Streaming executor

Return an async iterable when request.stream is true:
The event sequence must be valid: start tool calls before their deltas, close tools and reasoning before finish, and emit nothing after finish. The full event union is exported as RouterStreamEvent.

Model metadata

Custom models should declare the capabilities they genuinely support:
Capability metadata controls eligibility. It does not add features to your transport; your executor must implement the contract it advertises.

Cancellation and cleanup

Propagate signal to the SDK. Request cancellation and response-body cancellation abort it. For streams, release resources in finally; Router Core closes an async iterator when a stream ends early.

Fallback

Same-model retries belong to your executor. To retry once on another eligible candidate:
requiresDifferentProvider restricts the retry to another provider. The response, hooks, and routing metadata report the model that actually served. A failed primary’s lease is removed. For retry budgets, error classification, or multi-step recovery, own that orchestration outside createRouter.