Loops and autonomous runs in codex
# Loops and autonomous runs in codex
Some coding work is the same step on repeat until a condition is met: run the tests, read the failure, patch the code, run the tests again. That pattern is exactly what Codex was built to automate, not as a one-shot request but as an agentic loop that keeps editing and running until the task is actually done.
The agentic loop, concretely
You already know an agent plans, acts, and observes. In Codex that loop is grounded in a real workspace: a checkout of your repo, a shell, and the ability to run commands. Each turn looks like this:
1. Read the task and the current repo state.
2. Decide on an action (edit a file, run a command).
3. Execute it in the sandbox and capture the output.
4. Compare the result against the goal. If not met, loop.
The critical difference from a single prompt is the observe step. Codex sees stdout, exit codes, and stack traces, then feeds them back into the next decision. That is why "make the tests pass" works: the test output *is* the signal that drives the next edit.
Codex comes in two shapes that share this engine: the CLI/IDE agent that runs locally against your working tree, and Codex cloud, which runs the loop on OpenAI's infrastructure against a connected GitHub repo. The cloud version is where autonomous and scheduled runs live. See the Codex documentation for the current surface.
When a loop beats a single request
A single request is right when the change is bounded and you can eyeball the diff. ReachReachThe number of unique people exposed to your message in a given period. Unlike impressions, reach counts each person once, no matter how often they see it.Voir la définition complète → for a loop when the task has a verifiable stop condition the agent can check itself:
- Iterate until tests are green. The test suite defines "done." The agent doesn't need you between attempts.
- Work through a backlog of files. Migrate every component off a deprecated APIAPIApplication Programming Interface: a standardised interface that lets applications communicate and exchange data without knowing each other's internal workings.Voir la définition complète →, add type hints to a directory, or bump a pattern across 40 modules. The loop is "for each file: apply change, run its tests, move on."
- Fix until lint and type checks pass.
ruff,mypy,tsc: each returns a clean exit code you can loop against.
The common thread: there is a machine-checkable oracle. If "done" is subjective ("make the UI nicer"), a loop just burns budget chasing a target it can't measure. Keep those as interactive sessions.
Iterate until the tests are green
Here is the canonical loop. You give Codex the goal, the command that verifies it, and a ceiling. Locally, that looks like a prompt plus a config; in cloud you set it up per task. This YAML is the kind of task spec you'd hand a scheduled Codex run:
task: Fix the failing tests in the billing module.
repo: acme/payments
branch: fix/billing-tests
setup:
- pip install -e ".[dev]"
verify:
command: pytest tests/billing -q
success_when: exit_code == 0
limits:
max_iterations: 8
max_wall_clock_minutes: 20
on_success:
open_pull_request: true
reviewers: [payments-team]The loop the agent actually runs is trivial in pseudocode, and worth seeing so you know exactly what it's optimizing:
for attempt in range(max_iterations):
result = run("pytest tests/billing -q")
if result.exit_code == 0:
commit("fix: billing tests green")
break
# Codex reads result.stdout, edits the relevant files,
# then the loop re-runs the same command.
apply_fix(diagnose(result.stdout))
else:
report("gave up after max_iterations; latest diff attached")Two things make this safe rather than a runaway. First, verify.command is the *only* definition of success, so the agent can't declare victory on vibes. Second, the loop terminates on either green tests or a hard cap. There is no path where it runs forever.
Kicking off autonomous and scheduled runs
In Codex cloud you connect a GitHub repo, then start tasks that run without you sitting there. There are three ways to trigger one:
- On demand. Describe the task, pick the repo and branch, and Codex spins up an environment, runs the loop, and opens a PR when it finishes.
- Scheduled. Codex supports recurring runs, the same mechanism behind ChatGPT scheduled tasks. A nightly "run the full suite on
main, fix any flakes, open a PR" job is the classic use. - Event-driven, via the API. Wire a run to fire from CI or a webhook (a new issue labeled
codex, say) using the Responses API with tools, or orchestrate multi-step control with the Agents SDK.
The mental model: an on-demand run is you pressing go. A scheduled run is a cron job that happens to be an agent. Both drop their work into a branch and a pull request, never straight onto main.
A scheduled backlog example
Say you're migrating a codebase off a deprecated logging call. You don't want to babysit 40 files. Schedule a nightly run:
> "For up to 6 files still using old_logger, replace it with structlog per docs/logging.md, run pytest for each touched module, and open one PR titled chore: migrate logging (batch). Skip files where tests fail after the change and note them in the PR description."
That spec has a batch size (cost control), a per-file verify step (correctness), and an explicit escape hatch for the hard cases (don't force a broken change). Over a week the backlog drains itself, one reviewable PR at a time.
Building with Codex
Stop conditions: what actually ends a loop
An unattended loop needs more than one exit. Design for all of these:
- Success condition met. The verify command returns exit code 0. This is the happy path.
- Iteration cap.
max_iterationsstops the "edit, still red, edit again" spiral. If eight attempts don't get tests green, more attempts rarely will. - Wall-clock / budget cap. A time or tokentokenA token is the basic unit of text that language models process, often a word fragment, whole word, or punctuation mark rather than a single character.Voir la définition complète → ceiling. When Codex can't converge, you want it to stop *cheaply* and hand you a diff, not grind.
- No-progress detection. If two consecutive attempts produce the same failing output, the agent is stuck. A good loop treats that as a stop, not a reason to try the identical fix again.
State every cap explicitly. The failure mode of autonomous runs is not usually a bad edit; it's an agent thrashing against a problem it can't solve while the meter runs.
Cost caps and the sandbox
Every Codex cloud run executes in an isolated container: a fresh environment with your repo, no access to your other systems unless you grant it. That isolation is your first cost and safety boundary, because a loop that can't touch production can't cause a production incident.
Control spend at two levels:
- Per run: the iteration and time caps above. A 20-minute ceiling on a nightly job bounds the worst case.
- Per account: set usage limits in the OpenAI platform billing settings so a misconfigured schedule can't quietly run all night for a week.
Also control what the loop can reach. Network access in the Codex environment is configurable; for a test-fixing job, the agent needs your repo and package installs, not the open internet. Narrow the environment to what the task requires. A loop with fewer capabilities is a loop with fewer ways to surprise you.
Vérification des acquis
1. What is the critical difference between an agentic loop in Codex and a single one-shot prompt?
2. According to the lesson, what is the defining characteristic of a task that is well-suited to an autonomous loop?
3. Why does the lesson advise keeping a task like 'make the UI nicer' as an interactive session rather than an autonomous loop?
4. Select ALL of the following that are valid examples, per the lesson, of tasks with a verifiable stop condition suited to a loop.
Sélectionnez toutes les réponses correctes.
5. Select ALL correct statements about the two shapes of Codex described in the lesson.
Sélectionnez toutes les réponses correctes.
Review gates: trust, but verify the diff
The single most important safety property: an autonomous Codex run produces a pull request, not a merge. The loop's output lands on a branch and waits for a human. Your existing GitHub protections still apply, and you should lean on them:
- Required reviews. Branch protection means a Codex PR can't merge without human (or CI) approval. Treat the agent as a contributor whose PRs always need review.
- CI as a second oracle. The agent ran tests locally in its sandbox; CI runs them again in your real pipelinepipelineAll active sales opportunities across the stages of the sales process, together with their combined potential value and probability of closing.Voir la définition complète →. If CI disagrees, the loop's "green" was environment-specific, and you just caught it.
- Scoped diffs. Batch size limits (six files, one module) keep PRs small enough to actually review. A 3,000-line autonomous diff is not reviewable and defeats the purpose.
Think of it as a funnelfunnelThe customer journey from awareness to purchase, typically Awareness, Interest, Consideration, Decision, Action, with prospects narrowing at each stage.Voir la définition complète →: the loop iterates freely inside the sandbox, but the exit is a narrow, reviewable gate. Freedom *inside*, control *at the boundary*.
Reading a Codex PR fast
Because the run logs every action, its PRs come with a trail: which commands it ran, what output it saw, and why it made each edit. When you review, check three things: does the diff match the stated goal, did the verify command genuinely pass (not get disabled or @skip'd), and is the change scoped to what you asked. A loop that "passes tests" by deleting the failing test is the classic cheat. Read for it.
Putting it together
A well-designed autonomous run reads like a contract. Goal, a machine-checkable definition of done, hard caps on iterations and time, a narrow environment, and a PR-only exit. Give Codex all five and you can leave it alone overnight with the same confidence you'd give a junior engineer working a well-specified ticket: it either finishes the ticket or tells you why it couldn't.
Key Takeaways
- Use a loop only when "done" is machine-checkable. Tests passing, lint clean, a type check exit code. If the target is subjective, keep it interactive.
- Always set three caps: success condition, iteration limit, and time/budget ceiling. The dangerous failure is an agent thrashing on an unsolvable problem, not a single bad edit.
- Schedule recurring work (backlog migrations, nightly test fixes) with batch sizes and per-item verification so each run drains the queue in small, reviewable PRs.
- Keep the sandbox narrow. Grant only the repo access and network the task needs; set account-level usage limits so a misconfigured schedule can't run up cost.
- The exit is a pull request, never a merge. Enforce branch protection and re-run tests in CI, and always read the diff for the "deleted the failing test" cheat.
À faire, tiré de cette leçon
Ces actions sont compilées dans le plan d'action du rôle.
- Set branch protection requiring PR, review, and passing checks before Codex runs
- Run autonomous loops only with a machine-checkable done condition and hard caps
- Review every diff for the deleted-failing-test cheat and scope creep