Nova Admin Docs
Concepts

Service Tiers (Priority & Flex)

How Nova runs background work cheaper with a priority/flex compute service-tier axis that is orthogonal to model/complexity routing — automatic by trigger source, with an optional per-agent and per-flow override.

What a service tier is

A service tier controls who gets compute priority on a request — a separate axis from which model serves it. The Auto router picks the model (cheap / mid / frontier by complexity); the service tier then chooses the serving lane:

TierForCost / latency
priorityLatency-sensitive, user-facing work — a Slack @mention, a web chat turnPremium serving, fastest
flexBackground, non-interactive work — cron-triggered reports, webhook/GitHub/Sentry-triggered flowsCheaper, slower serving

The two axes are independent: a frontier-complexity model can run on the flex tier (a heavy nightly report), and a cheap model can run on priority (a quick interactive lookup). Prompt caching is a third, separate optimization and is unaffected by the service tier.

How the tier is decided

serviceTier = node override  ??  agent override  ??  default-by-trigger-source
  1. Default by trigger source. Interactive sources (slack, web, email, linear, manual, sms) default to priority. Every other source — scheduled/cron, webhook, github, sentry, api, mcp_server, integration, or an unknown/absent source — defaults to flex. Background work is the cheaper default; a user-facing channel always passes a known interactive source and gets priority.
  2. Per-agent override (AgentDocument.serviceTier) — pins a tier for every run of one agent.
  3. Per-flow-node override (the agent node's serviceTier in the flow builder) — the most specific; wins over the agent and the source default.

This mirrors the human-vs-background split the HITL approval gate already uses, so background flows that auto-approve also run on the cheaper lane by default.

How the tier is applied (server-side, capability-gated)

The decision is resolved in runConversation and passed down to every model round. It is applied only when the resolved provider + key supports the matching capability, and is otherwise a graceful no-op — the request is simply served at the provider's normal rate. No configuration error, no failure.

ProviderflexpriorityHow
OpenAIResponses API service_tier field
All others (Anthropic, Gemini, xAI, …)no-opno-opField omitted; served at the normal rate

Capability detection is reported by each provider via supportsFeature("service-tier-flex") / supportsFeature("service-tier-priority"). To add support for another provider, report the capability in that provider's supportsFeature and map the tier onto its request in chat().

A note on Anthropic's Batch API

Anthropic offers a roughly 50%-cheaper Batch API, but it is asynchronous: you submit a job and poll for results minutes to hours later. The agent loop is synchronous (a turn must return a response inline), so the Batch API is not wired into this axis: a flex run on Anthropic is a no-op rather than silently deferring a live chat turn. Offline, batch-friendly workloads (like a corpus eval) are a separate, future integration.

Setting an override

  • Per agent: set serviceTier: "priority" | "flex" on the agent document.
  • Per flow node: set the agent node's serviceTier field. Leave it unset to inherit the agent override, then the trigger-source default.

Override precedence is node → agent → source default, so you can force a normally-background cron flow onto priority for one critical node, or push a normally-interactive agent onto flex when it is being used for bulk processing.

Where it lives

  • apps/admin/src/lib/agent-core/models/service-tier.ts — the decision + capability-gating logic (resolveServiceTier, applicableServiceTier, defaultServiceTierForSource).
  • apps/admin/src/lib/agent-core/models/provider-types.ts — the ServiceTier type, the service-tier-{flex,priority} capabilities, and the serviceTier chat param.
  • apps/admin/src/lib/agent-core/models/providers/openai.ts — maps serviceTierservice_tier.
  • apps/admin/src/lib/agent-core/chat/conversation.ts — resolves and gates the tier, then threads it through the conversation loop to provider.chat.

On this page