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:
step | Routed as | Complexity |
|---|---|---|
classification | classification | low |
search_query | extraction (writing a search query) | low |
extract | extraction | low |
long_context | summarisation of long input | medium |
reasoning | reasoning / analysis | high |
format | structured data | low |
plan | reasoning / analysis | medium |
answer | general chat | medium |
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
| Field | Effect |
|---|---|
oryvox.workflow_id | Groups the requests of one run (max 80 characters). Filter the log with GET /v1/requests?workflow_id=. |
oryvox.workflow_budget | USD (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.agent | The agent's name; cached answers are tagged agent:<name> for invalidation. |
oryvox.session_id | Same as the X-Oryvox-Session header. |
Project, key and per-request limits still apply (Billing).
Traces across steps
| Header | Effect |
|---|---|
X-Oryvox-Trace-Id | Every request with this id joins one trace (max 40 characters). |
X-Oryvox-Parent-Span | The request's root span becomes a child of this span (max 24 characters), so tool calls and sub-agents nest. |
X-Oryvox-Session | One 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.