[CLI] Add deterministic execution budgets to `codex exec` (`--max-steps` / `--max-agent-turns`)
What variant of Codex are you using?
Cli
What feature would you like to see?
Please add a deterministic execution-budget option to codex exec, similar to a --max-steps or --max-agent-turns flag.
Example:
codex exec \
--json \
--max-agent-turns 10 \
"Evaluate whether the appropriate skill is triggered for this task"
The default could remain unlimited, preserving the current behavior.
The option should limit the number of agent loop iterations rather than wall-clock execution time. A clear possible definition would be:
One agent turn is one model response cycle. Parallel tool calls initiated by the same model response count as part of the same turn.
When the limit is reached, Codex should:
- stop the run cleanly;
- return a non-zero exit code;
- preserve the JSONL trace generated so far;
- emit a structured terminal event, for example:
{
"type": "turn.failed",
"error": {
"code": "max_agent_turns_exceeded",
"message": "Maximum agent turn limit of 10 was reached."
}
}
A configuration equivalent would also be useful:
max_agent_turns = 10
Why this is needed
This is particularly useful for automated evaluation of Codex Skills.
For example, in a repository containing a large hub of skills, we may need to evaluate whether a skill's description correctly routes a natural-language request to the intended skill.
A typical evaluation runs the same prompt multiple times and compares:
- a baseline run without the skill;
- a run with the skill installed;
- whether the expected skill was triggered;
- whether it was triggered early enough;
- the trigger success rate across repeated runs;
- whether unrelated skills were incorrectly selected.
Without an execution-step limit, individual runs can vary significantly in duration, token consumption, tool calls, and exploration depth. This makes comparisons less reproducible and increases the cost of running larger evaluation matrices.
It is also useful for deliberately simple tasks. A caller may know that a task should require no more than a small number of model/tool cycles and may want Codex to fail explicitly if it begins over-exploring the repository.
Why existing workarounds are insufficient
Wall-clock timeout
An external timeout limits elapsed time, but does not provide a deterministic behavioral budget.
Two runs may perform very different numbers of model and tool iterations within the same time limit because of network latency, command duration, repository size, caching, and model response time.
Counting JSONL events externally
A wrapper can count command_execution, mcp_tool_call, or other JSONL events, but these are not equivalent to agent turns:
- one model response can initiate multiple parallel tools;
- an agent iteration may contain no shell command;
- file changes and tool calls do not necessarily map one-to-one to model cycles;
- the wrapper may have to terminate the process abruptly instead of allowing Codex to produce a structured final event.
The Codex runtime itself is the only layer that can enforce this limit with well-defined semantics.
Suggested minimum implementation
A minimal implementation would be sufficient:
--max-agent-turns <N>
With the following behavior:
- omitted: unlimited, matching current behavior;
- positive integer: stop before starting turn
N + 1; - limit reached: structured JSONL failure event and non-zero exit code;
- available in both the CLI and configuration file;
- compatible with
codex exec --json.
An optional future extension could introduce separate budgets such as:
--max-tool-calls <N>
--max-output-tokens <N>
However, a model-loop or agent-turn limit alone would already solve the main reproducibility problem.
Related issue
Related to #12336, which requested a general --max-turns option.
This request provides a more specific use case and proposed semantics for deterministic Skill evaluation, automated regression testing, JSONL-based CI workflows, and bounded execution of simple tasks.
Additional information
_No response_