CONCEPT · 45 minutes
Learn how to build a practical planning system for agentic workflows by asking a model to generate a step plan, storing it in shared context, and executing steps sequentially.
When I first built the task-orchestration layer of my Python orchestration framework, I did what felt natural: I handed each step to the model with just enough context for that step to make sense on its own. Step 1 would research the problem. Step 2 would draft a solution. Step 3 would write the final report.
The model was capable. Each step produced reasonable output. But the final report contradicted the draft, which contradicted the research. The three steps were navigating by dead reckoning — each one started from a different internal map of the task.
The fix was not a smarter model or a more elaborate prompt. It was a shared plan.
Think of a plan like a shared map before a hiking group sets out. Everyone studies the same route, the same checkpoints, and the same notes about terrain. Without the map, three hikers take three different paths and end up at three different summits. With it, each hiker builds on what the previous one scouted. A plan is a shared map — without it, each step navigates by dead reckoning.
In the task-orchestration agent I run on my Mac Mini for client work, every task now starts with a planning call: the model reads the task spec and returns a numbered list of steps. That list goes into a shared context dictionary. Every subsequent step reads it. The contradiction problem disappeared entirely.
Key insight: A planning call costs one extra API round-trip and buys coherence across every subsequent step. That trade-off is almost always worth making.
The planning call is simple. I ask the model to break a task into numbered steps and return each step on its own line. That is the entire planning system.
Here is the first runnable block — copy it, set ANTHROPIC_API_KEY, and run it:
Running this returns something like:
The model reasons about the task and produces a sequenced plan. That is the planning system. No STRIPS formulas. No A* search. No hierarchical task networks. Just a model, a clear prompt, and a numbered list of steps.
Common pitfall: Asking for a plan and immediately discarding its structure. If you parse the plan into a list and store it, every later step can reference it. If you only print it and move on, you have thrown away the shared map before the hike even starts.
The plan arrives as free text. The next step is to parse it into a Python list so each step is addressable by index, then store everything in a context dictionary that travels with the task for its entire lifetime.
Once parsed, the steps go into a context dictionary alongside everything else the task needs:
This dictionary is the single source of truth for the entire task run. Every step reads from it before acting and writes its completion record back into it afterward. No step ever starts from a blank slate.
Before reading on, consider this: what would happen if you skipped the shared context and passed only the current step description to the model at each call?
The model would produce output that is locally reasonable but globally incoherent. Step 3 might undo what step 2 set up because step 3 never saw it. This is exactly the failure mode I described at the start — each step navigating by dead reckoning from its own internal map.
The context dictionary is what makes the plan a shared map, not just a list of suggestions that each step can silently ignore.
Each step gets the full context: the original task, the ordered plan, and a summary of every step that has already completed. The model cannot accidentally undo previous work because it always sees what has been accomplished.
After each step, record its completion before advancing:
The full planning loop assembles all of these pieces:
This is the complete planning system I run in the SDLC harness on my Mac Mini. It is not STRIPS. It is not A*. It is a model that generates a plan, a parser that structures it, and a loop that executes steps sequentially while keeping every step informed about the ones before it.
What this buys you: Each step sees the full completion record. The model cannot make a decision that contradicts earlier work because it always knows what has already been done. Coherence is structural, not coincidental.
What would happen if you ran these steps in parallel instead of sequentially?
Step 3 — "Apply the updated Kubernetes manifest" — depends on step 2 having built and pushed the Docker image. Running both at the same time would mean step 3 applies a manifest that points to an image which does not exist yet. The deployment would fail.
This is the deeper reason why the planning system and the linear execution model belong together. The plan establishes dependencies implicitly through ordering. The sequential loop respects those dependencies automatically. Parallelizing the steps would require you to explicitly model every dependency between them — which is the path back to STRIPS and A*, the very complexity this approach is designed to avoid.
The planning loop here still asks the model to describe what it would do for each step. In the next module, I extend this pattern to a proper tool-orchestration layer: instead of asking the model to narrate a step, I give it a small set of verified tools — read file, write file, run command — and let it pick the right one. The planning system you built here becomes the input to that orchestration layer.
The planning and tool layers together form the backbone of the task-orchestration agent. Module 06 then explains why keeping this agent linear and single-threaded — rather than splitting it into parallel sub-agents — is what makes it reliable in production.
Application-level questions — predict outcomes and spot the failure mode.
1. In the task-orchestration agent, what goes wrong when each step receives only its own description and no prior context?
Correct Answer: B
Without a shared context, each step builds on its own internal map. Later steps do not know what earlier steps decided, so they make conflicting assumptions. The outputs are locally reasonable but globally incoherent.
2. In the planning loop, what does the shared context dictionary contain after the plan is generated but before any step runs?
Correct Answer: B
The context is initialized with the task, the parsed plan list, and an empty completed list. The completed list is populated as steps finish.
3. Which model does the planning loop use in the examples above?
Correct Answer: C
All examples in this module use claude-sonnet-4-6. It is the pinned intermediate model for this learning path — balanced for the kind of agentic task orchestration work being demonstrated.
4. What is the role of parse_plan in the planning loop?
Correct Answer: B
parse_plan takes the model's free-text output and extracts the numbered steps into a Python list. This makes each step addressable by index and suitable for storage in the context dictionary.
5. If the steps 'Build a Docker image' and 'Apply the Kubernetes manifest' run in parallel, what is the most likely failure?
Correct Answer: B
The manifest references the image by tag. If the image has not been built and pushed before the manifest is applied, Kubernetes will try to pull an image that does not exist and the deployment will fail. Ordering the steps sequentially avoids this by design.
6. After step index 0 runs successfully, what does context['completed'] contain?
Correct Answer: C
context['completed'] is appended with a completion record after each step runs. After step 0, it contains one entry — the description of step 0 plus a done marker.
7. What does adding a planning call at the start of a task cost, and what does it buy?
Correct Answer: B
The planning call is one extra API round-trip. The return is a shared plan that every subsequent step reads, which prevents steps from making conflicting decisions. For most multi-step tasks, that trade-off is clearly worth making.