2026-08-29 · Updated 2026-08-29 · 12 min read

Reusable agent-task dependency examples and diagrams

A copyable library of five agent-task dependency shapes — chain, fan-out, fan-in, diamond, and a cross-project hand-off held open by a forward reference — each drawn as a diagram, declared with the exact yylo-ledger commands, and proven by a recorded 2026-08-29 run: what ready admits at each stage, what the priority scores rank, and how wide each shape may safely run.

By Juno AI INC · yylo-ledger · dependencies

An architect staring at a whiteboard does not need another argument for dependency graphs; they need the shapes. Which structures recur on real agent boards, how each is declared in commands you can paste, what the readiness answer does as the work lands, and how much of the graph may run at once without lying about the edges. This page is that library: five named dependency patterns, each drawn as a diagram, each declared with the exact CLI forms, each executed against the released tool with the transcripts recorded below. Copy the shape that matches your work, adjust the task titles, and the semantics arrive with it.

Provenance first, because a pattern library stands or falls with its drills. Every pattern command and quoted output on this page ran on 2026-08-29 against yylo-ledger 0.2.0, the release version that the generated facts on this site record, driven module-direct in sandbox boards made for these drills; the one fence shown in generalized form is named where it appears. Task IDs are the ones the recorded boards minted; rerun the declarations and you will mint your own. What transfers is the structure and the behavior, both of which the transcripts pin to real state changes. The semantics underneath the shapes — what one edge means, when a blocker counts as resolved, why cycles are refused at the write — are established ground belonging to the dependency-graph design guide; this library stands on those contracts and adds only the reusable forms. The pattern identifiers DEP-1 through DEP-5 are permanent: version 1 names each shape once, and later versions will add or retire shapes without renumbering.

One declaration rule, five shapes

Every pattern below is built from the same declaration move, applied on the dependent: name the blockers when the task is born, or edit them later through the dedicated mutation commands. The forms, all exercised in the recorded runs:

sh
yylo-ledger create "ship the release" --blocked-by L5lT46,OLtyi5,gWbAK7
yylo-ledger create "harden the parser tests [blocked_by]Iv6bDs[/blocked_by]"
yylo-ledger deps add --id 5YzANg --blocked-by 84GmFS
yylo-ledger deps remove --id 5YzANg --blocked-by 84GmFS

The first form takes a comma- or space-separated list at creation; the second carries the edge inside the task body, parsed on write — the recorded run stored blocked_by: ["Iv6bDs"] from exactly that body; the third and fourth mutate an existing task's edges, and the recorded deps add returned the task with its new blocked_by while deps remove returned it empty. Reading a graph back is one command per question — ready for what may start, deps TASK_ID for one task's verdict, order --scores for the whole board's ranking. Transcripts below quote the recorded runs; table rows are verbatim with column spacing compressed to fit the page, and long JSON verdicts are condensed to the fields that changed. The five shapes:

text
DEP-1 chain            A ──> B ──> C
                         one lane, start to finish

DEP-2 fan-out                  ┌──> I1
                       R ──┤──> I2        one gate, then a wave
                               └──> I3

DEP-3 fan-in           B1 ──┐
                       B2 ──┼──> S        wide entry, one exit
                       B3 ──┘

DEP-4 diamond                  ┌──> M1 ──┐
                       D ──┤           ├──> F
                               └──> M2 ──┘

DEP-5 cross-project    UP (other board) ──> DN   edge held open until
                                                   the blocker lands

DEP-1: the chain

The baseline shape: each task consumes the last one's output, so exactly one task is admissible at any moment. Use it when the hand-off is real — a schema must exist before a migration reads it, a migration must land before release notes describe it.

text
[2rH2JC] define the schema
    │
[n1DuEY] migrate the data
    │
[84GmFS] publish the release notes

Declared as three creates, each naming its predecessor:

sh
yylo-ledger create "define the schema"
yylo-ledger create "migrate the data" --blocked-by 2rH2JC
yylo-ledger create "publish the release notes" --blocked-by n1DuEY

The recorded run behaved as the drawing promises. ready listed 2rH2JC alone; order --scores ranked the board 2, 1, 0 down the chain — every task's score is the count of work waiting behind it, so the head of a chain always outranks its tail. After the schema was marked done, ready listed n1DuEY alone; after the migration landed, 84GmFS alone:

text
$ yylo-ledger ready -f table                    # at declaration
2rH2JC   backlog   define the schema
$ yylo-ledger ready -f table                    # after 2rH2JC done
n1DuEY   backlog   migrate the data              2rH2JC
$ yylo-ledger ready -f table                    # after n1DuEY done
84GmFS   backlog   publish the release notes    n1DuEY

Parallel semantics: none, and that is the point. A chain is the honest drawing only when each step truly needs the last; if two steps could overlap, the chain is an accidental serialization and DEP-2 or DEP-4 is the truer shape.

DEP-2: the fan-out

One root gates several independent dependents, and the root's completion releases all of them in the same instant. Use it when one decision unblocks a perimeter of work — an API cut once, then client SDK, server adapter, and migration guide each built against it.

text
                    ┌──> [f6AVhI] client SDK against the API
[1vk61H] cut ───────┼──> [6IgqKV] server adapter against the API
  the stable API    └──> [fCAA32] migration guide for the API
sh
yylo-ledger create "cut the stable API"
yylo-ledger create "client SDK against the API" --blocked-by 1vk61H
yylo-ledger create "server adapter against the API" --blocked-by 1vk61H
yylo-ledger create "migration guide for the API" --blocked-by 1vk61H

Before the root landed, ready offered 1vk61H alone and order --scores read 3 for the root and 0 for each dependent — the whole board's downstream work sat behind one task. The recorded release moment, root marked done:

text
$ yylo-ledger ready -f table
ID       Status  Body                              Tags  Related  Blocked By
fCAA32   backlog migration guide for the API                    1vk61H
6IgqKV   backlog server adapter against the API                 1vk61H
f6AVhI   backlog client SDK against the API                     1vk61H

Three tasks, one query, zero recomputation. Parallel semantics: the root is the serialization point and the only one; after it lands, the wave is as wide as your slot budget — every dependent is independently admissible, and capping the concurrent launches is execution discipline, not graph structure. Run the root ahead of unrelated leaf work when slots contend; the score ranking made exactly that call on the recorded board at declaration time, and the wave is why.

DEP-3: the fan-in

The mirror of DEP-2: several independent blockers converge on one dependent, and the dependent waits for the last of them. Use it for release gates — backend sign-off, security review, load evidence — where every blocker is genuinely separate work and the ship task may not start until all three stand.

text
[L5lT46] backend sign-off ───┐
[OLtyi5] security review ────┼──> [UveE9K] ship the release
[gWbAK7] load test evidence ─┘
sh
yylo-ledger create "backend sign-off"
yylo-ledger create "security review"
yylo-ledger create "load test evidence"
yylo-ledger create "ship the release" --blocked-by L5lT46,OLtyi5,gWbAK7

The recorded progression, condensed from the run to the verdict fields, is the whole contract of this shape:

text
$ yylo-ledger deps UveE9K      unmet: L5lT46 backlog, OLtyi5 backlog, gWbAK7 backlog
$ yylo-ledger mark done --id L5lT46 --response "backend signed off"
$ yylo-ledger deps UveE9K      unmet: OLtyi5 backlog, gWbAK7 backlog   met: L5lT46 done
$ yylo-ledger mark done --id OLtyi5 --response "security review passed"
$ yylo-ledger deps UveE9K      unmet: gWbAK7 backlog                    met: L5lT46, OLtyi5
$ yylo-ledger mark done --id gWbAK7 --response "load evidence recorded"
$ yylo-ledger deps UveE9K      is_blocked: false   met: L5lT46, OLtyi5, gWbAK7 all done
$ yylo-ledger ready -f table   UveE9K   backlog   ship the release

Two behaviors earned their place in the record. The join moved exactly one blocker at a time from unmet to met and released the dependent on the third, with no partial readiness at any stage — two of three done left is_blocked as true as zero of three. And ready throughout offered the three blockers themselves, never the ship task, until the moment the last one landed. Parallel semantics: everything above the join is independent work — run the blockers concurrently, because the dependent releases on the latest of them and a sequenced pair merely donates its second slot to waiting.

DEP-4: the diamond

The composition the first three point at: a fan-out whose branches re-converge. One design task, two implementation paths built from it, one ship task gated on both. It is the shape a feature takes when one design fans into independent paths that must land together — and the drawing error to guard against is the forgotten re-convergence.

text
                          ┌──> [eZee1N] implement the client path ──┐
[VzkN4J] design the ──────┤                                         ├──> [tufIO5] ship the feature
       interface          └──> [FJM7qW] implement the service path ─┘
sh
yylo-ledger create "design the interface"
yylo-ledger create "implement the client path" --blocked-by VzkN4J
yylo-ledger create "implement the service path" --blocked-by VzkN4J
yylo-ledger create "ship the feature" --blocked-by eZee1N,FJM7qW

The recorded run traced the three-wave rhythm. ready offered the design alone; order --scores read 3 for the design, 1 for both implementers, 0 for the ship task — the ranking draws the diamond's waistline by itself. Design done: both implementers appeared together. First implementer done: ready offered the second alone, the ship task still excluded with one unmet blocker. Second implementer done: the ship task alone:

text
$ yylo-ledger ready -f table                    # at declaration
VzkN4J   backlog   design the interface
$ yylo-ledger ready -f table                    # after VzkN4J done
FJM7qW   backlog   implement the service path   VzkN4J
eZee1N   backlog   implement the client path    VzkN4J
$ yylo-ledger ready -f table                    # after eZee1N done
FJM7qW   backlog   implement the service path   VzkN4J
$ yylo-ledger ready -f table                    # after FJM7qW done
tufIO5   backlog   ship the feature             eZee1N, FJM7...

Parallel semantics: one lane, then two, then one. The diamond is also the shape to reach for when a third or fourth implementer joins — the declaration grows one line, the ship task's blocker list grows one ID, and the release rule does not change: the widest wave is the middle, and the join at the far side is the same all-of behavior DEP-3 demonstrated.

DEP-5: the cross-project hand-off

The one shape whose blocker starts life on a different board. A consumer team's task depends on a producer team's task, but boards are per-project, and no live link spans them. The pattern: declare the edge anyway, as a forward reference to the producer's task ID, and let the consumer's dependent wait until the blocker physically arrives on the consumer board through a sealed merge.

text
producer board                             consumer board
┌────────────────────────────┐            ┌────────────────────────────────────────┐
│ [2D8lCE] ship the pricing  │  sealed    │ [H4iYtM] integrate the pricing API     │
│         API                │  merge ──> │   blocked_by 2D8lCE (forward reference│
│                            │            │   — does not exist on this board yet) │
└────────────────────────────┘            └────────────────────────────────────────┘

The declaration, run on the consumer board, produced a warning worth reading as a contract:

text
$ yylo-ledger create "integrate the pricing API" --blocked-by 2D8lCE
Warning: 2D8lCE wasn't found on the kanban (stored as forward reference).

The edge was stored, and the dependent was held out of ready — the consumer board answered No ready tasks found — while deps reported the blocker in a state no on-board task can have:

text
$ yylo-ledger deps H4iYtM
"is_blocked": true, "unmet_blockers": [{ "id": "2D8lCE", "status": "unknown" }]

unknown is the marker of a promise rather than a task: the ID matches the ledger's format but no record on this board carries it, so the reference waits instead of guessing. The landing is the sealed two-step merge — preview a plan, review it, apply exactly that plan with a receipt. This fence is the one shown in generalized form: the paths are placeholders, and the recorded run invoked the same two steps against its sandbox's real directories:

sh
yylo-ledger merge /path/to/producer/.juno_task --into .juno_task \
  --dry-run --plan-file /tmp/dependency-landing-plan.json
yylo-ledger merge /path/to/producer/.juno_task --into .juno_task \
  --apply-plan /tmp/dependency-landing-plan.json --receipt-file /tmp/dependency-landing-receipt.json

The recorded apply added the producer task (New tasks added: 1, plan digest 5e6f4b14…c11096ba, receipt digest eca21d5b…ff9ad8a6, the receipt naming the added ID with before and after content hashes), and the graph's answer changed shape on the spot: deps H4iYtM now reported the blocker as 2D8lCE backlog — a real task with a real status — and ready offered the landed producer task itself as admissible work on the consumer board. Marking 2D8lCE done moved the dependent through the same gate every other shape uses: is_blocked: false, then ready offering H4iYtM. The hand-off is complete when the cross-board edge has become an ordinary on-board edge, resolved by ordinary state.

Two boundaries keep this pattern honest. The edge never resolves across live boards — it resolves when the blocker's record lands on the dependent's board, so the merge cadence is part of the design, not an implementation detail. And driving commands at the producer board from the consumer's shell is a separate contract — an explicit alias, an opt-in policy, refusal before any fallback — owned by the cross-project routing guide; this pattern needs only its discipline, not its machinery.

What the shapes promise a dispatcher

Each pattern's value is that its readiness behavior is predictable at declaration time. Compressed from the five recorded runs:

  • DEP-1 chain: exactly one ready task at every stage; scores descend down the line; dispatch is a queue of one.
  • DEP-2 fan-out: one ready root, then a simultaneous wave — the moment width stops being a graph property and becomes a slot decision.
  • DEP-3 fan-in: blockers ready together, dependent absent until the last lands; the wave's width lives above the join.
  • DEP-4 diamond: one-two-one rhythm; the middle wave is the parallel section, and both its lanes gate the same exit.
  • DEP-5 cross-project: the dependent invisible to ready on the consumer board until the landing; after it, the pattern decays into whichever on-board shape the landed work carries.

The scores are a declaration-time instrument — they rank the whole open board before any of it flies, which is when a wave plan is written. Choosing which ready tasks to admit when slots are scarce is a selection discipline with its own contract in the dependency-ready selection guide, and the launch side — pool caps, worker isolation, run artifacts — is the parallel execution playbook's ground. The shapes above end where those two begin: at the moment a ready answer has to become running work.

Cite this library

The patterns are the citable unit. Version 1 comprises DEP-1 through DEP-5 as defined, drawn, and drilled on this page; the citation block:

text
Agent-task dependency patterns, version 1 (DEP-1 through DEP-5)
https://yylo.dev/guides/agent-task-dependency-examples
YYLO, sandbox drills against yylo-ledger 0.2.0, evidence dated 2026-08-29

Reuse terms: copy the declarations, the diagrams, and the shape names into your own boards and documents, with attribution to the URL above. Stability terms: the identifiers are permanent, shapes are never renumbered, and a future version that adds or retires a shape will say so on this page with a new evidence date — the recorded drills behind version 1 remain true of the release they named. No search-demand estimate underwrites this library; the approved route matrix records zero corpus rows for it, and its value rests on the evidence and the reuse, nothing else. For the command surface beyond these patterns, start from the YYLO Ledger documentation, which links the repository behind the CLI.