Codex Retrospective: From 30-Second Feedback to Hour-Long Autonomous Runs
The Codex team's retrospective reveals how AI coding agents evolved from requiring human feedback every 30 seconds to running autonomously for hours, shifting feedback from granular actions to high-level events like permission boundaries and acceptance criteria, enabled by a persistent runtime that preserves goals and state across sessions.
Not Fewer Glances, But a Different Kind of Feedback
In late 2024, Alexander Embiricos set a standard: users must know what the model is doing every 30–60 seconds. Early models could only read a few files, run a command, or hit an error before drifting off course. Frequent human checks acted as the system's direction-keeping mechanism.
Later models gained cross-file editing and self-test execution. Pushing every command to the human interrupted flow, yet returning only a "done" message after hours left no confidence to merge. The key insight: long tasks don't eliminate feedback; they change its unit.
Early feedback: actions — which file read, which command executed.
Long-task feedback: events — why it stopped, what information is missing, which action crosses a permission boundary, whether direction needs adjustment, and what evidence proves the result usable.
Codex's pivots — Cloud → CLI → IDE → Desktop App — all centered on the same problem: how does a human re-attach to the same task after leaving?
First Cloud Version Moved Execution Away and Locked Humans Out
Spring 2025: ~7 weeks to build Cloud v1. Developers handed off tasks; Agent ran on remote machines — read code, edit files, run tests. Laptop could close; results viewed later. Worked inside OpenAI, failed externally.
External developers spent hours replicating local software, permissions, settings, credentials, and dependencies into the cloud. If the Agent misunderstood, users couldn't add a follow-up in the same task — a new prompt spawned a fresh remote machine.
Submit task
↓
Remote execution ── Direction drifted ── Spin up new machine
↓
Return result"Cloud config is hard" was surface-level. For async execution to work, the goal left by the human, the Agent's attempts, and the human's later corrections must live in one task state. Missing any piece turns "letting go" into post-hoc rework.
A Database Driver Upgrade: Where the Human Gets Called Back
Illustrative engineering example (not an OpenAI internal case):
Task: upgrade DB driver and fix affected tests.
Agent updates driver version, lock file, connection-pool compat code. Unit tests pass. Next it tries to run: ./scripts/test-migrations.sh Script needs /srv/shared/test-db.env outside the sandbox — task halts at permission boundary.
A bare "needs approval" popup is useless. The request must surface:
About to execute ./scripts/test-migrations.sh Will read /srv/shared/test-db.env Driver version, lock file, compat layer already modified
No migration run yet, shared DB untouched
Reject preserves current edits, awaits new test path
Developer denies shared config, adds: "Don't touch shared env; use repo's docker-compose.test.yml to spin local Postgres."
Agent keeps prior dependency/compat changes, adjusts test fixture, continues from migration test.
At acceptance, developer sees: driver version, diff scope, migration exit code, unit + migration test results, inspectable migration log — not just "completed".
Human intervened twice: once for permission/path decision, once for final acceptance. Intermediate file reads, edits, retries handled by Agent.
Fewer process views ≠ less control. Control compressed to the two moments that actually change outcome.
Runtime Must Remember More Than Chat History
After Cloud setback, Tibo took engineering lead, shifted to local CLI. Instead of piling terminal features, team rewrote core Agent in Rust, extracting task loop, tool calls, context, and run state from the UI.
This foundation now powers CLI, IDE, Desktop, and mobile — different entry points, same task chain.
Public Codex App Server API shows the chain: Thread persists task + history turn/steer injects new requirements into running Turn turn/interrupt halts current execution thread/status/changed notifies outer product on state changes thread/resume restores original Thread when human returns
For the DB driver example, system must retain:
Original goal: upgrade DB driver and fix affected tests
Completed: driver version, lock file, connection-pool compat code
Current stop reason: migration script requests /srv/shared/test-db.env
Human decision: reject shared config, use repo-local Postgres via docker-compose.test.yml
Resume point: keep existing edits, continue from migration test
Acceptance criteria: diff, exit status, unit tests, migration tests, migration logIf state lives only in a UI's memory, switching to mobile, restarting client, or any interruption forces full re-explanation. Runtime lifts state out of the UI so human input becomes a steer on current execution, not a fresh prompt.
Agent control plane isn't a fancier task board. It must answer four questions: where is the task, why did it stop, what must the human decide, and where to resume after the decision.
Mobile Only Receives That Decision
With state extracted from UI, mobile entry becomes viable.
OpenAI's Remote Connections docs clarify: project, files, credentials, shell, tools, and execution environment stay on the connected computer or remote host. Mobile can continue tasks, answer questions, add requirements, handle approvals, view diffs, test results, terminal output, screenshots.
It doesn't squeeze an IDE onto a small screen; it delivers a concrete decision to the human.
Example: during the migration test, a developer in line or at lunch can't re-grasp the whole codebase but can understand which config the command reads and choose local test container. Back at desktop, full diff and test logs await.
Notifications must carry stop reason, completed actions, impact scope, and optional paths — not just "task needs attention".
Phone isn't a new dev environment; it's the nearest control entry point.
Goal Holds the Target, Evidence Decides Completion
Multi-hour tasks don't mean a single Turn runs forever.
Codex's Goal is a Thread-scoped persistent target. System continues only when a Turn ends, Thread is idle, no pending work or queued input. Interrupt pauses the Goal; a continuation with no tool calls suppresses the next auto-continue to prevent idle spinning.
In the driver upgrade, Goal stays "upgrade driver and pass related tests". Switching test paths, re-running migrations, fixing compat code — all without re-declaring the goal.
But Goal cannot declare completion.
Budget exhausted → only means this run stops.
Turn ends → only means one execution round finished.
Model says "fixed" → just a sentence.
Final verdict requires verifiable artifacts: driver version updated, diff in bounds, migration exit code, unit + migration tests pass, log shows no skipped/ignored failures.
Three concerns must stay separate in long tasks: Agent executes, Runtime persists state and catches human intervention, tests/logs/artifacts prove the result. Model capability expands execution fastest; human confidence to walk away depends on whether the other two keep pace.
From 30 Seconds to Hours: The Reason for Return Changes
Embiricos's original "30 seconds to 1 minute" rule hasn't expired.
When model only takes a few steps, human returns to watch actions, prevent early drift.
When model runs hours alone, human skips file reads and command executions but still returns at specific nodes: insufficient info, permission boundary, direction change, execution anomaly, and result awaiting acceptance.
This product history isn't "local beat cloud" nor "Desktop App replaces IDE". Entry points will keep shifting; model autonomy will keep growing.
What remains stable is a handoff chain: task state, stop reason, human decision, resume point, acceptance evidence.
The more the Agent can do alone, the less the human should be trapped in the process. But every recall must carry a concrete, decidable reason.
References
Dan Shipper, How Codex Happened (https://every.to/p/how-codex-happened)
OpenAI, Codex App Server (https://learn.chatgpt.com/docs/app-server)
OpenAI, Using Goals in Codex (https://developers.openai.com/cookbook/examples/codex/using_goals_in_codex)
OpenAI, Remote connections (https://learn.chatgpt.com/docs/remote-connections)
Thomas Ricouard, Mastering remote engineering work from your phone (https://learn.chatgpt.com/blog/mastering-codex-remote-for-engineering)
OpenAI, Codex as a platform: build on the open agent harness (https://developers.openai.com/blog/codex-as-a-platform)
OpenAI Engineering, Unrolling the Codex agent loop (https://openai.com/index/unrolling-the-codex-agent-loop/)
OpenAI, Introducing the Codex app (https://openai.com/index/introducing-the-codex-app/)
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architect
Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
