[Feature] Add a non-executing task handoff artifact for asynchronously queued Codex workflows
What feature would you like to see?
Codex should provide a first-class, non-executing task handoff mechanism that transfers a bounded, authoritative continuation state from one durable thread to another without resuming, waking, forking, or importing the full source thread.
This is needed for workflows where multiple Codex tasks have dependencies and must execute asynchronously in sequence:
Source task A: establish and approve a plan
Prerequisite task B: perform work that must finish first
Continuation task C: after B succeeds, execute A's plan
Task C should inherit a compact handoff from A, not A's entire conversation and not merely a best-effort transcript read. Task A should remain inactive.
This is different from moving an existing thread between a checkout, worktree, or host. It is a transfer of task state and intent, not a migration of the source thread itself.
Concrete use case
I had one Codex task that developed a detailed Android phone backup plan.
Before that plan could be executed, another task had to:
- temporarily move data off an exFAT SSD;
- format the SSD as NTFS;
- verify the new filesystem;
- restore the data.
The Android backup task could not know when this prerequisite would finish. After the storage task completed, I referenced the earlier Android task from the current task and asked Codex to continue its plan.
What I wanted was:
Prerequisite completed
-> obtain the final approved Android backup plan
-> transfer its scope, decisions, exceptions, and next step
-> execute it in the current task
I did not want to reactivate the original Android task or import its entire historical conversation.
What happened instead
The referenced task was initially exposed with a notLoaded status.
Codex used read_thread to inspect it. The result looked structurally successful, but recent turns contained empty item lists, while only some older conversation content was available.
The receiving model had no reliable indication that this was an incomplete or unhydrated projection. It interpreted the returned content as the complete task history, reconstructed an outdated plan, and began following the wrong backup scope.
A later message sent to the source task asking it to restate its final plan caused that task to wake. Its status changed to idle, and the correct later context and final plan then became available.
This recovered the information, but it also demonstrated why the current primitives do not compose into a safe handoff mechanism.
Why the existing primitives are insufficient
read_thread is transcript inspection, not task handoff
read_thread exposes a technical representation of thread history. Pagination, hydration state, empty item projections, compaction, large tool outputs, and history limits are implementation details.
A model can see a syntactically successful response without knowing whether it represents:
- the complete relevant history;
- only the currently hydrated portion;
- an incomplete projection;
- turns whose items are temporarily unavailable;
- truncated output;
- or merely the oldest/newest available page.
Even if every underlying bug were fixed, a raw transcript is not the same thing as an authoritative continuation state.
send_message_to_thread has execution semantics
As described in #32547, sending a message to a dormant durable thread can wake it and immediately start a new turn under its historical context.
Using this as a fallback to ask "What was your final plan?" is therefore not a read-only operation. The source task may run tools or resume stale work.
A system-prompt guardrail cannot remove that transport-level side effect.
Forking or importing the source thread transfers too much
Forking the source would retain historical instructions, discarded hypotheses, large logs, tool outputs, and assumptions that may no longer be relevant.
The desired continuation needs only the final accepted task state and a small amount of traceable supporting context.
Prompt guardrails cannot establish missing information
A receiving model can be instructed to distrust incomplete history, but it still needs a supported way to obtain the authoritative plan.
Prompting cannot:
- determine that an apparently successful read is incomplete;
- recover unavailable turns;
- safely query a dormant source without waking it;
- distinguish final decisions from superseded discussion;
- or prove that the transferred plan corresponds to the latest accepted source state.
This therefore needs a product/protocol mechanism rather than only additional system-prompt instructions.
Proposed mechanism
Introduce a persistent, immutable handoff artifact, tentatively named TaskHandoff, ContinuationPacket, or similar.
A handoff could contain:
{
"schema_version": "task-handoff/v1",
"source_thread_id": "...",
"source_revision": "...",
"source_turn_id": "...",
"created_at": "...",
"objective": "...",
"scope": {
"included": [],
"excluded": []
},
"approved_plan": [],
"completed_steps": [],
"pending_steps": [],
"prerequisites": [],
"decisions": [],
"constraints": [],
"known_failures": [],
"verification_evidence": [],
"next_action": "...",
"context_refs": [],
"authority": "inform_only",
"completeness": "authoritative_for_continuation"
}
The exact schema is flexible. The important properties are:
- bounded and structured;
- associated with an explicit source revision;
- distinguishable from raw conversation history;
- reviewable by the user;
- immutable once attached to a queued continuation;
- non-executing;
- and explicit about completeness and authority.
Safe production of the handoff
Creating or retrieving the handoff must not silently resume the source task.
Possible implementations include:
- materializing a handoff when a task reaches a stable stopping point;
- allowing the user to explicitly save or approve the current plan as a handoff;
- generating the handoff in an isolated summarization operation with no tools or mutation permissions;
- extracting it from a known completed source turn without creating a new turn in the source thread.
If the system cannot establish an authoritative plan, it should return a structured failure or ask the user. It should not infer that an incomplete transcript is the final plan.
Async dependency workflow
The handoff should be usable with queued execution:
Create continuation C from handoff A
Block C on prerequisite B
If B succeeds:
start C with the immutable handoff
If B fails or is cancelled:
keep C stopped and report the dependency failure
This would let users arrange multi-task work without requiring every task to stay active or know when unrelated prerequisite work finishes.
The source task remains dormant throughout.
Suggested acceptance criteria
- A user can create a bounded handoff from a completed or dormant task.
- Retrieving the handoff does not start a new turn in the source task.
- The receiving task does not inherit the complete source transcript or its historical execution authority.
- The handoff identifies the exact source revision or stopping point it represents.
- The user can preview or edit the handoff before using it.
- The receiving model can distinguish authoritative handoff fields from optional historical context.
- A continuation can be queued behind another task or operation.
- The continuation starts only after the declared prerequisite succeeds.
- Failure or cancellation of the prerequisite does not activate the continuation.
- The mechanism works independently of
notLoaded/idlestate, transcript pagination, compaction, and UI hydration. - Missing or ambiguous handoff state produces an explicit error instead of silent inference.
- Source and destination retain an auditable link without requiring the source task to resume.
Related issues
- #32547 — cross-thread delegation can silently wake a dormant thread and execute with stale context
- #36843 — typed, evidence-aware
CrossThreadEventproposal - #40014 — completed answer visible in the UI while
read_threadreturnsitems: [] - #30058 — undocumented
read_threadturn limit and required pagination - #37030 — model-visible history can diverge after cross-thread delegation
The proposal in #36843 provides a useful typed transport and provenance model. This request focuses on a specific higher-level artifact carried by such a transport: an authoritative, bounded, non-executing continuation plan for asynchronously ordered tasks.
Summary
The required semantic distinction is:
inspect another thread
!= resume another thread
!= inherit another thread
!= receive an approved task handoff
Codex currently has primitives for the first three behaviors, but not a dedicated representation of the fourth.
For asynchronous dependency-queued workflows, attempting to synthesize task handoff from read_thread, cross-thread messaging, and prompt guardrails is both unreliable and potentially unsafe. A first-class continuation artifact would make the intended workflow explicit, bounded, auditable, and non-executing.