Skip to content

Architecture model

A C4 model of Dirigent, generated from the Structurizr model in architecture/workspace.dsl. Every box is labelled with its type. For the interactive viewer, with zoom and click-through between levels, see architecture/README.md.

What each package is for, and what may depend on what, is on the architecture page.

L1 - System landscape

graph LR

  subgraph diagram ["System Landscape View"]

    1["Pipeline author<br/>[Person]<br/>Writes pipeline documents in YAML or the builder, applies them, and starts and reads runs."]
    10["Chap<br/>[Software System]<br/>Climate-and-health modelling platform (chap-core). Datasets, backtests and predictions over HTTP."]
    11["FHIR servers<br/>[Software System]<br/>Any FHIR R4 server: HAPI FHIR, a cloud FHIR service, a facade. Resources read, searched and written over REST."]
    12["Open climate service<br/>[Software System]<br/>openEO-style climate data service. Aggregates climate data to org units and runs batch jobs."]
    13["S3-compatible storage<br/>[Software System]<br/>Buckets the storage blocks and storage sources read and write. AWS S3, RustFS, MinIO."]
    14["Kafka / RabbitMQ<br/>[Software System]<br/>Message brokers. Topics and queues the queues pack consumes from and publishes to."]
    15["Alert channels<br/>[Software System]<br/>SMTP, Slack and webhook receivers an alert rule delivers through."]
    16["HTTP APIs<br/>[Software System]<br/>Any HTTP service an http.request step reaches, or that calls an endpoint source."]
    17["Dirigent<br/>[Software System]<br/>Generic pipeline orchestrator. Pipelines are documents built from pluggable blocks; every run, attempt and due time is a row."]
    2["Operator / admin<br/>[Person]<br/>Runs the processes, holds connections, users, tokens and schedules, and watches health and alerts."]
    3["AI agent<br/>[Person]<br/>A coding agent operating an instance through dirigent-mcp, bounded by the role of its token."]
    4["dirigent-dhis2<br/>[Software System]<br/>Adapter pack (winterop-com/dirigent-dhis2): the dhis2 connection kind, DHIS2 formats, and blocks for jobs, imports, metadata, tracker and analytics."]
    5["dirigent-fhir<br/>[Software System]<br/>FHIR pack (dirigent-fhir): the fhir connection kind and the REST blocks for one FHIR R4 server, built on the dhis2w-fhir engine's R4 models."]
    6["dirigent-contrib<br/>[Software System]<br/>Block packs for outside systems (winterop-com/dirigent-contrib), one package with a subpackage per system."]
    9["DHIS2<br/>[Software System]<br/>Health information system. Source and destination of data values, metadata, tracker data and analytics."]

    17-. "Calls pack blocks<br/>[in-process, entry point dirigent.plugins.v1]" .->4
    17-. "Calls pack blocks<br/>[in-process, entry point dirigent.plugins.v1]" .->5
    17-. "Calls pack blocks<br/>[in-process, entry point dirigent.plugins.v1]" .->6
    17-. "http.request, webhook.post<br/>[HTTPS]" .->16
    17-. "storage blocks, storage sources<br/>[S3 API]" .->13
    17-. "Consumes and publishes<br/>[Kafka, AMQP]" .->14
    17-. "Delivers alerts<br/>[SMTP, HTTPS]" .->15
    4-. "Implements" .->17
    5-. "Implements" .->17
    6-. "Implements" .->17
    4-. "Reads and writes<br/>[DHIS2 Web API]" .->9
    5-. "Reads, searches, and writes conditionally and in transactions<br/>[FHIR R4 REST, JSON]" .->11
    6-. "Imports data, runs backtests and predictions<br/>[HTTP/JSON]" .->10
    6-. "Aggregates, runs batch jobs<br/>[HTTP/JSON]" .->12
    12-. "Delivers saved exports<br/>[DHIS2 Web API]" .->9
    1-. "Builds pipelines, starts and reads runs<br/>[HTTPS]" .->17
    2-. "Manages connections, users, schedules and alerts" .->17
    3-. "Calls tools<br/>[MCP over stdio]" .->17
    16-. "Calls an endpoint source<br/>[HTTPS POST /endpoints/...]" .->17

  end

L2 - Containers: Dirigent

graph TB

  subgraph diagram ["Container View: Dirigent"]

    1["Pipeline author<br/>[Person]<br/>Writes pipeline documents in YAML or the builder, applies them, and starts and reads runs."]
    2["Operator / admin<br/>[Person]<br/>Runs the processes, holds connections, users, tokens and schedules, and watches health and alerts."]
    3["AI agent<br/>[Person]<br/>A coding agent operating an instance through dirigent-mcp, bounded by the role of its token."]
    16["HTTP APIs<br/>[Software System]<br/>Any HTTP service an http.request step reaches, or that calls an endpoint source."]

    subgraph 17 ["Dirigent"]

      18["Web UI<br/>[Container: React SPA]<br/>Pipeline builder, run grid and logs, connections, schedules, sources and alerts. Built from the block catalog."]
      19["API server<br/>[Container: FastAPI / Uvicorn (Python)]<br/>dg server. The REST API, the web UI bundle, SSE streams, and endpoint sources. Embeds the scheduler unless --no-scheduler."]
      26["Scheduler<br/>[Container: asyncio (Python)]<br/>dg scheduler, or embedded in dg server. Turns due schedules into run rows. Time, and only time."]
      27["Worker [1..*]<br/>[Container: asyncio (Python)]<br/>dg worker. Claims due attempts and calls blocks; polls and holds sources; sweeps leases and deadlines; delivers alerts. Routed by capability tags."]
      41["dg CLI<br/>[Container: Typer (Python)]<br/>Applies documents, starts and watches runs, and starts the server, worker and scheduler processes."]
      42["dirigent-mcp<br/>[Container: MCP over stdio (Python)]<br/>MCP server. Every tool is a call the Python client makes; nothing deletes."]
      43[("Database<br/>[Container: PostgreSQL 17; SQLite under dg dev]<br/>Pipeline versions as JSONB documents; runs, items, attempts, leases and due times as indexed rows; logs; the worker registry.")]
      44[("Artifact storage<br/>[Container: file:// or s3:// (dirigent-storage-s3)]<br/>Step outputs too large to inline, and each run's scratch prefix. Never a worker-local path.")]
    end

    27-. "http.request, webhook.post<br/>[HTTPS]" .->16
    1-. "Builds pipelines, starts and reads runs<br/>[HTTPS]" .->18
    1-. "Applies documents, runs and watches pipelines" .->41
    2-. "Manages connections, users, schedules and alerts" .->18
    2-. "Starts processes, migrates, checks health" .->41
    3-. "Calls tools<br/>[MCP over stdio]" .->42
    18-. "Loads the bundle<br/>[HTTPS]" .->19
    41-. "Applies, runs, cancels, retries<br/>[HTTP/JSON (dirigent-client)]" .->19
    41-. "Migrates the schema, ensures connections<br/>[SQL]" .->43
    42-. "Calls the API with the agent's token<br/>[HTTP/JSON (dirigent-client)]" .->19
    16-. "Calls an endpoint source<br/>[HTTPS POST /endpoints/...]" .->19
    19-. "Reads and writes definitions; creates ad hoc runs<br/>[SQL, JSONB]" .->43
    19-. "Streams artifacts<br/>[file:// or s3://]" .->44
    26-. "Holds the leader lock; claims due schedules and inserts their runs<br/>[pg_advisory_lock, FOR UPDATE SKIP LOCKED]" .->43
    27-. "LISTEN dirigent_work<br/>[pg_notify]" .->43
    27-. "Writes and reads outputs<br/>[file:// or s3://]" .->44

  end

L3 - Components: API server

graph TB

  subgraph diagram ["Component View: Dirigent - API server"]

    16["HTTP APIs<br/>[Software System]<br/>Any HTTP service an http.request step reaches, or that calls an endpoint source."]

    subgraph 17 ["Dirigent"]

      subgraph 19 ["API server"]

        20["API routes<br/>[Component]<br/>/api/v1: pipelines and apply, runs, sources, triggers, connections, alerts, users, workers, system."]
        21["Auth<br/>[Component]<br/>Session cookie for the UI, bearer token for automation. Viewer, operator and admin roles."]
        22["Event streams<br/>[Component]<br/>SSE tails of a run's log entries and events, woken by dirigent_settled."]
        23["Endpoint intake<br/>[Component]<br/>/endpoints: checks a call in a fixed order (route, token, rate, type, size, signature), records the input, creates the run."]
        24["Reply waiter<br/>[Component]<br/>One reader per process. Answers each held caller with the first reply to settle, or with the run's failure, or 504 at its deadline."]
        25["UI host<br/>[Component]<br/>Serves the SPA bundle and the shell for its deep links."]
      end

      18["Web UI<br/>[Container: React SPA]<br/>Pipeline builder, run grid and logs, connections, schedules, sources and alerts. Built from the block catalog."]
      41["dg CLI<br/>[Container: Typer (Python)]<br/>Applies documents, starts and watches runs, and starts the server, worker and scheduler processes."]
      42["dirigent-mcp<br/>[Container: MCP over stdio (Python)]<br/>MCP server. Every tool is a call the Python client makes; nothing deletes."]
      43[("Database<br/>[Container: PostgreSQL 17; SQLite under dg dev]<br/>Pipeline versions as JSONB documents; runs, items, attempts, leases and due times as indexed rows; logs; the worker registry.")]
      44[("Artifact storage<br/>[Container: file:// or s3:// (dirigent-storage-s3)]<br/>Step outputs too large to inline, and each run's scratch prefix. Never a worker-local path.")]
    end

    18-. "Loads the bundle<br/>[HTTPS]" .->25
    18-. "Reads and writes<br/>[HTTP/JSON]" .->20
    18-. "Follows logs and events<br/>[SSE]" .->22
    41-. "Applies, runs, cancels, retries<br/>[HTTP/JSON (dirigent-client)]" .->20
    41-. "Watches a run<br/>[SSE]" .->22
    41-. "Migrates the schema, ensures connections<br/>[SQL]" .->43
    42-. "Calls the API with the agent's token<br/>[HTTP/JSON (dirigent-client)]" .->20
    16-. "Calls an endpoint source<br/>[HTTPS POST /endpoints/...]" .->23
    20-. "Authenticates every call" .->21
    20-. "Reads and writes definitions; creates ad hoc runs<br/>[SQL, JSONB]" .->43
    20-. "Streams artifacts<br/>[file:// or s3://]" .->44
    22-. "Tails log entries; LISTEN dirigent_settled<br/>[SQL, LISTEN]" .->43
    23-. "Records the input, creates the run; LISTEN dirigent_sources for routes<br/>[SQL, LISTEN]" .->43
    23-. "Holds the caller when a reply can answer" .->24
    24-. "Reads rendered replies; LISTEN dirigent_settled<br/>[SQL, LISTEN]" .->43
    24-. "Streams a body_from reply<br/>[file:// or s3://]" .->44

  end

L3 - Components: engine and worker

graph TB

  subgraph diagram ["Component View: Dirigent - Worker [1..*]"]

    13["S3-compatible storage<br/>[Software System]<br/>Buckets the storage blocks and storage sources read and write. AWS S3, RustFS, MinIO."]
    14["Kafka / RabbitMQ<br/>[Software System]<br/>Message brokers. Topics and queues the queues pack consumes from and publishes to."]
    15["Alert channels<br/>[Software System]<br/>SMTP, Slack and webhook receivers an alert rule delivers through."]
    16["HTTP APIs<br/>[Software System]<br/>Any HTTP service an http.request step reaches, or that calls an endpoint source."]
    4["dirigent-dhis2<br/>[Software System]<br/>Adapter pack (winterop-com/dirigent-dhis2): the dhis2 connection kind, DHIS2 formats, and blocks for jobs, imports, metadata, tracker and analytics."]
    5["dirigent-fhir<br/>[Software System]<br/>FHIR pack (dirigent-fhir): the fhir connection kind and the REST blocks for one FHIR R4 server, built on the dhis2w-fhir engine's R4 models."]
    6["dirigent-contrib<br/>[Software System]<br/>Block packs for outside systems (winterop-com/dirigent-contrib), one package with a subpackage per system."]

    subgraph 17 ["Dirigent"]

      subgraph 27 ["Worker [1..*]"]

        28["Wake-ups<br/>[Component]<br/>LISTEN on dirigent_work. A commit wakes idle claims instead of the next poll; a lost one costs the poll it replaced."]
        29["Claim<br/>[Component]<br/>One query: a queued attempt past available_at, or a waiting one past next_poll_at, by priority then fairness. FOR UPDATE SKIP LOCKED, filtered by tags."]
        30["Executor<br/>[Component]<br/>Calls one block under a per-worker semaphore: execute, probe, fetch or poke. Commits a remote handle the moment it returns."]
        31["Readiness and run status<br/>[Component]<br/>The last statement of every outcome transaction: readies dependents, renders replies, derives the run's status."]
        32["Run creation<br/>[Component]<br/>Inserts a run, its items and attempt rows in one transaction, under the pipeline's lock. Shared by the API, the scheduler and sources."]
        33["Recovery and deadline sweeps<br/>[Component]<br/>Reclaims expired leases (waiting if a handle was committed, else queued), settles overdue deadlines, flags stuck runs, reaps dead workers."]
        34["Polled sources<br/>[Component]<br/>Leases each due storage or sensor source, polls it with no lock held, makes a run per input and stores the cursor."]
        35["Held sources<br/>[Component]<br/>Keeps kafka and rabbitmq consumers open under a lease. A message is acknowledged only after its run commits."]
        36["Alert dispatcher<br/>[Component]<br/>Claims queued notifications and delivers each through its channel, retried like an attempt."]
        37["Plugin host<br/>[Component]<br/>Discovers packs through pluginkit entry points at startup, then dispatches by block id."]
        38["Block contract<br/>[Component]<br/>dirigent-plugin: Operator, Sensor, source kinds, notifiers, storage backends, connection kinds and formats."]
        39["Built-in blocks<br/>[Component]<br/>dirigent-blocks: http, storage, execute, sql, jq, queues and parquet families, and the alert channels."]
        40["Storage facade<br/>[Component]<br/>Dispatches URIs by scheme. Keeps a small output inline and a large one as a URI."]
      end

      43[("Database<br/>[Container: PostgreSQL 17; SQLite under dg dev]<br/>Pipeline versions as JSONB documents; runs, items, attempts, leases and due times as indexed rows; logs; the worker registry.")]
      44[("Artifact storage<br/>[Container: file:// or s3:// (dirigent-storage-s3)]<br/>Step outputs too large to inline, and each run's scratch prefix. Never a worker-local path.")]
    end

    37-. "Calls built-in blocks" .->39
    37-. "Calls pack blocks<br/>[in-process, entry point dirigent.plugins.v1]" .->4
    37-. "Calls pack blocks<br/>[in-process, entry point dirigent.plugins.v1]" .->5
    37-. "Calls pack blocks<br/>[in-process, entry point dirigent.plugins.v1]" .->6
    39-. "http.request, webhook.post<br/>[HTTPS]" .->16
    39-. "storage blocks, storage sources<br/>[S3 API]" .->13
    39-. "Consumes and publishes<br/>[Kafka, AMQP]" .->14
    39-. "Delivers alerts<br/>[SMTP, HTTPS]" .->15
    4-. "Implements" .->38
    5-. "Implements" .->38
    6-. "Implements" .->38
    28-. "LISTEN dirigent_work<br/>[pg_notify]" .->43
    28-. "Wakes" .->29
    29-. "Claims attempt rows<br/>[FOR UPDATE SKIP LOCKED]" .->43
    29-. "Hands over the claimed attempt" .->30
    30-. "Resolves the block by id" .->37
    30-. "Commits handles, heartbeats the lease, writes logs<br/>[SQL, JSONB]" .->43
    30-. "Persists the output" .->40
    30-. "Records the outcome" .->31
    31-. "Settles the attempt, readies dependents; NOTIFY dirigent_work, dirigent_settled<br/>[SQL, pg_notify]" .->43
    40-. "Writes and reads outputs<br/>[file:// or s3://]" .->44
    33-. "Sweeps leases, deadlines, stuck runs, dead workers<br/>[SQL]" .->43
    34-. "Leases due sources; stores the cursor<br/>[SQL]" .->43
    34-. "Polls the source kind" .->37
    34-. "Makes a run per input" .->32
    35-. "Leases held sources<br/>[SQL]" .->43
    35-. "Opens the consumer" .->37
    35-. "Makes a run per message" .->32
    32-. "Inserts run, item and attempt rows; NOTIFY dirigent_work<br/>[SQL, JSONB, pg_notify]" .->43
    36-. "Claims queued notifications<br/>[SQL]" .->43
    36-. "Resolves the notifier" .->37
    37-. "Indexes contributions by id" .->38

  end

Flow - An ad hoc run

graph LR

  subgraph diagram ["Dynamic View: Dirigent"]

    subgraph 17 ["Dirigent"]

      19["API server<br/>[Container: FastAPI / Uvicorn (Python)]<br/>dg server. The REST API, the web UI bundle, SSE streams, and endpoint sources. Embeds the scheduler unless --no-scheduler."]
      27["Worker [1..*]<br/>[Container: asyncio (Python)]<br/>dg worker. Claims due attempts and calls blocks; polls and holds sources; sweeps leases and deadlines; delivers alerts. Routed by capability tags."]
      41["dg CLI<br/>[Container: Typer (Python)]<br/>Applies documents, starts and watches runs, and starts the server, worker and scheduler processes."]
      43[("Database<br/>[Container: PostgreSQL 17; SQLite under dg dev]<br/>Pipeline versions as JSONB documents; runs, items, attempts, leases and due times as indexed rows; logs; the worker registry.")]
      44[("Artifact storage<br/>[Container: file:// or s3:// (dirigent-storage-s3)]<br/>Step outputs too large to inline, and each run's scratch prefix. Never a worker-local path.")]
    end

    1["Pipeline author<br/>[Person]<br/>Writes pipeline documents in YAML or the builder, applies them, and starts and reads runs."]
    16["HTTP APIs<br/>[Software System]<br/>Any HTTP service an http.request step reaches, or that calls an endpoint source."]

    1-. "1. dg run CODE --watch" .->41
    41-. "2. POST /api/v1/pipelines/{code}/$run<br/>[HTTP/JSON (dirigent-client)]" .->19
    19-. "3. Insert run and attempt rows; NOTIFY dirigent_work on commit<br/>[SQL, JSONB]" .->43
    27-. "4. Wake and claim the queued attempt FOR UPDATE SKIP LOCKED<br/>[pg_notify]" .->43
    27-. "5. execute: submit the job, get a remote handle<br/>[HTTPS]" .->16
    27-. "6. Commit the handle; park as waiting with next_poll_at<br/>[pg_notify]" .->43
    27-. "7. probe when due, until terminal; then fetch<br/>[HTTPS]" .->16
    27-. "8. Write the output as an artifact<br/>[file:// or s3://]" .->44
    27-. "9. Settle, ready dependents, derive run status; NOTIFY dirigent_settled<br/>[pg_notify]" .->43
    41-. "10. GET the run's events (SSE) until it settles<br/>[HTTP/JSON (dirigent-client)]" .->19

  end

Flow - An endpoint source with a reply

graph LR

  subgraph diagram ["Dynamic View: Dirigent"]

    subgraph 17 ["Dirigent"]

      19["API server<br/>[Container: FastAPI / Uvicorn (Python)]<br/>dg server. The REST API, the web UI bundle, SSE streams, and endpoint sources. Embeds the scheduler unless --no-scheduler."]
      27["Worker [1..*]<br/>[Container: asyncio (Python)]<br/>dg worker. Claims due attempts and calls blocks; polls and holds sources; sweeps leases and deadlines; delivers alerts. Routed by capability tags."]
      43[("Database<br/>[Container: PostgreSQL 17; SQLite under dg dev]<br/>Pipeline versions as JSONB documents; runs, items, attempts, leases and due times as indexed rows; logs; the worker registry.")]
    end

    16["HTTP APIs<br/>[Software System]<br/>Any HTTP service an http.request step reaches, or that calls an endpoint source."]

    16-. "1. POST /endpoints/greet/Bergen with the source's token<br/>[HTTPS POST /endpoints/...]" .->19
    19-. "2. Check in order, record the input, create the run with the source settled<br/>[SQL, JSONB]" .->43
    27-. "3. Claim and run each step<br/>[pg_notify]" .->43
    27-. "4. Last prerequisite settles; the walk renders the reply; NOTIFY dirigent_settled<br/>[pg_notify]" .->43
    19-. "5. Reply waiter wakes and reads the rendered reply<br/>[SQL, JSONB]" .->43
    19-. "6. Answer the held caller with the reply's status, headers and body<br/>[HTTPS POST /endpoints/...]" .->16

  end

Flow - A polled source

graph LR

  subgraph diagram ["Dynamic View: Dirigent"]

    subgraph 17 ["Dirigent"]

      27["Worker [1..*]<br/>[Container: asyncio (Python)]<br/>dg worker. Claims due attempts and calls blocks; polls and holds sources; sweeps leases and deadlines; delivers alerts. Routed by capability tags."]
      43[("Database<br/>[Container: PostgreSQL 17; SQLite under dg dev]<br/>Pipeline versions as JSONB documents; runs, items, attempts, leases and due times as indexed rows; logs; the worker registry.")]
    end

    13["S3-compatible storage<br/>[Software System]<br/>Buckets the storage blocks and storage sources read and write. AWS S3, RustFS, MinIO."]

    27-. "1. Lease the due source and commit before any I/O<br/>[pg_notify]" .->43
    27-. "2. List the prefix; objects not in the cursor are new<br/>[S3 API]" .->13
    27-. "3. Under the pipeline lock: one run per object, store the cursor, next poll one cadence later<br/>[pg_notify]" .->43
    27-. "4. Any worker claims the new runs' attempts<br/>[pg_notify]" .->43

  end

Deployment - Docker Compose

graph LR

  subgraph diagram ["Deployment View: Dirigent - Docker Compose"]

    subgraph 150 ["Docker host"]

      subgraph 151 ["postgres"]

        152[("Database<br/>[Container: PostgreSQL 17; SQLite under dg dev]<br/>Pipeline versions as JSONB documents; runs, items, attempts, leases and due times as indexed rows; logs; the worker registry.")]
      end

      subgraph 153 ["s3"]

        154[("Artifact storage<br/>[Container: file:// or s3:// (dirigent-storage-s3)]<br/>Step outputs too large to inline, and each run's scratch prefix. Never a worker-local path.")]
      end

      subgraph 155 ["migrate"]

        156["dg CLI<br/>[Container: Typer (Python)]<br/>Applies documents, starts and watches runs, and starts the server, worker and scheduler processes."]
      end

      subgraph 158 ["server"]

        159["API server<br/>[Container: FastAPI / Uvicorn (Python)]<br/>dg server. The REST API, the web UI bundle, SSE streams, and endpoint sources. Embeds the scheduler unless --no-scheduler."]
        163["Scheduler<br/>[Container: asyncio (Python)]<br/>dg scheduler, or embedded in dg server. Turns due schedules into run rows. Time, and only time."]
      end

      subgraph 165 ["worker"]

        166["Worker [1..*]<br/>[Container: asyncio (Python)]<br/>dg worker. Claims due attempts and calls blocks; polls and holds sources; sweeps leases and deadlines; delivers alerts. Routed by capability tags."]
      end

      subgraph 169 ["docker"]

        170["Docker daemon<br/>[Infrastructure Node: TLS on tcp://docker:2376]<br/>Runs what docker.*, compose and build steps start."]
      end

    end

    156-. "Migrates the schema, ensures connections<br/>[SQL]" .->152
    159-. "Reads and writes definitions; creates ad hoc runs<br/>[SQL, JSONB]" .->152
    159-. "Streams artifacts<br/>[file:// or s3://]" .->154
    156-. "Applies, runs, cancels, retries<br/>[HTTP/JSON (dirigent-client)]" .->159
    163-. "Holds the leader lock; claims due schedules and inserts their runs<br/>[pg_advisory_lock, FOR UPDATE SKIP LOCKED]" .->152
    166-. "LISTEN dirigent_work<br/>[pg_notify]" .->152
    166-. "Writes and reads outputs<br/>[file:// or s3://]" .->154

  end

Deployment - dg dev

graph LR

  subgraph diagram ["Deployment View: Dirigent - dg dev"]

    subgraph 172 ["Developer machine"]

      subgraph 173 ["dg dev"]

        174["API server<br/>[Container: FastAPI / Uvicorn (Python)]<br/>dg server. The REST API, the web UI bundle, SSE streams, and endpoint sources. Embeds the scheduler unless --no-scheduler."]
        175["Scheduler<br/>[Container: asyncio (Python)]<br/>dg scheduler, or embedded in dg server. Turns due schedules into run rows. Time, and only time."]
        176["Worker [1..*]<br/>[Container: asyncio (Python)]<br/>dg worker. Claims due attempts and calls blocks; polls and holds sources; sweeps leases and deadlines; delivers alerts. Routed by capability tags."]
      end

      subgraph 177 [".dirigent/state"]

        178[("Database<br/>[Container: PostgreSQL 17; SQLite under dg dev]<br/>Pipeline versions as JSONB documents; runs, items, attempts, leases and due times as indexed rows; logs; the worker registry.")]
        182[("Artifact storage<br/>[Container: file:// or s3:// (dirigent-storage-s3)]<br/>Step outputs too large to inline, and each run's scratch prefix. Never a worker-local path.")]
      end

    end

    174-. "Reads and writes definitions; creates ad hoc runs<br/>[SQL, JSONB]" .->178
    175-. "Holds the leader lock; claims due schedules and inserts their runs<br/>[pg_advisory_lock, FOR UPDATE SKIP LOCKED]" .->178
    176-. "LISTEN dirigent_work<br/>[pg_notify]" .->178
    174-. "Streams artifacts<br/>[file:// or s3://]" .->182
    176-. "Writes and reads outputs<br/>[file:// or s3://]" .->182

  end