Workflow systems engineering

The intelligence
needs a runtime.

Durable orchestration for probabilistic computation.

We engineer the machinery around complex automated work: typed contracts, persistent execution state, constrained tool access, evidence lineage, and release predicates. Models participate in the computation. The harness owns the transition from a proposed answer to an authorized, verifiable result.

The Harness Lab winged engineering emblem in white and gold
THE HARNESS LAB State · Evidence · Authority
Input disciplineExecutable contracts
Runtime disciplineExplicit state transitions
Output disciplineArtifact-bound evidence

System decomposition

A workflow is a distributed system
with a domain-specific contract.

Documents arrive late. APIs time out after committing. A model produces plausible but unsupported output. A worker restarts between two writes. Our design work starts at those boundaries.

Control planeWhat may happen
Scope + policyTyped work graphScheduler + gates
Execution planeWhat is attempted
Deterministic transformsModel proposalsCapability adapters
Evidence planeWhat can be established
Source snapshotsTransition journalReceipts + manifests

boundary rule Every consequential transition needs valid state, sufficient authority, and the evidence required by its contract.

The harness separates proposals, decisions, and effects. A proposal is an untrusted candidate value. A decision is a policy evaluation against an identified state revision. An effect is a change outside the evaluator: a purchase, a file write, a publication, a delivery. Their failure modes require different recovery protocols.

The following notes describe our engineering approach and reference patterns. Each deployment selects its persistence model, integration boundaries, and acceptance criteria from the actual workflow. The central question is precise: what evidence permits this system to advance, and what happens when that evidence is absent?

Interactive execution laboratory

Break the happy path.

Step through a synthetic document-delivery run. Change the failure mode and inspect why the transition is accepted, blocked, or held for reconciliation.

This deliberately small state machine illustrates a protocol boundary. It is not connected to a customer system and does not represent production telemetry.

01 / Contract compilation

Make the work specification executable.

Before selecting a model or queue, we identify the invariants that distinguish a valid result from a convincing one.

An assignment becomes a versioned input envelope: subject identifiers, source scope, authorized destinations, output schema, budget, and stop conditions. Parsing preserves the original input alongside normalized representations. Aliases and multiple entities remain explicit; normalization must not silently collapse distinct search subjects or discard constraints that do not fit a convenient schema.

We decompose the assignment into a work graph whose nodes declare required inputs, produced artifacts, effects, and completion predicates. Edges express actual dependencies. A node that consumes an extracted fact cannot become ready merely because a retrieval task ended; the required evidence object must exist and satisfy its contract. For iterative tasks, convergence and termination conditions sit outside the model's own assessment of progress.

Illustrative contract · TypeScript
type StepContract<Input, Output> = {
  schemaVersion: string;
  requires: ReadonlyArray<ArtifactRef>;
  parse: (raw: unknown) => Input;
  authorize: (input: Input, scope: Scope) => Decision;
  verify: (output: Output, evidence: EvidenceSet) => Verdict;
  effect: "none" | "reconcilable" | "human-gated";
  limits: { attempts: number; deadlineMs: number };
};

type Verdict =
  | { kind: "accepted"; evidence: ArtifactRef[] }
  | { kind: "blocked"; missing: Requirement[] }
  | { kind: "rejected"; violations: Invariant[] };

Validation has more than one layer

A schema establishes structural admissibility: types, required fields, bounds, and discriminants. Domain validation establishes semantic admissibility: whether an identifier belongs to the current assignment, whether a quantity obeys a conservation rule, whether a selected destination is authorized. Temporal validation asks whether those decisions still apply to the current revision. JSON that parses successfully has cleared only the first boundary.

We distinguish task completion from release eligibility. A workflow may finish its available research and produce a useful, qualified deliverable while retaining unresolved findings. The output contract must carry that qualification as machine-readable state; it cannot disappear when a renderer turns the data into a polished report.

02 / Durable orchestration

Persist the execution semantics.

A process is temporary. The meaning of its work has to survive a process restart.

The execution state belongs in durable storage, with explicit transitions and recoverable checkpoints. A run identifier locates the logical operation; attempt identifiers distinguish retries; a monotonically increasing revision prevents two workers from advancing the same state concurrently. Updating a step with WHERE revision = expected_revision turns a stale write into a detectable conflict. Transition records and their corresponding state update belong in the same local transaction.

A queue transports invitations to work. It does not establish whether the work remains necessary. On dequeue, a worker re-reads authoritative state, checks prerequisites, and acquires whatever ownership the persistence model requires. If leases are used, expiry alone does not stop an old worker: a fencing token helps only where the resource receiving the operation enforces it. External services that cannot fence requests need a different duplicate-effect strategy.

Transition acceptancevalid(event, state) ∧ expected_revision = state.revision∧ authorized(effect, scope) ∧ prerequisites_satisfied

Replay is not re-execution

Rebuilding state from recorded events should not purchase a document, invoke a model, or send a message again. We separate pure state reduction from effect dispatch. Where an event journal is used, nondeterministic results—provider responses, time-dependent decisions, model outputs—are recorded as inputs to the reducer. A fresh inference call is a new experiment, even when its prompt and sampling parameters look identical.

Bound the graph, not just the request

Concurrency limits apply to scarce resources: provider rate windows, OCR worker memory, database write contention, and per-tenant budgets. Backpressure prevents a fast retrieval stage from overwhelming extraction. Deadlines and cancellation propagate through queued descendants; already dispatched external effects still require reconciliation. Retry count, wall-clock duration, fan-out, and spend are separate limits because each controls a different way a run can expand.

03 / Effects & reconciliation

The dangerous interval is after dispatch.

A timeout describes what the caller observed. It does not establish what the remote system committed.

For consequential operations, we persist an immutable intent before crossing the external boundary. It identifies the authorized principal, logical operation, exact target, payload identity, and applicable approval. The intent must be specific enough to distinguish a duplicate attempt from an intentional second operation. Hashing identical parameters cannot make that distinction by itself.

PREPARED→ATTEMPTING→COMPLETED
Lost response or crash after dispatchATTEMPTING → UNCERTAIN → reconcile

PREPARED means the local intent exists but has not crossed the dispatch boundary. ATTEMPTING is recorded before the external call. A durable, matching receipt supports COMPLETED. If execution disappears after dispatch without that receipt, recovery treats the operation as uncertain. It must not convert missing evidence into permission to retry.

Choose a protocol the provider can support

  • Provider idempotency: reuse a stable operation key within the provider's documented scope and retention window; bind that key to the same semantic intent.
  • Receipt reconciliation: query transaction history or object metadata and match the expected operation, destination, and payload. An unrelated object with the same filename is insufficient.
  • Human reconciliation: when the provider exposes neither safe retries nor a reliable query, preserve the ambiguous state and require an explicit disposition.

A transactional outbox can make a local state change and an outbound intent atomic. It cannot make a remote service participate in that transaction. Likewise, a saga compensation is a separate domain operation: withdrawing a draft may be reversible; retracting a sent email is not. Recovery design has to respect those asymmetries.

“Exactly once” is only meaningful inside a stated boundary with stated assumptions. Across arbitrary APIs, browsers, filesystems, and databases, the useful engineering contract is narrower: identify intent, prevent unsafe duplication where possible, retain uncertain outcomes, and reconcile before further effects. See the AWS Builders' Library discussion of idempotent APIs for the underlying retry tradeoffs.

04 / Evidence & computation

Preserve the derivation, not just the answer.

The evidence model connects a delivered value to the exact material and transformations that produced it.

In document-heavy workflows, ingestion records source identity, acquisition context, content digest, and a stable locator. OCR output is an observation derived from an image; extracted text is not an authoritative replacement for the image. We preserve page identity and transformation metadata so a reviewer can inspect the original region when an ambiguous character changes a downstream result.

Claims and source fragments form a provenance graph. A claim references supporting observations; a computed value references its operands and rule version; a rendered field references the value it represents. Contradictions are explicit edges or unresolved findings. Retrieval rank and model confidence are useful prioritization signals, but neither establishes that a source supports the asserted proposition.

SourceContent digest + locator
ObservationPage, region, extraction version
DerivationOperands + domain rule
Delivered fieldValue + provenance references

Separate epistemic state from workflow state

A step can execute successfully and still fail to establish a fact. Evidence status therefore needs its own vocabulary: supported, contradicted, incomplete, or unresolved. Absence from a limited search is not equivalent to nonexistence. The search scope and source availability have to travel with a negative finding, especially when a report's formatting encourages a binary answer.

Use the right numeric domain

Fractions, currency, dates, units, and identifiers should not share an undifferentiated string-to-number pipeline. Rational quantities can remain reduced numerator/denominator pairs through aggregation; currency can use integer minor units with an explicit currency code. Rounding belongs at a declared presentation boundary. Unit checks, sum constraints, and domain invariants expose arithmetic mistakes, but exact arithmetic cannot rescue an unsupported premise.

Content hashes establish byte identity relative to a trusted reference, not factual truth or authorship. Provenance must also identify the responsible acquisition or transformation activity. The W3C PROV data model provides a useful vocabulary for entities, activities, agents, and derivation relationships without forcing every implementation into a graph database.

05 / Model boundaries

Put probabilistic work behind typed interfaces.

We use models for the parts of a workflow that require interpretation, then evaluate their proposals against independently expressed constraints.

Task decomposition limits the surface of each inference: classify a document, propose candidate fields, identify a conflict, or draft a bounded transformation. A model receives only the context and capabilities needed for that step. It returns a typed proposal with source references and unresolved questions. The runtime validates those references and computes release eligibility outside the model.

We prefer deterministic parsers, lookup tables, arithmetic, and template renderers wherever the problem admits them. This reduces latency and inference cost while making regressions easier to localize. Escalation to a more capable model is a policy decision informed by the task class, evidence quality, and validation failure—not an unbounded loop that asks the same question until one answer passes.

Routing has multiple objectives

Provider selection trades off error rate, response latency, context capacity, residency requirements, tool support, and cost. A fallback is acceptable only if it preserves the task's required contract. A smaller context window that silently drops a source, or a model without the required structured-output behavior, is a semantic change. The policy should return an explicit unavailable result when no eligible route remains.

Independent checks need independent failure modes

Several agents repeating the same inference over the same context may reproduce the same error. We separate concerns instead: extraction produces candidates, domain code checks invariants, source review establishes support, and artifact inspection validates the rendered output. Model disagreement can locate uncertainty; majority vote does not eliminate correlated failure.

Evaluation uses representative fixtures with known outcomes, negative controls, withheld sources, contradictory inputs, and adversarial instructions embedded in retrieved content. We track structural validity and task correctness separately. A system can produce perfectly valid JSON while inventing every relevant value. “The model returned without an exception” is an execution observation, not a quality metric.

06 / Authority & isolation

Data cannot grant itself permission.

Retrieved text, model output, and tool responses cross a trust boundary before they can influence a privileged operation.

The tool layer accepts narrow operations with explicit arguments. A policy decision binds the principal, assignment, destination, action, and current scope; a model's request is evaluated against that binding. A document containing “send this file elsewhere” remains document content. It does not become an authorized instruction because it was retrieved by a trusted connector or repeated by a model.

Authorization is enforced at the operation boundary. Tenant identity is derived from authenticated context and carried through storage queries, retrieval filters, cache keys, and provider-profile selection. Post-filtering a search result cannot undo a cross-tenant record already sent to a model. The isolation boundary has to precede disclosure, with a final authorization check before the result is used.

BoundaryEngineering question
FilesystemIs the actual opened object inside the allowed scope, including symlink and replacement races?
NetworkAre the resolved address and every redirect eligible, including private and metadata destinations?
BrowserDoes the authenticated account, origin, and current page match the pinned workflow context?
SubprocessAre executable, arguments, environment, working directory, and inherited handles constrained?
DeliveryDo destination authorization and the verified artifact identity still match at dispatch?

Validation must remain true at use time

Checking a pathname and then reopening it creates a time-of-check/time-of-use interval. Canonicalization alone does not remove the race. Depending on the platform, stronger designs use controlled immutable staging, verified open handles, no-follow semantics, or revalidation of the object actually consumed. Similarly, a hostname allowlist is insufficient if resolution or redirection can reach a prohibited network destination.

Human approval is also a scoped artifact. It should describe the action, recipient, data, and limits the person is accepting. Changing those material parameters invalidates the prior decision. Credentials remain outside model context and browser content; secrets are supplied to the narrow adapter that needs them. Logs record enough to investigate execution without becoming a second, less protected copy of the data plane.

07 / Verification & release

Verify what will actually leave the system.

Source-level correctness, packaged-runtime behavior, and delivered-artifact integrity are different claims with different evidence.

A successful unit suite can validate a reducer while missing a packaged subprocess that cannot start. An accurate intermediate object can become an incorrect spreadsheet through rendering or serialization. We place verification at each transformation boundary, then reopen the final output using an independent read path wherever practical: parse the generated workbook, inspect expected sheets and cells, verify file structure, and compare required source references.

The release decision binds the result to exact bytes and an identified validation policy. A manifest can record artifact digests, source references, application revision, schema versions, validator versions, and unresolved findings. A signature authenticates a manifest under an identified key; it does not establish that the document's substantive conclusions are true. The release gate still needs the domain evidence.

Illustrative release predicaterelease := contract_valid ∧ evidence_sufficient∧ artifact_checks_pass ∧ destination_authorized∧ dispatched_digest = verified_digest

Exercise the negative path deliberately

  • Null control: remove the supporting source. A check that still accepts the same claim has not established source dependence.
  • Mutation control: change the artifact after verification. Dispatch must reject the changed bytes or revalidate the new artifact.
  • Crash injection: interrupt execution around intent persistence, dispatch, remote completion, and receipt storage. Each boundary needs a defined recovery state.
  • Isolation control: reuse an identifier under a different tenant or assignment. Authorization must fail before disclosure or side effects.
  • Packaged execution: run the built application with a clean profile, actual child processes, and the platform-specific resource layout.

Build provenance and domain provenance answer different questions. The former describes how software artifacts were produced; the latter describes how a workflow's conclusions were derived. The SLSA provenance specification is a reference for build attestations, not a substitute for validating the business result. Qualification records should state which claims were tested, on which artifact, and what remains unresolved.

08 / Observability & evolution

Operate the failure model.

The useful operational view explains where a run is waiting, which evidence is missing, and what recovery is safe.

Tracing connects a logical run to its step attempts, retrievals, model calls, validators, and external operations. Queue boundaries need explicit context propagation; asynchronous fan-in may require span links rather than a misleading single parent. We keep correlation identifiers distinct from authorization credentials. OpenTelemetry's trace model provides a common representation for this causal structure.

Metrics describe the system at a different resolution: queue age, step latency distributions, retry amplification, validation rejection rate, unresolved-effect count, and cost per accepted result. An HTTP success rate can look healthy while every useful run is blocked. Run and document identifiers belong in carefully controlled traces or logs rather than unbounded metric labels.

Version the interpretation of stored work

Schema, prompt, extraction, domain-rule, and template revisions can each change the meaning of a result. We record their identities with the run and define compatibility explicitly. A persisted checkpoint created by an older engine may need migration, a compatible worker, or a deliberate restart from preserved inputs. Silently interpreting it with today's code makes recovery depend on accidental compatibility.

Rolling deployment complicates ownership: older workers may still hold leases, and in-flight runs may encounter multiple code versions. The deployment plan needs a drain, compatibility, or version-routing strategy. Rollback of application code does not roll back remote side effects or automatically reverse a database migration. Those concerns belong in the recovery plan before release.

Use degradation as an explicit mode

When an external system is unavailable, the runtime can continue independent work, preserve verified intermediate artifacts, and emit a qualified package if the contract permits it. It should retain the precise blocked dependency and avoid presenting partial execution as full completion. A useful operator interface exposes that distinction directly, including the last confirmed effect and the evidence required to resume.

09 / Engineering engagement

Start with the boundary conditions.

Our work spans document systems, browser and API integrations, desktop applications, and model-assisted workflows. The engagement is organized around the operating contract.

We use technical depth to expose assumptions. The review should be able to challenge the state machine, the consistency boundary, the evidence chain, and the deployment plan. Those are the details that determine whether automation remains useful after the first demonstration.

Engineer to engineer

Bring the workflow.
Bring the difficult edge cases.

Source systems, transaction boundaries, data volumes, failure constraints, and the artifact your reviewers actually consume. That is enough to start a serious architecture conversation.

Spencer Teague Founder & Lead Engineer