Turn collaboration into a dependency graph
How to study this lesson
Read one section, trace the worked example, and try the knowledge check. Bookmark saves a shortcut; notes appear in My notebook. Mark lesson complete is your own assessment and does not mark its lab passed.
By the end, you can
- Specify agent work as contracts with explicit dependencies.
- Calculate critical paths and available parallelism.
- Recognize tasks that should stay inside one agent.
Start with artifacts, not job titles
A useful multiagent design starts by naming the artifacts a task needs. For a release assessment, those might be a change inventory, a compatibility report, a risk table, and a final recommendation. Calling three agents researcher, critic, and manager leaves their interfaces ambiguous. Instead, specify the input snapshot, output schema, permitted tools, completion condition, and evidence requirements for each assignment. A compatibility worker might consume an immutable API diff and produce rows containing affected symbol, supported version, test evidence, and unresolved uncertainty.
This makes collaboration inspectable. The coordinator can reject an incomplete artifact without judging whether the worker sounded confident. It also exposes false independence: if the risk table requires compatibility results, those tasks cannot run concurrently merely because different agents own them. A dependency is an information requirement, not an organizational preference.
Read a DAG as a scheduling constraint
Represent each task as a node and each prerequisite as an incoming edge. A directed acyclic graph, or DAG, describes work with no circular prerequisite chain. Suppose inventory takes two minutes, compatibility takes five after inventory, security takes four after inventory, and synthesis takes two after both analyses. Sequential execution takes thirteen minutes. With enough workers, the earliest finish is nine: two for inventory, five for the slower analysis, then two for synthesis. The security branch has one minute of slack.
These are planning estimates, not measured model benchmarks. Real latency includes queueing, tool delays, retries, and coordination. Python's TopologicalSorter accepts predecessors and exposes ready nodes; it does not allocate workers or estimate duration. The example below calculates earliest finish times separately, making the scheduling assumption explicit. [Python graphlib documentation](https://docs.python.org/3/library/graphlib.html).
Choose dependencies that preserve meaning
Excess edges reduce parallelism, while missing edges produce incorrect work. Consider a documentation worker and a test worker that both read the same frozen interface specification. They can proceed independently. If the documentation worker instead reads the test worker's evolving patch, its output depends on an unstable artifact and may describe a version that never ships. Freeze a shared input or introduce a dependency on a reviewed patch, then record its content hash in the downstream assignment.
A DAG is most helpful when tasks have bounded interfaces. Exploratory dialogue may legitimately revisit earlier assumptions. Model that as a new iteration with a new graph or an explicit bounded loop outside the DAG. Do not hide a circular dependency by dropping an edge until the sorter accepts it; you have changed the meaning of the work rather than resolved the cycle.
Schedule under scarce resources
Ready does not mean running. A service may allow only two simultaneous browser sessions or one repository writer. Add resource requirements to tasks and let the scheduler choose among ready nodes. Critical path priority can improve completion time, but repeatedly preferring long jobs may delay small interactive requests. Tenant quotas and deadlines are separate scheduling objectives that should be stated rather than buried in an arbitrary alphabetical order.
In the worked graph, two analysis workers realize the nine minute estimate. One worker still needs thirteen minutes because the five and four minute analyses cannot overlap. Adding a fourth worker provides no further benefit for this graph. That observation is a useful budget defense: worker count should follow available independent work. It also helps diagnose slow runs before blaming an individual model or increasing concurrency globally.
Know when one agent is the better design
A task with a long sequential reasoning chain can lose coherence when split across workers. Each handoff requires context selection, serialization, and verification. A single agent that can inspect a small codebase, make one localized edit, and run one check may be simpler and faster than a committee. Specialization earns its cost when workers need different tools, substantially different evidence, or independent analyses that can be evaluated separately.
Evaluate this choice using the same cases and outcome rubric. Compare task completion, correctness of artifacts, elapsed time, total tokens, and integration corrections. A multiagent run that finishes earlier but leaves contradictory assumptions is not an automatic improvement. Keep a one-agent baseline and require the graph to explain its advantage. The graph is an executable hypothesis about where independence exists, not proof that more agents make the task easier.
Work through the code
This deterministic teaching simulation uses invented minute estimates and unlimited workers. It calculates earliest finishes for a DAG; it is not a multiagent runtime. Change a duration or edge and compare total work with critical path length.
from graphlib import TopologicalSorter
graph = {
'inventory': (),
'compatibility': ('inventory',),
'security': ('inventory',),
'synthesis': ('compatibility', 'security'),
}
duration = {
'inventory': 2,
'compatibility': 5,
'security': 4,
'synthesis': 2,
}
finish = {}
for task in TopologicalSorter(graph).static_order():
start = max((finish[p] for p in graph[task]), default=0)
finish[task] = start + duration[task]
print(f'{task}: {start}->{finish[task]}')
print('sequential:', sum(duration.values()))
print('unlimited workers:', max(finish.values()))
inventory: 0->2 compatibility: 2->7 security: 2->6 synthesis: 7->9 sequential: 13 unlimited workers: 9
Run Python snippets locally with the prerequisites named above. The module coding lab runs directly in your browser.
Pause and reason
Security grows to eight minutes. What are the earliest completion time and compatibility slack with unlimited workers?
Check your understanding
Two workers independently write the same mutable configuration file. What should the coordinator change first?
Your notes
Explain the mechanism in your own words. Add a failure you want to test.