Open Workflow GraphPre-release
Introduction

Quickstart

Write a valid OWG document, validate it, and understand what the graph now knows — in about ten minutes.

View as markdownMachine-readable source for agents and scripted implementers

This walks through the smallest complete OWG document, then adds the pieces that make it useful. You need Node 20 or newer.

1. What you need

A JSON editor and a validator that implements the four validation passes. Pointing your editor at the schema gives you completion and inline errors as you type:

{ "$schema": "https://openworkflowgraph.org/schemas/core/v0.92.json" }

2. The smallest complete document

A single task that transcodes one file. Save as hello.owg.json:

{
  "$schema": "https://openworkflowgraph.org/schemas/core/v0.92.json",
  "owg_version": "0.92",
  "id": "hello-transcode",
  "profiles": ["core", "cloud-services"],
  "description": "Transcode one source file MOV→MP4.",
  "objective": "Produce an MP4 delivery from a MOV source.",

  "organizations": [
    { "id": "org_mine", "name": "My Facility" }
  ],

  "participants": [
    { "id": "transcode_svc", "kind": "service", "name": "Transcode Service",
      "organization_id": "org_mine" }
  ],

  "infrastructure": [
    { "id": "cloud_saas", "type": "saas_platform", "owner": "org_mine" }
  ],

  "assets": [
    {
      "id": "source_mov",
      "role": "source",
      "type": "video.master",
      "content_type": "video/quicktime",
      "storage": { "provider": "s3", "locator": "s3://my-bucket/in/clip.mov" }
    },
    {
      "id": "delivery_mp4",
      "role": "delivery",
      "type": "video.delivery",
      "content_type": "video/mp4",
      "version_relation": "representation",
      "predecessor": "source_mov",
      "produced_by": "transcode",
      "storage": { "provider": "s3", "locator": "s3://my-bucket/out/clip.mp4" }
    }
  ],

  "tasks": [
    {
      "id": "transcode",
      "label": "Transcode MOV → MP4",
      "type": "work",
      "executor": { "type": "service", "ref": "transcode",
                    "environment": "saas" },
      "ai_role": "none",
      "performed_by": "transcode_svc",
      "ran_on": "cloud_saas",
      "used": ["source_mov"],
      "produced": ["delivery_mp4"],
      "failure_mode": "HALT"
    }
  ]
}

Three things to notice:

  • used and produced are the provenance edges. They are what make this a graph rather than a list. The asset's produced_by mirrors the task's produced[] — the task is authoritative.
  • version_relation: "representation" says the MP4 is a format change of the same content, not a revision of it. That distinction matters more than it looks — see Assets and versioning.
  • ai_role: "none" is declared explicitly rather than left absent. AI involvement is never inferred from the executor type.

3. Validate it

owg-validate hello.owg.json
✓ Valid — "hello-transcode" (v0.92): 1 task, 2 assets, 1 participant

Now break it deliberately. Change "used": ["source_mov"] to "used": ["source_mv"] and re-run:

✗ Invalid — 1 error(s):

  [OWG_UNKNOWN_REFERENCE] /tasks/0/used/0
    Task "transcode" uses "source_mv", which doesn't exist in this document.
    Did you mean "source_mov"?

Try a misspelled field too — change performed_by to performed_bye:

✗ Invalid — 1 error(s):

  [OWG_UNKNOWN_PROPERTY] /tasks/0
    Unknown property "performed_bye". Did you mean "performed_by"?

Both matter more than they look. Unknown properties are errors rather than silently accepted fields, which is what stops a generated document from validating and then doing nothing. See Validation.

Implementation note. The reference validator currently implements the structural pass fully and the referential, graph, and expression passes partially. Until they land, run the pre-flight checklist yourself.

4. What the graph now knows

From those few lines, without anything else being recorded:

  • Lineagedelivery_mp4 came from source_mov via transcode, as a format representation.
  • Attributiontranscode_svc performed it, on behalf of org_mine.
  • Placement — it ran on cloud_saas, so cost attributes somewhere real.
  • Location — both assets carry locators, so nothing had to move to be governed.

None of that required a separate provenance step. These are structural edges — they fall out of describing the work.

5. Add a chain and a human gate

Real workflows have dependencies and decisions. Add a review task:

{
  "tasks": [
    {
      "id": "transcode",
      "executor": { "type": "service" },
      "performed_by": "transcode_svc",
      "used": ["source_mov"],
      "produced": ["delivery_mp4"],
      "failure_mode": "HALT"
    },
    {
      "id": "qc",
      "type": "qc",
      "executor": { "type": "service", "ref": "qc_validate" },
      "performed_by": "transcode_svc",
      "depends_on": ["transcode"],
      "used": ["delivery_mp4"],
      "checks": ["duration_match", "codec_compliance"],
      "on_pass": "approve",
      "on_fail": "transcode",
      "max_reroutes": 2
    },
    {
      "id": "approve",
      "type": "review",
      "executor": { "type": "human" },
      "performed_by": "a.singh",
      "depends_on": ["qc"],
      "used": ["delivery_mp4"],
      "failure_mode": "HALT"
    }
  ]
}

Add a.singh to participants as kind: "human" with a role, and the document stays valid.

The qc task is a gate: it routes on outcome rather than merely succeeding, and max_reroutes caps how many times it can send work back. A human review is an ordinary task with executor.type: "human" — the same shape as a machine task, which is what lets a schedule and a cost model span both. See Gates and re-routes.

6. Add an AI step

{
  "id": "generate_thumb",
  "type": "work",
  "executor": { "type": "comfyui_graph", "environment": "cloud" },
  "ai_role": "generative",
  "performed_by": "agent_thumb",
  "ran_on": "gpu_cloud",
  "depends_on": ["approve"],
  "used": ["delivery_mp4"],
  "produced": ["thumb_png"],
  "subgraph": "graphs/sdxl_thumb.json"
}

With agent_thumb declared as an agent carrying operated_by:

{ "id": "agent_thumb", "kind": "agent", "operated_by": "a.singh",
  "organization_id": "org_mine" }

And the produced asset carrying credentials:

{ "id": "thumb_png", "type": "image.generated",
  "version_relation": "derivation", "predecessor": "delivery_mp4",
  "produced_by": "generate_thumb",
  "credentials": { "scheme": "c2pa" } }

That gives you three things at once:

  1. Accountability — the agent's work traces to a.singh via operated_by.
  2. Disclosureai_role: "generative" means an Article 50 manifest can be computed from lineage.
  3. Encapsulation — the whole node graph is one task with an interior, not fifty governed nodes.

Next steps