Separate work definition from execution so a runner can tell what is ready now,
what is blocked, and what can happen next.
What you'll build
A tiny DAG runner with durable task state.
This lab gives you a small task graph stored in JSON and a Python script that
reads it, checks dependencies, and tells you which tasks are ready. In plain
English, it answers the boring but essential orchestration question: what can
run right now without breaking the order of the work?
Under the hood, that is DAG execution in miniature. The graph says which tasks
depend on which other tasks, and the runner only advances work when every
upstream dependency is already done. That same pattern shows up in build
systems, data pipelines, CI jobs, and multi-step agent workflows.
Run it
cd ai_ecosystem_labs
python3 07-task-graph/task_graph.py ready
python3 07-task-graph/task_graph.py done add-hook
Starting here? Quick setup
git clone https://github.com/BanditF/ai_ecosystem_labs
cd ai_ecosystem_labs
python3 07-task-graph/task_graph.py ready
Requires Python 3.8+. No extra packages needed.
Time guide. Setup: ~2 min. Working through it: 20–35 min, especially if you pause to inspect the saved task state.
Why this piece exists
Coordination gets easier once the graph is explicit.
If you keep task order in your head, or bury it inside one long script, the
system cannot help you much. It cannot tell you what is blocked, cannot resume
cleanly after a restart, and cannot hand work to another process without a lot
of custom logic. A task graph fixes that by making dependencies part of the data.
A real-world analog is a pipeline orchestrator like Airflow or Dagster, or even
a CI workflow that refuses to run deployment before tests pass. This lab is a
much smaller version of the same idea: write the dependency graph down, then let
the runner decide what is ready instead of guessing.
The code
task_graph.py
Walk through it
Four things worth noticing.
ready_tasks() is dependency filtering, not full ordering
The key function loops through every pending task and only returns it if all
of its dependencies already have status done. A full
orchestrator would also validate the graph for cycles and produce a
complete topological order. This toy runner asks only: which tasks are
ready to run right now?
The task graph lives in data, not hard-coded branches
tasks.json defines the work, the dependency edges, and the
current status. The Python file just loads, checks, and updates that graph.
That separation matters because a coordinator can change the plan by editing
data instead of rewriting the runner itself.
Status behaves like a tiny state machine
Even in this stripped-down version, each task moves through recognizable
states: pending until dependencies clear, then done once the runner marks it
complete. In a fuller orchestrator you would usually insert running
between those two states, checkpoint the graph, and resume later from the
saved file.
DAG rules are what prevent deadlock
The graph only works cleanly if dependencies stay acyclic. If task B depends
on task A, task A cannot also depend on task B. Once you introduce a cycle,
nothing can become ready, because every task in the loop is waiting on some
other task in the same loop to finish first.
After that update, re-running the ready check would surface
agent-loop. That is the whole orchestration pattern in miniature:
finish upstream work, then unlock the next node in the graph.
Try this
Three things to try before moving on.
Add another task to tasks.json.
Create a new task that depends on an existing one, then run the ready command
again. It should stay hidden until its dependency is marked done.
Manually edit a task status.
Flip one of the upstream tasks to done in tasks.json,
save the file, and re-run the script. Watch which downstream task becomes ready.
That is dependency propagation, just without a scheduler wrapped around it yet.
Create a cycle on purpose.
Make task A depend on task B and task B depend on task A, then run the ready
check. Notice how nothing new becomes runnable. That is why orchestration
systems insist on DAGs instead of arbitrary graphs.
Concepts behind this
Agents matter here because multi-step agents
often need this exact shape: represent work as nodes, check dependencies,
and only advance when prerequisites are complete.
The next lab, Lab 08, builds on the same
idea by adding a queue and worker coordination around tasks that are ready.