openai / openai/codex

MultiAgentV2 followup_task can run a new assignment under a stale canonical task name

Open
#45,210 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug subagent
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

What happens

followup_task can reactivate a completed child agent for an unrelated logical task while retaining the original canonical task name and context. The task tree and UI then show the old name even though the agent is doing different work, so ownership and scope are no longer observable from the agent identity.

Reproduction

On Codex 0.153.1:

  1. Spawn a child with task_name: old_scope and let it complete.
  2. Call followup_task on old_scope with an unrelated task.
  3. Observe that the call succeeds and the child runs again under old_scope; there is no declared current-scope field to validate or display.

This happened in a live multi-agent session: a completed agent named for one narrow task was reused for two unrelated design/review assignments, but list_agents and the UI continued to expose only the original name.

Source boundary

FollowupTaskArgs currently contains only target and message. The message is marked encrypted in the model-facing tool schema, so a local PreToolUse hook cannot reliably compare the new task semantics with the target's currently registered task name. The handler resolves the existing target and sends the communication without any declared-scope check.

Expected contract

Treat the user-visible unit of work as an assignment, independently of whether the runtime allocates a new resident thread.

  • Every assignment has a stable assignment identity/generation and canonical task name for its lifetime. The current effective assignment identity is exposed consistently by list_agents, the UI, activity events, and audit output.
  • followup_task is same-assignment continuation. It carries the expected assignment identity/generation, and dispatch atomically verifies that it is still current. A stale or mismatched request is rejected with a machine-readable receipt before resident/thread load, message delivery, wake-up, or assignment/context mutation.
  • Unrelated work starts a new assignment with a fresh validated task name and a new identity/generation. It does not inherit context from the previous child assignment; parent history inheritance or explicit handoff is determined by the new spawn/retask request. A new thread is valid, but an implementation may instead atomically retask a fully quiescent terminal resident; it must not retain or display the previous assignment's name or implicit context.
  • No turn or queued communication from the previous assignment may cross the assignment-generation boundary, and concurrent follow-up/retask attempts must be linearizable.

The runtime cannot infer semantic relatedness from the encrypted free-text message. The enforceable boundary is the caller's explicit choice between continuing the current assignment and starting a new one, plus an atomic generation check.

Suggested regression tests:

  1. A matching same-assignment follow-up succeeds, including after completion when continuation is intended.
  2. A stale or mismatched assignment generation rejects without resident/thread load, delivery, wake-up, or assignment/context mutation.
  3. Starting unrelated work creates a new visible assignment name and generation without previous child-assignment context, whether backed by a fresh thread or an explicit retask operation; configured parent-history inheritance or explicit handoff remains allowed.
  4. Concurrent follow-up and retask calls cannot deliver old-assignment work into the new generation.
  5. The invariants survive unload/reload and terminal outcomes including completed, failed, and interrupted.

A blanket local ban on all follow-ups to terminal agents would hide this bug but would also break valid same-task continuation. Semantic inspection of message is not a viable hook workaround because that field is encrypted before hooks receive the tool call.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with FollowupTaskArgs and the followup_task handler, then trace target resolution, delivery, resident loading, and assignment identity handling. Add regression coverage for matching, stale, unrelated, concurrent, and unload/reload cases, verifying stale requests are rejected before side effects and visible assignment names and generations remain consistent.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend, distributed-systems
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.