Download all docs

Runs: how an operation executes

When you invoke an element operation, the platform creates a run: a tracked execution with inputs, status, output, logs, and a cost debit. Runs are how you see what happened and why.

The execution model

Every run starts the same way: a POST to an operation URL.

POST /api/{circle}/{slug}/ops/{operation}
Lead Scorer Python action selected on the logged-in Triform hex canvas.
Action elements use the same canvas grammar as data and frontend elements, so code, data, automations, and UI stay visually comparable.Live triform.dev - 1920x1080 - 433914e4d138Open full size

The operation and its input schema come from the element’s chemistry YAML and flow through generated code, so the runtime, the docs, and the agent tools all agree on what a given operation accepts. The runtime never branches on element type to decide how to run it — dispatch is driven by the element’s category metadata, the same element-agnostic contract every other surface follows. That is why one URL shape and one run model cover Python, SQL, an LLM call, and a browser action alike.

Where the work actually happens depends on the element family, and this is the part worth understanding — a run is a uniform envelope around very different machinery:

  • Code actions (python, javascript, go-fn, …) run in a sandboxed Firecracker microVM on the isolation fleet. The sandbox is the security boundary: isolation workers have zero internet egress, so untrusted code can compute but cannot phone home. How that boundary actually holds — the microVM, the snapshot restore, the no-egress network — is its own concept (see isolation).
  • Intelligence operations (a lab/brain call) go through the in-process LLM gateway, which fronts multiple providers behind one interface.
  • Data queries (sql, vector, and the rest of the data category) execute against Postgres inside the circle’s own schema (circle_{uuid}) — never another circle’s.

Same envelope, different physics underneath. The dispatch layer that routes each one lives in the element runtime engine; the substrates it dispatches to are the compute, storage, and network force providers.

A run carries the four things you reason about after the fact:

  • Inputs — the JSON body you posted, validated against the operation’s schema.
  • Status — whether the run is in flight, finished, or failed. The live view of this transition is its own concept (see live-events); a run is the execution, the event stream is how you watch it move.
  • Output — the operation’s result, or a structured error. Errors follow the platform’s typed _suggestion contract, so a 4xx tells you why and how to fix it, not just what broke.
  • Logs and diagnostics — every run emits an OpenTelemetry trace span (ops.execute), tagged with triform.circle, triform.element, and triform.operation. That is the durable record of a run: filter on those tags in SigNoz to find exactly what one invocation did, how long it took, and where it failed.

Cost

A run is also the unit that gets billed. Metered operations debit AU from the circle’s wallet when they execute; how much depends on per-element pricing, and the full cascade — what’s free versus metered, and what happens when the balance runs out — is owned by billing-au. The point for the execution model is simply that the run is the thing the debit attaches to: no run, no charge.

Related