Skip to content

Planner-Executor AI Workflow: Using Opus for Planning and Budget Models for Execution

My Claude API bill hit $300 last month. Most of that spend went to routine coding tasks — code reviews, documentation generation, test case creation. Tasks that didn’t need Opus-level reasoning.

I had two options: cut back on AI usage or find a cheaper way to handle the routine work. I chose the second option and tested a planner-executor workflow for five days.

The results: 60-80% cost reduction with minimal quality loss.

The Core Idea

The planner-executor pattern separates high-level reasoning from task execution. Instead of sending every request to Opus, I use it only for planning. Then I hand those plans to budget models for execution.

Workflow Overview
Task -> Opus Planning -> Detailed Plan -> Budget Execution -> Implementation -> Review

Opus creates detailed, step-by-step instructions. Budget models follow those instructions. A review step catches errors.

Why This Works

I tested three models over five days: GLM-5.1, MiniMax-2.7, and Claude Haiku. Each had different strengths:

Model Performance Comparison
+------------------+----------------------+----------------------+
| Model | Strength | Best Use Case |
+------------------+----------------------+----------------------+
| Claude Opus | Deep reasoning | Planning phase |
| Claude Sonnet | Balanced | Review phase |
| Claude Haiku | Fast, cheap | Simple execution |
| GLM-5.1 | Strong logic | Complex execution |
| MiniMax-2.7 | Fast execution | Rapid iteration |
+------------------+----------------------+----------------------+

The key insight from my testing: plan quality determines execution success. When Opus creates a plan that a “junior developer” can follow, MiniMax performs well. When the plan is vague or ambiguous, execution fails.

Setting Up the Workflow

Phase 1: Planning with Opus

Opus analyzes the task and breaks it into atomic steps. The prompt needs to emphasize creating instructions for a less capable model:

planner_executor.py
def create_plan(self, task: str, context: str) -> dict:
"""Use Opus to create detailed implementation plan"""
prompt = f"""
You are creating a detailed implementation plan for a junior developer.
Task: {task}
Context: {context}
Create a step-by-step plan that:
1. Breaks down the task into atomic operations
2. Specifies exact file paths and function names
3. Includes error handling considerations
4. Provides test cases to validate each step
Format as JSON with keys: steps, files_to_modify, tests_needed, edge_cases
"""
response = self.client.messages.create(
model="claude-3-opus",
max_tokens=4096,
messages=[{"role": "user", "content": prompt}]
)
return self._parse_plan(response.content[0].text)

I learned to make plans more explicit after several failures. When I wrote “implement authentication”, MiniMax created a basic login form. When I wrote “create JWT-based authentication with refresh tokens, rate limiting, and session management”, MiniMax delivered a complete system.

Phase 2: Execution with Budget Models

The executor receives the plan and implements it step by step:

planner_executor.py
def execute_plan(self, plan: dict) -> dict:
"""Execute plan with budget model"""
prompt = f"""
Follow this plan exactly. If you encounter ambiguity, note it for review.
Plan:
{plan['steps']}
Implement step by step, providing code for each step.
Format output as JSON with keys: implemented_steps, code_changes, issues_found
"""
response = self.client.messages.create(
model="minimax-2.7", # or glm-5.1 or haiku
max_tokens=8192,
messages=[{"role": "user", "content": prompt}]
)
return self._parse_execution(response.content[0].text)

The “follow exactly” instruction matters. Without it, budget models sometimes improvise. Improvisation leads to drift from the original plan.

Phase 3: Review with Sonnet

Review catches what budget models miss:

planner_executor.py
def review_implementation(self, plan: dict, implementation: dict) -> dict:
"""Review implementation against original plan"""
prompt = f"""
Review this implementation against the original plan:
Original Plan:
{plan}
Implementation:
{implementation}
Check for:
1. Plan adherence (each step completed correctly)
2. Edge cases missed
3. Code quality issues
4. Security concerns
Provide: approval_status, issues, suggested_fixes
"""
response = self.client.messages.create(
model="claude-3.5-sonnet",
max_tokens=2048,
messages=[{"role": "user", "content": prompt}]
)
return self._parse_review(response.content[0].text)

I skip review for trivial tasks. For anything touching production code or security, review is mandatory.

The Cost Math

Here’s what the numbers look like for a typical feature development cycle:

cost_calculator.py
MODEL_COSTS = {
# Input cost per 1M tokens
"claude-3-opus": 15.00,
"claude-3.5-sonnet": 3.00,
"claude-3-haiku": 0.25,
"minimax-2.7": 0.10, # estimated
"glm-5.1": 0.50, # estimated
}
def calculate_workflow_cost(
planning_tokens: int,
execution_tokens: int,
review_tokens: int,
executor_model: str = "minimax-2.7"
) -> dict:
"""Calculate cost comparison for different workflows"""
# Traditional: All Opus
traditional_cost = (
(planning_tokens + execution_tokens + review_tokens)
/ 1_000_000 * MODEL_COSTS["claude-3-opus"]
)
# Planner-Executor: Opus + Budget + Sonnet
pe_cost = (
planning_tokens / 1_000_000 * MODEL_COSTS["claude-3-opus"] +
execution_tokens / 1_000_000 * MODEL_COSTS[executor_model] +
review_tokens / 1_000_000 * MODEL_COSTS["claude-3.5-sonnet"]
)
savings = traditional_cost - pe_cost
savings_percent = (savings / traditional_cost) * 100
return {
"traditional_cost": traditional_cost,
"planner_executor_cost": pe_cost,
"savings": savings,
"savings_percent": savings_percent
}

Running the numbers for a typical feature:

Cost Comparison Example
Traditional (all Opus): $0.915
Planner-Executor: $0.225
Savings: $0.69 (75%)

The execution phase consumes most tokens. That’s where the savings come from.

Model Selection Guide

I choose executors based on task characteristics:

Executor Selection Matrix
+------------------------+------------+------------------+
| Task Characteristic | Executor | Reason |
+------------------------+------------+------------------+
| Speed critical | MiniMax | Fastest response |
| Logic complex | GLM-5.1 | Better reasoning |
| Routine/boilerplate | Haiku | Cheapest |
| High-stakes production | Sonnet | Safer fallback |
+------------------------+------------+------------------+

GLM-5.1 has better logic but runs slower. MiniMax is fast but sometimes misses subtle edge cases. Haiku is cheap but struggles with complex tasks.

Mistakes I Made

Vague Plans

My first attempts failed because plans lacked specificity. “Add error handling” produced inconsistent results across executors. “Add try-catch blocks to database operations with specific error messages for connection failures, query timeouts, and constraint violations” produced consistent output.

Skipping Review

I skipped review on a database migration. The executor missed a cascade delete that wiped related records. Review would have caught it.

Wrong Executor Choice

I sent a complex refactoring task to Haiku. It produced syntactically correct code that broke the application logic. GLM-5.1 handled the same task correctly.

No Fallback

When MiniMax failed on a task, I had no fallback mechanism. Now I route failed executions to Sonnet automatically.

Practical Template

Here’s the prompt template I use for different task types:

prompts.py
PLANNING_PROMPTS = {
"feature_development": """
Task: Implement {feature_name}
Requirements: {requirements}
Existing Code Context: {context}
Create a plan covering:
1. New files/components needed
2. Modifications to existing code
3. API changes
4. Database schema changes (if any)
5. Testing strategy
6. Rollback plan
""",
"bug_fix": """
Task: Fix bug {bug_description}
Error Context: {error_context}
Affected Files: {files}
Create a plan that:
1. Identifies root cause
2. Proposes fix approach
3. Lists affected components
4. Defines test cases
5. Considers side effects
""",
}

The key is structure. Each prompt forces Opus to think through implementation details, not just high-level concepts.

When I Still Use Opus Directly

Some tasks don’t benefit from this workflow:

  1. Architectural decisions — Need deep reasoning throughout
  2. Novel problems — No clear plan structure exists yet
  3. Security analysis — Risk outweighs cost savings
  4. Complex debugging — Execution phase would fail

For these, I send the full task to Opus without the executor step.

Claude Code Configuration

I configured Claude Code with model roles:

.claude/settings.json
{
"env": {
"ANTHROPIC_AUTH_TOKEN": "your-token",
"ANTHROPIC_BASE_URL": "https://api.anthropic.com"
},
"defaultModel": "claude-3-opus",
"fallbackModel": "claude-3.5-sonnet",
"maxBudgetUsd": 10.00,
"modelRoles": {
"planning": "claude-3-opus",
"execution": "minimax-2.7",
"review": "claude-3.5-sonnet"
}
}

This lets me switch roles based on task phase without manual configuration changes.

Summary

The planner-executor workflow changed how I use AI for development. Opus handles the thinking. Budget models handle the doing. Sonnet handles the checking.

The tradeoff is clear: I spend slightly more time crafting detailed plans, but I save 60-80% on API costs. For routine tasks, that tradeoff works.

Three principles matter most:

  1. Plan specificity — Vague plans fail. Detailed plans succeed.
  2. Review discipline — Skip review only for trivial tasks.
  3. Executor matching — Match executor to task characteristics.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments