concept · 09

Coordinated agents

Run more than one agent on the same repo without them clobbering each other. The kernel owns the shared state, enforces version checks, and locks the files each step will write.

The kernel owns the context, not the model

Workflow state lives in a shared store the kernel owns — the coordination state about the repo, sitting alongside the working tree rather than inside any one agent’s head. Each agent receives only the slice relevant to its current step. The shared truth is in one place, which is what makes running more than one agent on the same repo tractable at all.

No agent acts on a stale read

Agent B won’t silently overwrite agent A’s fix. Every read returns the workflow version, and a write must echo it back as expectedVersion. If another agent moved the state in between, the write is rejected with STALE_WORKFLOW_VERSION and the fresh version comes back — so the agent re-reads and retries instead of clobbering work it never saw. Optimistic concurrency, enforced by the kernel.

← { "error": { "code": "STALE_WORKFLOW_VERSION",
      "message": "expected version 7, current is 9" },
    "workflow": { "version": 9 } }   // re-read, then retry

Two agents can’t hold the same files at once

A transition declares the files it will write with owned_files. Before it runs, the kernel takes a global lock on them — across every workflow running against the repo — and releases it when the step finishes. If another agent already holds one of those files, this one doesn’t fail and doesn’t stomp: it durably suspends with status waiting_on_lock and auto-resumes the moment the files free, in FIFO order — even across a restart. A dead holder’s lock is reaped on a TTL, so nothing deadlocks.

editing_auth:
  transitions:
    apply_patch:
      target: verifying
      executor:
        kind: agent
        owned_files: ["src/auth.rs", "src/session.rs"]   # locked globally for this step

Run the independent work in parallel

Once the work is partitioned into non-overlapping pieces, fan it out. The parallel executor runs N branches concurrently and aggregates them under a join condition — all, any, or at_least: K.

executor:
  kind: parallel
  branches:
    - { kind: script, subject: lint.check }
    - { kind: script, subject: test.unit }
    - { kind: script, subject: audit.deps }
  join: all
  max_concurrency: 4
← All concepts