Skip to content
Docs

Workflows

A workflow is a multi-stage pipeline submitted as one artifact. You buy a single completion window for the whole graph instead of one per stage, and Otium schedules the inside of it.

Compile one in your browser →

Why this exists

Otium prices waiting: you buy a completion window and we spend it hunting cheap capacity. That works for one call and fails for a chain, because a pipeline pays the full window per stage. Seven stages on a seven-day window is seven weeks.

A workflow moves the window from the stage to the run. One budget, one artifact, and the scheduler gets to see the whole shape before it starts — which is also what lets it keep a model resident across steps, reuse a shared prompt prefix, and retry a malformed output in place instead of costing you another window.

A minimal workflow

A node's body is literally an OpenAI chat-completions request, with ${…} bindings substituted in. If you can write a batch line, you can write a node.

workflow.yaml
name: summarize
description: One step, to see the shape.

input:
  schema:
    type: object
    required: [text]
    properties:
      text: { type: string }

schemas:
  summary:
    type: object
    required: [headline]
    properties:
      headline: { type: string }

nodes:
  summarize:
    target: { product: otium-small }
    estimate: { tokens_in: 800, tokens_out: 120 }
    body:
      messages:
        - role: system
          content: "Summarize in one line. Reply as JSON."
        - role: user
          content: "${input.text}"
    output:
      validators:
        - type: json_schema
          schema: { $ref: "#/schemas/summary" }
      on_invalid: { retry: 2, then: fallback }
    fallback:
      - { target: { product: otium-medium } }

Dependencies are derived, never declared

Add a node that reads another node's output and you have created an edge. There is no depends_on: the graph is whatever the data says it is, which means it cannot drift from the prompts.

workflow.yaml
  # A second node that reads the first. THIS is what creates the edge —
  # you never declare dependencies, they are derived from the binding.
  tag:
    target: { product: otium-small }
    body:
      messages:
        - role: user
          content: "Tag this headline: ${nodes.summarize.output.headline}"

The one edge you can write by hand is after: [x] — ordering with no data flowing, for when a step has to finish before another starts. The compiler asks about every one of them, because that is exactly where a pipeline transcribed from existing code carries a serialization it never needed. Removing one is often the cheapest speedup available.

Validators and fallback

output.validators says what a good result looks like. A failure retries in place — seconds later, on the same warm worker — instead of costing another batch round trip. When retries run out, fallback moves that one item to a different target: handle the bulk cheaply, spend only on the hard few percent.

Steps we don't run

Otium runs no customer code. When your pipeline needs a database write or a search query in the middle, mark that step type: external: the run parks, you do the work, and you resume it. The clock stops while it waits, the worker is released, and it is still one run — so a pipeline that interleaves your steps with ours stays a single completion window rather than three.

Publishing and submitting

Publish a workflow from the portal, the API, or otiumctl. A version is immutable and publishing an identical document changes nothing, so re-running publish in CI is safe. Then submit a batch whose lines reference it — the same JSONL ingress, one line per item:

batch line (JSON)
{"custom_id":"doc-1",
 "method":"POST","url":"/v1/chat/completions",
 "body":{},
 "otium":{"workflow":"summarize@1"}}

The batch's completion window becomes the budget for every run in it.

Where the full specification lives

This page is an orientation, not a reference. The complete design — assets, structured predicates, conditional prompt sections, the compiled plan and its scheduling artifacts, billing, and the security model — is maintained alongside the code in docs/workflow-graphs.md, with a full worked pipeline in docs/examples/ar15-enrich.yaml.

Everything the compiler will tell you about a document is also available offline: otiumctl workflow validate <file> exits non-zero when a document would be rejected, so it drops into a pre-commit hook or a CI step.

Stop paying for speed you don’t need.

Otium is in closed alpha. Leave your email and we’ll send an invite when a spot opens — then point your OpenAI-compatible client at our base URL and send your first batch.

No credit card, no spam — one email when your invite is ready.

Closed alpha — onboarding is gated while we calibrate. Already invited? Sign in.