Skip to content

Run a deployment

replay runs a bundle against whatever substrate you point it at. The backend selector chooses the surface: --backend web (the default) drives a browser, and there, with no --url, it serves the bundled sample app so you can watch the loop end to end (--drift demonstrates governed re-resolution on that demo). Other substrates set --backend with its target flag instead of --url: --backend windows drives a native Windows desktop through its in-session agent (--agent-url), --backend rdp drives a pixel-only RDP transport or bound client window, and --backend citrix binds the exact Citrix Workspace/Viewer window without requiring software inside the remote session. The demo path is one example, not the definition. run is the same execution path wired for a real deployment (a backend, effect verification, API actuation, a durable runtime, and a policy) all from one deployment.yaml, which is where a governed run gets its substrate: from the config's backend section, not from --url. This guide takes a certified bundle to a governed deployment run. Passing it does not by itself qualify a backend or workflow for production; qualify each workflow in its real environment.

One config wires the whole run

Write a deployment.yaml (see the full schema):

name: clinic-triage
backend:
  url: https://emr.internal.example.org
effects:
  kind: fhir
  base_url: https://emr.internal.example.org/apis/default/fhir
  resource_type: Observation
  access_token: "${OPENEMR_FHIR_TOKEN}"
runtime:
  durable: true
policy:
  policy: clinical-write

certify and run read the same file, so the bundle is certified against the policy it will run under.

Prepare, inspect, then run

run is stricter than replay: by default it refuses a plaintext bundle, uncertified policy, unarmed consequential action, write without an effect contract, unavailable verifier without explicit approval, or broken manifest. Normal compilation creates a plaintext bundle, so create a production copy and seal it with the shipped CLI before admission.

export OPENADAPT_BUNDLE_KEY='<inject from your secret manager>'
openadapt flow seal bundle --out bundle-prod

openadapt flow certify bundle-prod --config deployment.yaml
openadapt flow run bundle-prod --config deployment.yaml --dry-run
openadapt flow run bundle-prod --config deployment.yaml

The --dry-run form prints every admission-gate verdict and never executes, pass or fail. Once admitted, run uses the identical executor as replay (resolution ladder, identity gate, effect verification, durable checkpoints). The demo-only --drift teaching aid is not offered; the backend URL, system of record, actuation tier, durability, and policy come from the config. Direct flags override individual fields for a single run.

seal preserves the source, refuses symlinks and an existing destination, encrypts workflow JSON and template crops, verifies the result, and expires any certification inherited from the source. The key comes from the environment; production key custody, rotation, and recovery are operator responsibilities.

Verify writes against the system of record

With effects configured, each consequential write is verified against the real record, not the screen. CONFIRMED proceeds; REFUTED or INDETERMINATE halts. A step that declares effects while no verifier is configured is refused by run unless the operator supplies --approve-unverified-writes. That fallback is auditable approval, not independent verification.

You can also wire effects from flags for a quick run:

openadapt flow run bundle --url https://app.example.org \
  --effects-kind rest --effects-base-url https://app.example.org

Actuate through the API where one exists

Where the target app exposes a real API, driving its GUI to make the write is the wrong tool. With actuation.api: true (or --api-actuator / --api-base-url), a step carrying an ApiBinding performs the write by calling the API and confirms it with the same effect verifier, skipping the GUI. It is an optimization whose safe fallback is always the GUI.

Durable runs pause and resume

With runtime.durable: true (or --durable), the run checkpoints each verified step and, on a halt, writes a pending escalation and stops. Approve and resume it without re-running a confirmed write:

openadapt flow approve runs/replay-20260712-140233
openadapt flow resume  runs/replay-20260712-140233 --require-approval

resume rebuilds a live backend from backend.url (or --url), re-binds the run's parameters, and continues from the last verified checkpoint.

Keep it local by default

Nothing above requires the network beyond your own systems of record. The model tiers stay off unless you set runtime.allow_model_grounding: true (or --allow-model-grounding) and point the runtime at an on-prem VLM appliance. Left off, the run is fully local and makes zero outbound model calls, and the report says so explicitly. See Deploy on-prem for the data-handling boundaries.