Expose non-interrupt queued delivery for cross-thread send_message_to_thread

Open 💬 2 comments Opened Jun 29, 2026 by amatsuki5032

Feature request

Codex Desktop/App already has user-facing Queue vs Steer concepts, but the app/tool surface exposed to agents for cross-thread orchestration appears to only provide send_message_to_thread without an explicit delivery mode.

For parent/worker thread orchestration, we need a way for a worker thread to send a completion notice back to a parent thread without interrupting the parent thread's current turn. The desired behavior is:

  • delivery: "queued" or interrupt: false for send_message_to_thread / equivalent cross-thread send
  • the message is accepted immediately as pending input for the target thread
  • it is processed only after the target thread's current active turn completes
  • it should not be treated as turn/steer or an urgent interruption
  • it should be durable/visible enough that the parent does not need to poll child threads with read_thread
  • optionally expose status such as queued, delivered, canceled, failed

Why this matters

A common Codex workflow is a durable parent/router thread with multiple worker threads. Worker completion notices currently have two bad options:

  1. Use direct send_message_to_thread, which can interrupt or interleave with the parent thread's active reasoning and muddy decision-making.
  2. Do not send a notice and require the parent to poll/read worker threads, which is easy to miss and makes the workflow stall.

A non-interrupt queued cross-thread send would let workers report completion reliably while preserving the parent thread's current reasoning turn.

Related/adjacent issues found

  • #23615 Queue / Steer / Stash UX concepts
  • #23100 queued messages not processing until project focus
  • #14923 cross-thread orchestration over existing thread/turn primitives

Those are related, but the specific request here is an explicit non-interrupt delivery mode for cross-thread programmatic sends, suitable for agent/worker completion notices.

Suggested API shape

send_message_to_thread({
  threadId,
  prompt,
  delivery: "queued" // or interrupt: false
})

or app-server equivalent:

{
  "method": "thread/message/send",
  "params": {
    "threadId": "...",
    "input": [{"type":"text","text":"WORKER_NOTICE ..."}],
    "delivery": "queued"
  }
}

If an active turn exists, this should enqueue. If no active turn exists, it can start normally or remain queued depending on product semantics, but the delivery mode should be explicit and observable.

View original on GitHub ↗

2 Comments

devansh-jain-18 · 1 month ago

I strongly support this, especially for parent/worker thread workflows.

The important distinction for me is that cross-thread communication should not always mean steering the target thread. If a worker finishes while the parent/router thread is still actively reasoning or executing, I want the worker's completion report to be queued as the parent's next input, not injected into or interleaved with the active turn.

A useful shape would be a configurable delivery mode on cross-thread sends, for example:

  • delivery: "queued" / interrupt: false: enqueue for after the current active turn
  • delivery: "steer" / interrupt: true: urgent guidance for the current active turn
  • possibly a user or per-thread default so orchestrators can default worker reports to queue while still allowing explicit urgent steering

This would make multi-thread orchestration much calmer: workers can report completion reliably, but the parent thread keeps its current task boundary intact unless the sender explicitly chooses to interrupt.

michaelvd2 · 1 month ago

Non-interrupt queued delivery would help, but worker completion needs a slightly stronger app-server transaction to avoid both polling and duplicate/partial wake behavior.

Suggested scoped operation on the Desktop host that already owns the coordinator's app-server connection:

  1. Validate exact parent/worker lineage, a completion nonce, a compact terminal edge, and an existing report pointer.
  2. Append the completion through canonical thread history.
  3. Start exactly one normal coordinator turn.

The append and wake should be serialized per parent thread. Duplicate nonce is a no-op. Unknown lineage, oversized payload, busy/non-wakeable coordinator, or any failed precondition must append nothing and start no turn.

This cannot be safely emulated by attaching workers to the ChatGPT-owned stdio transport, launching a second app-server, separate thread/inject_items plus turn/start calls, rollout edits, direct steering, polling, a watcher, or a local queue: none can atomically target the already-running Desktop task with exactly-once semantics.

Useful acceptance fixtures: schema round-trip; valid append-plus-one-turn; duplicate nonce; wrong lineage; unknown thread; invalid/oversized payload; busy coordinator; rollback on precondition failure; and a Desktop-host integration proving one visible completion plus one coordinator turn on the owning connection. A negative fixture should show that a separately launched app-server cannot claim to wake the original Desktop task.