How I route work in Codex
How I use Astra to coordinate work, Sol to manage implementation and Luna for specific coding tasks, with a routing policy you can reuse.
Model names, benchmark figures and token rates checked on 17 September 2026. Sol’s listed rates are promotional through at least 21 November 2026.
Some Codex users on the $200 plan report using up a week’s allowance in a day. In a Reddit thread about the plan, one user reported using a quarter of it in two hours on Astra medium. Replies in the same thread describe much lighter use too. Another on OpenAI’s forum went from over 90% to 14% in nine hours on Astra extra high. I did the same. My first day on Astra used up the whole week’s allowance, so I changed how I assign work.
The setup I use now is costing me less in day-to-day use. That is my observation, without a measured comparison of the same tasks across all three setups. This post explains how I assign the work and why I chose these models.
This setup uses four Codex models: GPT-6 Astra, and GPT-5.6 Sol, Terra and Luna. From most to least expensive per token they are Astra, Sol, Terra and Luna. At the Codex token rates checked above, Astra costs two and a half times Sol for each token category. Sol costs twenty times Luna for input and cached input, and about seventeen times for output.
I have tried three setups. The labels high, medium and max are reasoning-effort settings: they control how much reasoning the model does.
| Setup | My experience | What I changed |
|---|---|---|
| 1. Astra high for everything. One chat plans, implements and reviews. | A week’s allowance gone in a day. | Moved implementation to a separate Sol medium chat. |
| 2. Astra high coordinates, Sol medium implements. Sol also runs its subagents on Sol medium. | I noticed lower usage after separating coordination from implementation. | Kept the Sol chat and moved scoped subagent work to Luna max. |
| 3. Astra high coordinates, Sol medium implements, Luna max runs the coding subagents. | In use since 10 September and costing me less in day-to-day use. | This is the setup I use. |
Since 10 September, I have kept Astra responsible for coordination, Sol for implementation and integration, and Luna max for scoped coding assignments. Below are the prompt and routing policy I use.
Ask Astra to create a separate Sol chat
Start in a chat set to Astra with high reasoning. Once you have agreed on the work, ask it:
Create a new chat to implement the work we have agreed.Use GPT-5.6 Sol with medium reasoning in that new chat.Pass it the agreed scope, repository context, constraints and acceptance checks.Coordinate the work from this Astra chat.Set up an automated check in this Astra chat every 15 minutes to follow the Sol chat.At each check, read its latest status and inspect more detail only if needed.Stay quiet while work is progressing normally. Notify me when the work is readyfor review, a material failure occurs, or a decision needs my input.Do not restart healthy work or duplicate Sol's implementation.Review the result against the acceptance checks when it is ready.Stop the automated checks once the work is complete or I ask you to stop.The new Sol chat appears in the sidebar. Astra sends it instructions and checks its progress through the app’s task tools. In the app, a task is a separate chat.
Astra owns the objective, the scope, decisions that span chats and the final judgment of whether the work is complete. Sol implements the change, merges its children’s contributions and runs the agreed checks. Sol’s children investigate code or implement one scoped change each. Sol stays responsible for the whole.
How I divide the work
-
Human Sets the goal and approves consequential choices
-
Your original chat Astra · high Owns the outcome, keeps context, and routes implementation
-
New implementation chat Sol · medium Implements, verifies, and returns the result to Astra
Bounded subagents
Sol can call one or more for a specific piece of work. Choose only the help the assignment needs.
- Luna · mediumRoutine work
- Luna · maxCoding
- Terra · highExploration
- Sol · highJudgment
Checks and evidence return through Sol to Astra. Astra reports progress and approval points to the human.
Astra reads the evidence, resolves decisions outside Sol’s assignment and checks the result against the objective. It does not redo Sol’s implementation. Sol returns changed files, check results and anything unresolved.
The prompt requests both the Sol chat and a recurring 15-minute check (a heartbeat) in the Astra chat. The ROLES.md file below tells Sol which children to use; it does not schedule those checks. These controls are in the desktop app. Other Codex hosts differ.
Choose a model for each subtask
This is the child-routing policy. The full ROLES.md is below:
| Work | Model | Reasoning effort |
|---|---|---|
| Routine lookups, inventories, log summaries and status checks | Luna | medium |
| Bounded implementation, tests, diagnosed fixes and mechanical refactors | Luna | max |
| Substantial code exploration and dependency tracing | Terra | high |
| Planning, architecture, difficult diagnosis and independent review | Sol | high |
I set reasoning effort alongside the model, so Luna medium and Luna max are different choices.
Choose by the judgment the work needs, not by file count. A fix with a known cause goes to Luna max with the cause, the files it may change and the acceptance checks. A fix with an unknown cause is a diagnosis job for Sol high. One file can need more judgment than a mechanical edit across twenty.
Every child gets a bounded outcome, the relevant evidence and a write scope. Children sharing a checkout preserve each other’s edits. I delegate when the pieces are independent; most tasks need one or two children, not four. When a child finds a conflicting requirement or an unresolved cause, I send the evidence and the open question to Sol high.
I never retry the same prompt on the next model. An unclear requirement or missing evidence can leave a more expensive model solving the same wrong problem. Before escalating, identify what failed and give the next model that evidence and a revised assignment.
Why Luna max does the scoped changes
Lower cost is my main reason for trying Luna max on scoped changes. Datacurve’s DeepSWE v1.1 provides supporting evidence: it runs an agent on engineering tasks and tests the committed patch in a clean environment. The table below uses the live leaderboard checked on 17 September 2026. Token counts and dollar costs are means per scored attempt, including failures:
| Model | Pass rate | Output tokens | Benchmark cost per attempt |
|---|---|---|---|
| Luna max | 67.19% ± 3.99 points | 73,400 | $0.61 |
| Sol medium | 61.06% ± 1.58 points | 18,425 | $1.42 |
| Sol high | 69.40% ± 1.43 points | 28,450 | $2.66 |
Luna max’s average pass rate is 6.13 percentage points above Sol medium’s, with a wider reported interval: ±3.99 points against ±1.58. Those results come from 113 tasks in Datacurve’s setup. They do not establish that Luna will perform better on my repositories. Sol high has the highest average pass rate among these three configurations.
Luna’s lower reported cost per attempt is the stronger reason to try it here. As I argued in the previous post, benchmarks help choose candidates. DeepSWE uses mini-swe-agent. My Astra, Sol and Luna workflow uses different instructions and divides the work between models, so the leaderboard cannot establish its cost or quality advantage. Sol still has to integrate each change and run the acceptance checks.
Benchmark scope and source data
The live leaderboard uses mini-swe-agent on 113 tasks over four runs. Luna max passed 301 of 448 scored attempts, Sol medium 276 of 452, and Sol high 313 of 451. The intervals are the published 95% run-to-run half-widths. Provider, verifier and network failures are excluded; timeouts and context-window failures count.
The cost column follows the live leaderboard. When checked on 17 September, its downloadable JSON reported different dollar costs, so it is not the cost source for this table.
Keep Astra focused on decisions
I use Astra to agree on the scope, resolve decisions outside Sol’s assignment and review the final result. Sol owns the implementation chat. Luna max gets individual coding assignments with the files it can change and the checks it must pass.
When Luna returns, Sol integrates its changes and runs the checks. Astra reads that result instead of repeating the implementation. The automated progress check follows the same rule: inspect more detail when something changes or needs attention.
The model prices are why I assign routine coding this way. At the Codex token rates checked on 17 September 2026, Luna’s uncached and cached input each cost one twentieth of Sol’s. Its output costs about one seventeenth. Repeated context, retries and review still consume tokens, so clear assignments matter.
Published Codex token prices
Credits per million tokens, excluding Fast mode multipliers:
| Model | Uncached input | Cached input | Output |
|---|---|---|---|
| Astra | 250 | 25 | 1,250 |
| Sol | 100 | 10 | 500 |
| Terra | 50 | 5 | 300 |
| Luna | 5 | 0.5 | 30 |
Sol’s listed rates are promotional and available at least through 21 November 2026. These are the published prices for tokens, not a fixed charge per task.
Put the policy where the implementer can read it
Read the full file below or download ROLES.md. Save it in your repository root, beside AGENTS.md. In this workflow, Sol reads it before delegating to children. The file uses “coordinator” for whichever agent delegates, which is Sol here.
Read ROLES.md
# Codex subagent routing
Use these rules when delegating work to Codex subagents. They apply in any repository and require no additional workflow or skill. The main agent's model and reasoning effort remain the user's or host's choice.
## Choose a model before delegating
| Work | Model | Reasoning || --- | --- | --- || Routine lookups, inventories, log summaries, and status checks; fallback for routine work | `gpt-5.6-luna` | `medium` || Bounded implementation, tests, fixes with a diagnosed cause, document edits, and mechanical refactors | `gpt-5.6-luna` | `max` || Read-heavy code exploration, dependency tracing, and checking documentation against code | `gpt-5.6-terra` | `high` || Planning, decomposition, architecture, difficult diagnosis, independent review, and final functional judgment | `gpt-5.6-sol` | `high` |
Choose by the judgment required, not by file count. A routine lookup stays Luna medium. Exploration requiring substantial synthesis uses Terra high. Writing a well-scoped change uses Luna max. Resolving an unclear contract or root cause, making architectural decisions, or judging correctness independently uses Sol high. Split mixed work only when the pieces can be completed independently; otherwise use the model required for its hardest essential decision.
Never select Luna low. Explicit user instructions and required project specialist configurations take precedence over this table.
## Delegate a bounded outcome
Before spawning a child, specify its outcome, relevant evidence, ownership or write scope, constraints, and completion checks. For code changes, tell the child that others may be working in the repository and that it must preserve their edits. Request a concise result with changed files, checks, and unresolved issues.
Select the model and reasoning effort explicitly through the host's supported delegation mechanism. Use an existing configured role when it provides the required settings. Some hosts pin specialist models or restrict overrides when inheriting conversation history: use a supported configuration or fresh child where available. If the requested selection is unavailable, report the limitation; do not claim that routing was applied.
## Control cost and escalation
Delegate when independent work justifies another agent. Give each child the relevant context and contracts, avoiding unrelated history. Reuse its completed work, use deterministic commands for mechanical checks, and avoid overlapping investigations or duplicate reviews.
If a child exposes an unresolved root cause, conflicting requirements, or a decision beyond its scope, send the evidence and remaining question to Sol high. Do not automatically retry through Luna, Terra, and Sol, or restart the same failed prompt without new evidence. Keep required independent review separate from implementation.
## Optional runtime fallback
This document guides the coordinator's choices; it does not change Codex settings. On hosts supporting these options, merge the following keys into the existing `[agents]` table in `.codex/config.toml`, preserving other settings:
```toml[agents]default_subagent_model = "gpt-5.6-luna"default_subagent_reasoning_effort = "medium"```
The fallback does not classify tasks. Explicit spawn settings and configured specialist roles can select other models. Check the host's reported child configuration when available before claiming a model was used.
Configuration reference: [Codex subagents](https://learn.chatgpt.com/docs/agent-configuration/subagents).Append this line to your existing AGENTS.md:
Before delegating work to subagents, read and follow [ROLES.md](ROLES.md) for model selection, delegation scope, and escalation.ROLES.md also carries the .codex/config.toml fallback that makes Luna medium the default child. The Sol implementer still picks Luna max, Terra high or Sol high when the work calls for it. After a run, check the reported child model and effort. The host applies the settings, not the file. My Astra choice for the main chat is separate from this policy.
Keep periodic supervision narrow
A 15-minute heartbeat on the Astra chat checks the Sol chat. It reads compact status first and looks deeper only when progress changes or something fails. It reports completion, a material failure or a decision I need to make. Healthy work stays quiet. It never restarts healthy work or opens a second writer, and it stops when the objective is done.
The heartbeat runs on Astra and consumes the usage allowance. Include it in what you measure.
When the workflow goes wrong
Here is how to handle three failure cases.
Two children edit the same files. Their patches can conflict or overwrite each other’s changes. Stop overlapping writes, preserve both sets of edits, and have Sol reconcile them before continuing. Assign shared files to one child or sequence the changes. Checks must run on the combined result.
A heartbeat restarts healthy work. That creates a second attempt, adds usage and may introduce another writer. Stop the duplicate, keep the original task running, and correct the check’s instructions. A status check should only intervene when there is evidence of a failure or a decision outside the assignment.
A child says “done” but the change fails its checks. Sol must treat that result as incomplete. Return the failing command, output and relevant diff with a bounded repair request. If the cause is unclear, send a diagnosis assignment to Sol high. Astra should review the evidence from the final combined change before reporting completion.
Judge the setup by accepted work
Sol is responsible for delivering a change that passes the agreed checks. Astra reviews the evidence and decides whether the objective is complete. A cheaper model has done useful work only when its result can be accepted.
The change is costing me less: Astra coordinates, Sol implements and integrates, and Luna handles scoped coding work. I keep the same requirement for completion: the combined change must pass its checks. To compare the setups properly, I would count Astra’s checks, Sol’s integration, every child’s attempts and the repairs. The measure remains the full cost of an accepted change.
For a defined development workflow, see Symphony Forge, which I built at KnackLabs. The ROLES.md above can also be used directly in any repository.
Continue the conversation
Share this article or talk with me about your team’s work.