Dispatch
Dispatch is Restormel's in-process model-execution Interaction Format: a structured request/response envelope for predictable AI interactions. Use it to standardise how your application communicates task intent, cost constraints, and routing context. It is an in-process contract, not a wire protocol — for spec-conformant cross-agent interop see A2A (Agent2Agent).
Formerly published as @restormel/aaif (the "AAIF" envelope); renamed to
Dispatch. Old AAIF* exports remain as deprecated aliases until 1.0.
Status
Dispatch is advanced — the type contract is defined and exported from @restormel/dispatch. Dispatch runtime helpers are available via executeDispatchRequest(). Before install, verify availability with npm view @restormel/dispatch version.
Request
type DispatchRequest = {
input: string
task?: "chat" | "completion" | "embedding"
constraints?: {
maxCost?: number
latency?: "low" | "balanced" | "high"
tokens?: {
inputTokensM?: number
outputTokensM?: number
}
}
user?: {
id: string
plan?: string
}
routing?: {
model?: string
provider?: string
}
routingContext?: { routeId?: string; workload?: string; stage?: string; /* … */ }
routingPlan?: { stepChain?: unknown[]; routingAttempts?: unknown[] }
integrationStack?: {
schemaVersion: "1"
templateId?: string
components: { id: string; role?: string }[]
}
} Response
type DispatchResponse = {
output: string
provider: string
model: string
cost: number
routing: {
reason: string
}
} Package
Types, runtime guards, and the runtime helper are exported from @restormel/dispatch:
import type { DispatchRequest, DispatchResponse } from "@restormel/dispatch";
import { isDispatchRequest, isDispatchResponse } from "@restormel/dispatch"; Use cases
- Agent orchestration — standardise how agents request model completions with cost and latency constraints.
- Routing transparency — responses include the routing reason so callers understand why a provider/model was chosen.
- Cost control — the
maxCostconstraint caps estimated spend per request.
Integration stack (optional)
Optional integrationStack on DispatchRequest declares which third-party products appear in the host environment (for example Neon, Vercel, OpenRouter). It is orthogonal to routingContext (resolve hints) and does not change provider selection. Use it for logs, MCP agents, and analytics. Valid components[].id values are exported as INTEGRATION_COMPONENT_IDS from @restormel/dispatch; isDispatchRequest() validates the object when present. The Dashboard Overview → Connect your stack wizard copies JSON that passes this guard.
Human index of vendors: Integration catalog.
Routing and resolve
Dispatch adds optional routingContext on DispatchRequest so hosts can mirror resolve hints (for example workload, stage, attemptNumber) next to the legacy routing object.
Dispatch does not call the dashboard resolve HTTP API; for a full stepChain from Keys, use @restormel/keys resolve() (Gateway key) then execute the model in your worker.
Canonical semantics: Routing contract (mirrors docs/architecture/keys-routing-contract.md). Agents: MCP docs.canonical_resolve topic keys_routing_contract or suite tool routing.capabilities.
When to choose Dispatch vs MCP vs CLI
- Dispatch — your app/service wants a typed contract and runtime helper for routing + cost estimation.
- MCP — an agent or IDE wants to call Restormel tool surface (routing/cost/validation) via stdio.
- CLI — you need local, developer-friendly inspection and debugging without embedding into runtime code.
Runtime helper
The Dispatch runtime helper resolves provider/model and estimates cost via @restormel/keys. Hosts can optionally provide the final model
output via the generate callback.
import { executeDispatchRequest } from "@restormel/dispatch";
import { createKeys, openaiProvider } from "@restormel/keys";
const keys = createKeys(
{ routing: { defaultProvider: "openai" }, keys: [{ id: "k1", provider: "openai" }] },
{ providers: [openaiProvider] }
);
const res = await executeDispatchRequest(
{ input: "Summarise…", task: "chat", routing: { model: "gpt-4o-mini" } },
keys,
{ generate: async (ctx) => "output(cost=" + ctx.cost + ")" }
); Next steps
- CLI quickstart — terminal-based tools
- MCP setup — connect to agent workflows
- All integrations