Clarify app-server turn lifecycle semantics for external clients
Open 💬 5 comments Opened May 4, 2026 by sanyathoque
💡 Likely answer: A maintainer (github-actions[bot], contributor)
responded on this thread — see the highlighted reply below.
What feature would you like to see?
Expose a stable, machine-readable lifecycle for Codex task execution so external clients can reliably monitor progress and decide when human review is needed.
This is intended for open-source integrations (CLI wrappers, dashboards, mobile/web review surfaces), without changing Codex model behavior.
Problem
Today, external tooling can observe Codex outcomes, but lifecycle signals are not consistently exposed as a stable contract. Integrators need to infer state transitions from mixed output/log patterns, which is brittle across versions.
Desired outcome
Provide a minimal, versioned lifecycle contract with:
- Run state transitions
- Review-required signal
- Diff/artifact summary metadata
- Final disposition
Proposed API shape (minimal)
A structured envelope emitted for each run:
run.createdrun.queuedrun.executingrun.review_requiredrun.completedrun.failedrun.canceled
Each event includes stable identifiers and timestamps, plus optional artifact summary fields.
Why this matters
- Enables reliable supervision UX for Codex runs
- Reduces parser fragility for community tooling
- Preserves Codex as source of truth while allowing ecosystem clients
Backward compatibility
- Additive only
- Existing human-readable output remains unchanged
- Version field in payload to support future extension
Acceptance criteria
- A documented event/state contract exists in docs.
- At least one output surface exposes the contract (stdout JSON mode, log stream, or dedicated command output).
- Contract includes explicit
review_requiredsignal. - Contract includes file-change summary metadata (
files_changed,insertions,deletions) when available. - Tests cover state transition ordering and terminal states.
Minimal schema example
{
"version": "1.0",
"event": "run.executing",
"run": {
"id": "run_123",
"session_id": "sess_456",
"task_id": "task_789",
"state": "executing",
"created_at": "2026-05-04T18:10:00Z",
"updated_at": "2026-05-04T18:10:12Z",
"review_required": false
},
"artifact": {
"diff_available": true,
"files_changed": 3,
"insertions": 42,
"deletions": 9,
"paths": [
"codex-rs/tui/src/app.rs",
"codex-rs/core/src/task.rs"
]
},
"terminal": {
"reason": null,
"exit_code": null
}
}
Enum values
state:created | queued | executing | review_required | completed | failed | canceledterminal.reason:success | error | user_canceled | policy_blocked | timeout
Additional information
I can help with:
- Repro cases
- Edge-case matrix (failed tool call, partial write, canceled run)
- Draft tests for transition validity
5 Comments
Adding a concrete transition test matrix proposal to make the lifecycle contract verifiable.
Transition Matrix (proposed)
Valid transitions:
created -> queuedqueued -> executingexecuting -> review_requiredexecuting -> completedexecuting -> failedexecuting -> canceledreview_required -> executing(after user requested changes / continue)review_required -> completed(after approval path)review_required -> canceledInvalid transitions (should be rejected or ignored with explicit error):
completed|failed|canceled) to non-terminalcreated -> completed(skipping execution)queued -> completed(skipping execution)created -> review_requiredInvariants (proposed)
run.idandsession_idare stable for all events in the same run.updated_atis monotonic per run.review_required=trueonly whenstate=review_required.files_changed,insertions,deletions) are non-negative integers when present.Edge Cases to test
executing -> failedand terminal reasonerror.executing -> canceledand terminal reasonuser_canceled.executing -> failed(orcanceled, depending on policy semantics) with terminal reasonpolicy_blocked.executing, final summary frozen at terminal state.review_required:review_required -> executingthen terminal state.If helpful, I can also draft this as table-form docs language to drop directly into
docs/.Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Following the guidance in #20952, I want to narrow this issue to app-server-facing lifecycle semantics rather than session JSONL stability.
Proposed narrowed scope:
Thread/Turn/Itemas the integration surface.turn/completedis guaranteed across terminal paths.I realize there is overlap with #20603, #19689, and #19934. My intent is to target the shared client-facing lifecycle contract (event semantics + invariants) rather than adding a separate JSONL stability requirement.
If this still reads as duplicate, I’m happy to close and consolidate into whichever issue you prefer.
Following the May 14 ChatGPT release of Codex remote access from the mobile app, I’d like to clarify the intended path for this issue.
The released mobile experience appears closely aligned with the use case described here: remote clients need to render and act on live Codex state, including approvals, diffs, terminal output, screenshots, and test results.
My request is not about the first-party mobile UI itself. I’d like to narrow this issue to the remaining open-source/app-server question:
Can the lifecycle semantics behind this remote experience be documented as a stable contract for external clients?
Specifically:
Thread/Turn/Itemevents are intended to be stable?Should this issue now be closed as covered by the May 14 release, or tracked as API/docs stabilization work for external integrations?
I opened this issue on May 4 as a community request for stable run/review lifecycle metadata. If the mobile rollout is using the same underlying direction, I’d appreciate acknowledgment of the prior community context here, and I’m happy to contribute a narrow docs draft, event schema draft, or lifecycle test matrix if maintainers think that would help.
Narrowing this further to make it actionable:
I’m happy to scope this as docs-only around the app-server interface.
Suggested deliverable:
Turnterminal statesNo runtime behavior change required unless maintainers identify a gap.