DataQubeDataQube
Blog

Deterministic AI workflows: a language, not a recording

Deterministic AI workflows can't be built by saving a session as a job — repetition needs properties you can read before anything runs. Why DataQube workflows are written in a language: ordered steps, typed parameters, and a grant manifest that can't lie about what it touches.

PE
Product Engineering
DataQube · 8 July 2026 · 5 min read
Product

Analytical work has two modes that pretend to be one. Investigation is open-ended: you meander, revise, follow the surprising number wherever it leads. Repetition is the opposite: the month-end pack, the supervisory response, the Monday committee deck — the same steps, on new data, where a surprise is not an insight but an incident. A platform that treats these as one mode will be mediocre at both; the entire design question is what the second mode deserves to be.

DataQube's answer: a workflow — a separate, first-class artifact with a strong claim attached. Not "the agent will try to do the same thing again." Not "we saved your session and will replay it." A workflow is a program: ordered steps, typed parameters, declared access — a thing you can read, review, and reason about before it runs, and that behaves the same way every time after.

The risk in recorded automations

Most agent products offer repetition as a recording: take the session that worked, save it as a job, run it on a schedule. It demos beautifully. The risk arrives later, and it compounds quietly. A recording carries everything the session happened to contain — the exploratory detours, the assumptions of that particular day, values buried in cell seventeen that were only ever meant for October. Nobody can say precisely what it will do on new data, because nobody ever wrote down what it should do; and when the recording is "replayed" by a model improvising around it, each month's run is a fresh interpretation of history. The drift has no changelog. The first time the Monday pack disagrees with itself, there is nothing to diff — just two runs, two vibes, and a meeting.

If you are evaluating automation features in any agent platform, this is the question that separates recording from engineering: show me the artifact that runs on Monday — can I read it, and can you prove what it may touch?

A workflow is a program you can read

In DataQube, that artifact answers both halves. Workflows are written in a small dedicated language — .wf — and here is the standing exposure workflow from our demo scenarios, lightly abridged (tool methods come from your own catalog):

cre-monthly-exposure.wf — the artifact itselfwf
import std @ 1 ## Rebuilds the monthly CRE exposure pack and stages it for review.## @param sql the SQL capability the queries run under## @param docs the document-store capability for policy citations## @param conn the registered risk-warehouse connection## @param as_of the reporting month-end, e.g. "2026-09-30"## @param dest the file store that receives the packdef cre_monthly_exposure(sql: Cap<dq.sql>, docs: Cap<dq.files>,                       conn: Connection, as_of: String, dest: Store) -> Step<ArtifactRef> = {let exposures: Table<{ segment: String, drawn: Decimal }> <- sql.execute_sql(  connection_id: conn,  sql: "select segment, sum(drawn_amount) as drawn        from loan_book where cre_flag and as_of = '{as_of}' group by segment",)let policy: Markdown <- docs.cite(file: "policies/CRE-limits-2026.pdf", section: "3.2")let pack: Markdown <- std.llm(prompt: "Build the CRE exposure pack for {as_of}.  Exposures: {exposures.rows}. Limits, cited: {policy}")let pdf: Pdf <- std.render_pdf(pack)std.upload(pdf, name: "cre-exposure-{as_of}.pdf", store: dest)}

Everything a recording leaves implicit is explicit here. The parameters are typed, declared in the signature, and documented with tags the checker enforces — the as-of date is an input, not archaeology. Every effect is a bound, ordered step. And the language itself is built so the artifact cannot drift: it is total and deterministic by construction — no recursion, no unbounded loops, no floating point (exact decimals only), no nulls. When the analysis must change, the change is a new version of this text, reviewed like any change to a governed process. Determinism is not a promise about the model's mood. It is a property of the artifact.

It cannot lie about what it touches

Look at the signature again, because it is doing the security work. Every tool family a workflow can use must arrive as a typed capability parameter — sql: Cap<dq.sql> — and capabilities cannot be created in the body. The signature is the access surface: this workflow can query one warehouse connection, cite documents, and upload one artifact, because that is all it was handed. From this, analysis computes the workflow's grant manifest before anything runs — what it reads, what it writes, what it may ask — as checked fact, not stated intent.

The discipline doesn't stop at built-in tools. Connect a third-party MCP server — Jira, ServiceNow, an internal service — and its tools are derived into the same typed world automatically: the capability appears as jira: Cap<mcp.`jira-cloud`.*>, its methods typed from the live catalog, no hand-written wrappers. External tools obey the same rules as native ones — declared in the signature, counted in the manifest, incapable of appearing in a run that didn't declare them.

That single property changes who can trust what. The person approving a workflow sees its exact surface at approval time. The permission system enforces the same ceiling as everywhere else: a workflow never exceeds its owner's grants, and scheduling grants nothing. And an auditor asking "what could this job have accessed in March" gets an answer from the artifact itself, not from reconstruction.

Extraction is the agent's job, not yours

None of this requires anyone to write workflow code. The thread is where the work gets figured out — and when it has to run again, you ask, and the agent derives the workflow from the record: the steps that actually ran, the parameters that actually varied, the sources that were actually touched. The append-only record from the investigation is precise enough to compile from; extraction is a projection of what happened into a program that can happen again. You review the result — readable, typed, manifest attached — rather than assembling it.

Three ways to run it

The same artifact runs three ways, and each answers a different need:

  • On demand — a person triggers it with today's parameters; the month-end pack, run early because the committee moved.
  • On a schedule — that's a scheduled agent: the Monday 06:00 IC pack that rebuilds itself, compares against last week, and stages a draft while the distributed version stays untouched.
  • By tool call — an agent in a live conversation invokes the standing workflow instead of re-deriving figures, which is how a number quoted in an ad-hoc thread comes out identical to the number in the distributed pack, run for run.

Here is a scheduled run executing — Monday, 06:00, nobody at the keyboard:

ic-weekly-packrun #112 · schedule · Mon 06:00
as_of = 2026-10-05portfolio = eu_equity_alphabenchmark = msci_europeparameters pinned
  1. riskdwh.sqlPull positions & weekly performance
  2. risk.engineRun attribution vs benchmark
  3. docstore.readCite mandate limits
  4. checks.runReconcile & verify
  5. thread.appendStage the IC deck draft
1 / 5 · running…

Based on real customer conversations — all data fictional.

Every run lands on the record

A workflow run is not fire-and-forget. Each one appends to the run history: which version ran, with which parameters, producing which outputs, with the full evidence chain attached — and its results land back in a thread as a staged draft for a person to publish. Failed runs surface in the same history with their provenance, not in a log nobody reads. The record's guarantees don't weaken because nobody was watching; six months of Monday runs is six months of evidence, not six months of hope.

That is the whole design: the thread is where you are allowed to be surprised, and the workflow is where you never are — because it is a program with a manifest, not a memory of a good day. The scheduled-agents module on the product page shows where this lives in the platform, and a demo will happily extract a workflow from a live conversation in front of you.

Deploys in your cluster - nothing leaves

See your data answer questions - without leaving your infrastructure

Thirty minutes with an engineer: live product, deployment options, and your security team's questions answered by someone who wrote the code.