Skip to content
Docs

Agents and workflows

An agent run is many requests with different jobs: classify, plan, search, extract, reason,

An agent run is many requests with different jobs: classify, plan, search, extract, reason, answer. ORYVOX can route each step on its own, share one budget across the run, and show the run as one trace.

Name the step

Send oryvox.step (or metadata.step) and that step routes as the job it is, instead of being guessed from the prompt:

stepRouted asComplexity
classificationclassificationlow
search_queryextraction (writing a search query)low
extractextractionlow
long_contextsummarisation of long inputmedium
reasoningreasoning / analysishigh
formatstructured datalow
planreasoning / analysismedium
answergeneral chatmedium

Cheap steps go to cheap, fast models; reasoning and plan get stronger ones. Unknown step names are ignored (the request is routed from its content).

{
  "model": "oryvox-auto",
  "messages": [...],
  "oryvox": {"step": "extract", "workflow_id": "ticket-8812", "workflow_budget": 0.05, "agent": "support-triage"}
}

Workflows and their budget

FieldEffect
oryvox.workflow_idGroups the requests of one run (max 80 characters). Filter the log with GET /v1/requests?workflow_id=.
oryvox.workflow_budgetUSD (model cost) the whole run may spend. Each step is capped at what is left; once it is spent, further steps fail with 402 budget_exceeded ("The workflow budget is spent."). Spend is tracked for 24 hours after the last step.
oryvox.agentThe agent's name; cached answers are tagged agent:<name> for invalidation.
oryvox.session_idSame as the X-Oryvox-Session header.

Project, key and per-request limits still apply (Billing).

Traces across steps

HeaderEffect
X-Oryvox-Trace-IdEvery request with this id joins one trace (max 40 characters).
X-Oryvox-Parent-SpanThe request's root span becomes a child of this span (max 24 characters), so tool calls and sub-agents nest.
X-Oryvox-SessionOne conversation: the router prefers staying on the model whose provider already caches the context, and the token engine leaves that cached prefix alone. A preference, never a lock.
const run = `run_${crypto.randomUUID()}`;
const plan = await client.chat.completions.create(
  { model: 'oryvox-auto', messages, oryvox: { step: 'plan', workflow_id: run, workflow_budget: 0.05 } },
  { traceId: run, sessionId: conversationId },
);
plan = client.chat.completions.create(
    model="oryvox-auto", messages=messages,
    oryvox={"step": "plan", "workflow_id": run, "workflow_budget": 0.05},
    trace_id=run, session_id=conversation_id,
)

Then GET /v1/requests?trace_id=<run> (key scope requests) lists every step with its step, model, cost and latency, and the dashboard draws the run as a tree (Core > Requests, /app/core/requests). See Observability.

Other hints

metadata.priority (realtime, batch, normal) moves weight between latency and cost; metadata.customer_tier and tags (for example faq, realtime, batch) are recorded and used by routing and caching. Rate answers with POST /v1/requests/{id}/feedback to teach the router which models do your steps well.

Was this page helpful?