Represent a plan as obligations and dependencies
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
- Translate a goal into verifiable steps and completion criteria.
- Distinguish plan syntax from feasible execution.
- Design structured prompts for observable artifacts.
A plan is a claim about future work
A useful plan says what will be done, what each step needs, and what observation will establish completion. A list of confident verbs is insufficient. For an agent investigating a failed data pipeline, inspect, fix, verify omits the evidence source, affected environment, required permissions, and success condition. The plan should expose those obligations so the runtime can reject impossible or unauthorized work before dispatch.
Represent a step with an ID, an action category, dependencies, required inputs, expected artifact, and verification condition. Add a status controlled by the runtime. The model may propose a step, but a successful-looking sentence must not set its status to complete. Completion should follow an observed artifact or explicit result. This keeps the public plan useful without requesting or revealing hidden model chain-of-thought.
Dependencies encode what can run now
Consider four steps: inspect the failure log, inspect the current configuration, propose a patch using both findings, and test the patch. The first two can run independently. The proposal depends on both, and testing depends on the proposal. A directed acyclic graph expresses this relationship more precisely than numbered prose. A dependency points from a prerequisite to the step that consumes its result.
If log inspection takes two minutes and configuration inspection takes three, parallel completion can make the proposal ready after three minutes rather than five, assuming resources permit. Dependencies describe logical readiness; resource limits describe operational readiness. A scheduler must satisfy both. A step with a missing input is not ready merely because a worker is idle, and parallel execution must not introduce conflicting mutations.
Structure narrows ambiguity, not truth
A structured prompt can request a JSON object with goal, steps, assumptions, and stop_conditions, plus a schema for each step. State the available tools, prohibited operations, budget, and known evidence outside untrusted task data. Provide one compact example of the desired artifact when it resolves ambiguity. Then validate the output rather than relying on the prompt to enforce the contract.
JSON validity proves only that the result parses. Schema validity proves only that required fields and types fit. Semantic validation checks duplicate IDs, missing dependencies, cycles, impossible prerequisites, and unsupported tools. Domain validation asks whether the proposed artifacts would actually establish the goal. These layers can reject different plans, so preserve the specific reason instead of returning a generic request to try harder.
A worked semantic check
Suppose the plan contains A: fetch logs, B: propose patch after A and C, and C: test after B. All fields can be syntactically valid, yet B and C form a dependency cycle. Neither can start. A topological validation pass repeatedly removes nodes whose prerequisites are already satisfied; if nodes remain and none are ready, the plan contains a cycle or an unresolved dependency.
Separate those faults. A missing dependency refers to an absent node and is usually a construction error. A cycle can reflect an unmodeled iterative process. Repair the latter by making iteration explicit: propose a candidate, test that candidate, and create a bounded revision step if the test fails. A loop needs state and a stopping rule rather than contradictory static prerequisites.
Plans should change when evidence changes
Freeze identifiers for completed artifacts, but permit remaining steps to be revised when new evidence invalidates an assumption. Record the revision reason as a concise observable statement, such as configuration differs from the incident snapshot. Replanning every turn wastes effort; refusing to replan preserves obsolete intentions. Trigger revision when a prerequisite fails, a required fact changes, or the remaining budget no longer supports the plan.
The code finds ready tasks and applies a deterministic cost ordering to one small budget. It is a scheduling demonstration, not an optimal planner and not a language-model call. The lab adds validation for missing nodes and cycles. A strong portfolio explanation should show a rejected invalid plan and an evidence-driven revision, because those cases reveal more about the architecture than a polished plan that never encounters trouble.
Work through the code
The fixture contains a dependency graph with two initially ready tasks. A budget of four selects the cheaper one; once both prerequisites are complete, patch becomes ready. This greedy policy maximizes neither total utility nor workflow speed in general.
steps = [
{"id": "logs", "deps": [], "cost": 2},
{"id": "config", "deps": [], "cost": 3},
{"id": "patch", "deps": ["logs", "config"], "cost": 4},
]
def choose_ready(steps, completed, budget):
ready = [step for step in steps if step["id"] not in completed
and set(step["deps"]) <= completed]
chosen = []
for step in sorted(ready, key=lambda item: (item["cost"], item["id"])):
if step["cost"] <= budget:
chosen.append(step["id"])
budget -= step["cost"]
return chosen
print(choose_ready(steps, set(), 4))
print(choose_ready(steps, {"logs", "config"}, 4))
['logs'] ['patch']
Run Python snippets locally with the prerequisites named above. The module coding lab runs directly in your browser.
Pause and reason
A plan has A with no prerequisites, B depending on A and C, and C depending on B. Explain why a valid JSON schema cannot establish executability and repair the loop.
Check your understanding
Which evidence should mark a test step complete?
Your notes
Explain the mechanism in your own words. Add a failure you want to test.