The anatomy of a defensible workflow
A walkthrough of what a Sommatic workflow is made of — nodes, knowledge, agents, gates, evidence — and what makes a workflow that holds up two years from now.
A workflow is not the run. The run is one execution — fifty milliseconds of traffic between systems, one decision out of millions. The workflow is the artifact behind it: the versioned graph, the contract, the thing that gets signed off, audited, replayed, and amended. When the team rotates, when the regulator updates a clause, when a partner changes their API, when next year happens — the run is already gone. The workflow stays. That distinction sounds academic until the day someone asks: what exactly did our system decide on April 14th, and on what grounds? A workflow that can answer that question is what we mean by defensible.
TL;DR
- A Sommatic workflow is a versioned graph of typed nodes — not a script — composed from a marketplace, anchored in policy from the Knowledge Center, and ending in evidence.
- Determinism comes from nodes; judgment comes from Agents; control comes from HITL gates; trust comes from the audit chain that every step writes by default.
- The workflow is the document the regulator reads, the post-mortem follows, and the next engineer inherits. Build it accordingly.
What a workflow actually is
A workflow in Sommatic is a versioned graph, not a script. That sentence sounds small and changes almost everything that follows. A script is a sequence of statements executed top to bottom inside a process that owns its own memory; when the process dies, the state dies with it. A graph is a declarative definition of nodes and edges that an external engine traverses. State lives outside the code. Each step is addressable. Each transition is a contract.
This matters in three concrete ways.
First, replayability. Because the graph and the inputs are persisted, the same run can be reconstructed weeks later — not as a log of what happened, but as the actual state machine moving from node to node with the values it saw. You are not reading a story about the execution; you are watching the execution again.
Second, resumability. A workflow that pauses for a human approval at node seven does not die at node seven. The instance persists. The active node, the variables, the last envelope returned — all serialized. When the human acts, the engine wakes the instance and continues from the same edge. Days later, weeks later, it does not matter.
Third, versionability. A workflow has a FlowDefinition (the named thing the team talks about — “refund intake”, “vendor onboarding”) and FlowVersion records that are immutable once published. New version, new graph. Old runs continue to point at the version they started on. There is no “the latest one” silently rewriting yesterday’s behavior.
The run is one execution. The workflow is the contract. Treat them differently.
In practice this changes how teams talk. People stop asking “is the workflow running?” and start asking “which version did that instance use?” That is the right question — and it is only possible because the workflow exists as an artifact independent of any single run.
Composed of nodes from a marketplace
The unit of composition is the node. A node is a typed operator with a slug (io.http, ai.classify, data.validate), a config schema, declared input and output ports, and an implementation that returns an envelope: { ok, data, port }. That envelope is what tells the engine which edge to follow next. Nodes do not call each other. They do not share memory. They emit, the engine routes, the next node receives.
We surface these as the Node Marketplace — a catalog of operators teams browse, configure, and drop into a graph the same way they would pick a Lego brick. The catalog is organized into twelve families:
- identity — token issue and inspect, crypto, PII redaction, consent checks, Veripass evaluation.
- flow —
flow.if,flow.switch,flow.join,flow.wait,flow.try,flow.split,flow.mutex,flow.window,flow.rate.limit. - io — HTTP, FTP, SMTP/IMAP, SSH, MQTT, gRPC, WebSocket, GraphQL, SOAP, OCR, local file and shell.
- ai — classify, compose, embed, summarize, extract, RAG, translate, transcribe, safety.
- data — transform, template, parse, validate, lookup, datetime, math, chunk, UUID, stringify.
- code —
code.js,code.python,code.shellfor the cases a marketplace node cannot express. - ops — trace start and end, checkpoint, metrics emit, state read and write, audit append, dedupe, saga begin and compensate.
- triggers — webhook, cron, queue, manual, event, workflow.
- hitl —
human.task.create,human.approval.gate,sommatic.app.execute. - workflow —
workflow.chainfor sub-workflow composition. - connectors — vendor-specific (Microsoft Graph and similar).
- integrations — AWS, PostgreSQL, MongoDB, Redis, Oracle, OpenAI.
Concrete picture. A four-node refund flow: triggers.webhook receives the customer request, ai.extract pulls amount and order ID from the message, data.validate checks the amount against an order lookup, human.approval.gate waits for a supervisor. That is the entire workflow. Four nodes, three edges, one outcome. The marketplace makes this assembly the default mode — not the exception.
Workflows are composed, not coded. The bricks are pre-typed; the engineering is in the graph.
The marketplace exists because the alternative is everyone re-implementing HTTP retries, OCR adapters, and rate limiters per project. That is how organizations end up with seventeen subtly different ways to call the same payment provider.
Knowledge as the substrate
A workflow that hardcodes policy is a workflow that will be rewritten the next time policy changes. That is most workflows in most organizations, and it is why operations teams stop trusting their own automations after eighteen months.
Sommatic separates the two. Decisions reference the Knowledge Center — a governed store of policies, criteria, thresholds, taxonomies, contract terms, and operational rules. A node does not embed “approve if amount < 500”; it asks Knowledge Center for the current refund threshold for this customer tier, in this jurisdiction, under this product. The threshold changes when the policy changes — not when the workflow ships.
The substrate has structure. Each knowledge resource has an owner, a version, an effective date, a scope. When a workflow reads a policy at runtime, the trace records which version of which resource it consulted. Two months later, when a customer asks why their refund was denied, the answer points to the specific clause that was active at the time of the decision.
Policy lives in Knowledge. Workflows reach for it. The day the policy changes, the workflows do not need to.
This separation also lets non-engineers edit the things they are accountable for. Compliance owns the compliance criteria. Finance owns the credit policy. Engineering owns the graph that consumes them. The boundaries match the org chart instead of fighting it.
Agents inside a workflow
Most steps in a defensible workflow should be deterministic nodes — they are cheaper, faster, testable, and produce the same output for the same input. Determinism is the floor. Judgment is the exception.
When judgment is required — classifying a free-form complaint, summarizing a meeting transcript into action items, choosing which of three reviewers should see a document — the workflow uses an Agent. An Agent in Sommatic is not a free-roaming chat session. It is a goal-bound actor with an explicit allowlist of tools, a token and cost budget, a context window populated from Knowledge, and a contract for what it returns.
The tradeoff is real and worth naming. A deterministic node will behave the same way on day one and day seven hundred; an Agent’s behavior depends on the model, the prompt, the context, and the data drift behind all three. So the rule is: use deterministic nodes where you can, use Agents where you must, and contain Agents inside the contract of the workflow that called them.
Agents go in the graph, not around it. They take inputs, they return outputs, they pay a budget, they leave a trace.
When an Agent in Sommatic produces an output that crosses a risk threshold, the workflow does not just execute that output — it routes through a HITL gate first. The Agent proposes; the workflow disposes; the human signs.
HITL gates
Human-in-the-loop is a node. That sentence is the design.
When a workflow needs a person — to approve a refund, to disambiguate an extraction, to choose between two probable matches, to release a payment — the graph contains a human.task.create or human.approval.gate node. The engine pauses the instance, persists state, and emits a Task into the work queue. The task carries everything the human needs: the input that triggered it, the workflow’s interpretation so far, the policies in play, the proposed action, and the buttons that resume the flow.
The human’s interface is not a generic ticket UI. It is an Operational App — a purpose-built React surface that receives the task payload as input and submits a typed output. The Document Intelligence Desk for review of OCR’d documents. The Approval Desk for amount-based sign-offs. The Decision Explorer for cases where the operator needs to inspect the Agent’s reasoning before agreeing. Each app is its own versioned artifact, with its own input and output contracts, hosted by the App Engine and reached by the workflow through the sommatic.app.execute node.
When the human acts, the app calls submitOutput(). The Task closes. The workflow resumes from the edge after the gate, with the human’s decision attached to the envelope and the operator’s identity in the trace. The workflow does not care if the human took thirty seconds or thirty days.
The gate is part of the graph. The operator is part of the contract. The trace records both.
This is what makes the HITL design honest: humans are not a fallback for when the AI is unsure — they are typed checkpoints declared at design time, where the workflow knows in advance it will hand off, and the audit trail treats the human action with the same weight as any other node’s output.
The audit chain
Every node execution writes a record. Actor (which system or which human), node slug, input envelope, output envelope, the version of the workflow it ran in, the version of the policies it consulted, the time it took, the correlation ID that ties it to upstream and downstream events. Nothing the workflow does happens outside this chain.
That sounds like logging, and it is not. Logging is what an engineer reads when something broke. The audit chain is what an auditor reads when something is being questioned — and the difference is structure. A log line is prose; an audit record is typed evidence. The workflow IS the audit document.
This is the substrate for Explainability. When someone asks “why was this decision made?”, the answer is generated from the chain itself: this version of this workflow received this input, consulted this version of this policy, reached this node which called this Agent with this prompt, which returned this output, which was approved by this operator, which resulted in this write to this system of record. Not a story we wrote. The actual sequence the engine executed.
Explainability is not a feature you bolt on. It is what falls out when every step is typed and every transition is recorded.
It also changes how teams write workflows. Knowing that every node’s output will be readable a year later changes the care that goes into shaping it. The output envelope becomes a small contract: what does the next node need, what should the auditor see, what should the post-mortem be able to reconstruct?
Versioning and replay
Incidents in operational systems usually arrive as a question: what did the system do for customer X on date Y, and why? The traditional answer is a multi-day archaeology project — stack traces, log aggregation, partial reconstructions, and educated guesses about what the code looked like at the time. Versioned workflows collapse that.
The instance recorded the workflow version it ran on. The version is immutable. The audit chain recorded every input, every output, every transition. The Knowledge Center recorded the policy version each lookup consulted. Replay is not metaphor — the engine can re-execute the same graph against the same inputs and watch the same path unfold.
This changes post-mortem culture. The question stops being “what did the system probably do?” and becomes “what did the system actually do, and where in the graph would we change behavior to prevent this?” The answer is usually a specific node, a specific config, a specific policy reference — and the fix is a new workflow version with a clear diff against the old one.
Versioned graphs beat stack traces. A diff between v3 and v4 is a sentence anyone in the org can read.
Replay also makes it safe to evolve aggressively. Teams ship more workflow versions when they know yesterday’s runs are protected from today’s changes, and when they know the new version’s behavior can be exercised against historical inputs before going live.
Worked example: a document intake workflow, end-to-end
Here is what the pieces look like together. Imagine a workflow named document-intake-v7 that receives supplier invoices, validates them, and writes the ones that pass into the AP system. Seven nodes. One graph. End to end.
Node 1 — triggers.webhook. A supplier email gateway POSTs the document into the workflow. The webhook node validates the signature, writes the raw payload to evidence storage, and emits { document_url, supplier_id, received_at } on its out port.
Node 2 — io.ocr. Receives the document URL, calls the OCR adapter, returns extracted text and a page-level layout map. Failure here goes out the error port to a human review gate; success continues.
Node 3 — ai.extract. This is the first Agent in the graph. It receives the OCR text and a prompt assembled from a Knowledge resource (invoice-extraction-schema-v4). It returns a structured envelope: { invoice_number, supplier_tax_id, line_items[], total_amount, currency } plus a confidence score per field. The Agent has a token budget of 8k and a cost ceiling per invocation. The envelope is written to the trace before the next node sees it.
Node 4 — data.validate. A deterministic node. Checks that the extracted total matches the sum of line items, that the supplier tax ID exists in the supplier master, that the currency is one the org accepts. Fails go out the invalid port. Successes carry forward.
Node 5 — policy lookup via state.read against Knowledge Center. Asks for the current approval policy for this supplier tier and this amount. Returns { requires_human_approval: bool, approver_role: string }. The version of the policy resource consulted is logged in the trace.
Node 6 — human.approval.gate (conditional). If the policy required human review, the gate creates a Task assigned to a user in approver_role, surfaces it through the Approval Desk Operational App with the extracted fields, the source document, the validation results, and the policy clause that triggered the gate. The instance suspends. When the approver acts, the workflow resumes carrying { approved: bool, approver_id, decision_notes }.
Node 7 — integrations.postgresql. Writes the approved invoice to the AP database. Returns the new record ID.
Node 8 — audit.append. Closes the loop with a structured audit record: input hash, workflow version, all node outputs in order, policy versions consulted, Agent invocations and their costs, human approver if any, final write target and record ID.
The whole thing is roughly 200 lines of graph definition. Every step is replayable. Every decision points to its rule. The day legal asks why a specific invoice was approved on April 14th, the answer is one query away — and the answer is the workflow itself, not a story about it.
Eight nodes. One contract. Two years of defensibility.
Build for the inheritor
A workflow that holds up two years from now is one that the engineer who inherits it can read without asking anyone what it does, the auditor can interrogate without your help, and the policy owner can amend without filing a ticket. Sommatic’s job is to make that the easy path: versioned graphs, marketplace nodes, externalized knowledge, typed Agents, HITL as first-class nodes, audit as a byproduct of execution, and Omnisearch as the way anyone in the org finds the workflow when they need it. The goal is not to write fewer workflows. It is to write workflows that survive the people who wrote them, the policies they encoded, and the systems they integrated with — and to do that without ceremony, because the framework already encodes the discipline as an organizational cognitive layer.