[Follow-up] Multi-Agent V2 needs verifiable full-profile application and lifecycle continuity for custom agents

Open 💬 9 comments Opened Jul 15, 2026 by zhang8630
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the Codex App are you using (From “About Codex” dialog)?

26.707.72221

What subscription do you have?

ChatGPT Pro

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64

What issue are you seeing?

Summary

This is a follow-up to #32782, not a duplicate of its initial role-selection request.

PR #32749 restores explicit model and reasoning_effort fields for Multi-Agent V2 spawns. Issue #32782 requests restoration of agent_type, or an equivalent configured-profile selector, so a parent can select a registered [agents.<role>] profile.

Those changes address two important launch-time problems:

  1. selecting a child model and reasoning effort;
  2. selecting a named custom-agent profile.

However, production multi-agent skills also need an end-to-end contract guaranteeing that the selected profile remains fully applied, observable, and stable for the complete child lifecycle.

A successful agent_type call is not sufficient if only the role label is retained while other profile layers are dropped, inherited from the parent, or changed during follow-up turns.

Production use case

I maintain a workflow skill in Codex Desktop with 10 registered Writer profiles:

  • 5 profiles use model_reasoning_effort = "max";
  • 5 profiles use model_reasoning_effort = "xhigh".

The profiles represent independent roles.

Each profile may carry:

  • role-specific developer instructions;
  • a configured model;
  • configured reasoning effort;
  • sandbox configuration;
  • role-specific tool permissions or allowlists;
  • a stable role identity used by the orchestration workflow.

The workflow depends on the selected profile being applied as one complete configuration unit. Manually passing only model and reasoning_effort cannot replace the profile because the role instructions and permissions are also material.

What #32749 solves

PR #32749 restores model-routing inputs to the Multi-Agent V2 spawn_agent schema:

model
reasoning_effort

This allows a generic child to be launched with an explicit model and reasoning level when using a compatible non-full-history fork.

However, it does not by itself select a registered [agents.<role>] profile.

What #32782 would solve

Issue #32782 requests:

agent_type

or an equivalent named-profile selector.

That would solve the initial selection boundary by allowing the parent to request a registered custom role instead of using task_name as a non-functional role label.

This is necessary and should be implemented.

Remaining contract needed after #32782

After a named profile is selected, Codex should guarantee all of the following.

1. Atomic full-profile application

The effective child configuration should apply the complete selected profile, including:

  • developer instructions;
  • model;
  • reasoning effort;
  • sandbox configuration;
  • tool permissions and allowlists supported by the profile;
  • profile/role identity.

The runtime must not apply only agent_role while silently inheriting the remaining settings from the parent.

2. Explicit precedence rules

Precedence should be deterministic and documented:

  1. values explicitly pinned by the selected role should win;
  2. when the role leaves a value unset, a valid spawn-time override should survive;
  3. otherwise, inheritance from the parent may apply.

Model and reasoning effort should be resolved independently. This is related to #32831.

3. Verifiable spawn receipt and metadata

The parent and user should be able to verify the effective configuration from runtime metadata rather than relying on the child’s self-report.

At minimum, the child record should expose:

agent_role
effective_model
effective_reasoning_effort
effective_sandbox
profile source or scope
parent_thread_id
multi_agent_version

If tool permissions cannot be displayed in full, the metadata should at least indicate that the selected role’s tool policy was applied.

4. No silent fallback

If the requested role is missing, invalid, unavailable, or incompatible with the selected fork mode, spawn_agent should return an explicit error.

It must not silently spawn a generic child with:

agent_role = null

or silently inherit the parent model while preserving a misleading role-like task name.

5. Follow-up continuity

followup_task or any equivalent continuation mechanism must preserve the child’s resolved role, model, reasoning effort, sandbox, developer instructions, and permissions.

A child initially created with one profile must not silently switch to the parent configuration during a later turn.

6. Deterministic lifecycle finalisation

Multi-Agent V2 should provide a documented and auditable way to finalise a completed or failed child.

V1 workflows previously exposed lifecycle operations such as close_agent. If V2 intentionally uses a different lifecycle model, it should provide an equivalent contract that guarantees:

  • terminal completion status;
  • deterministic resource/slot reclamation;
  • abnormal-child reporting;
  • no continued turns after finalisation;
  • an observable final state for orchestration logs.

interrupt_agent alone is not an obvious equivalent because interruption and final lifecycle closure have different meanings.

7. Desktop and CLI parity

The same profile-selection and lifecycle contract should work through:

  • Codex CLI;
  • Codex Desktop/app-server;
  • fresh sessions using the same supported configuration.

A profile should not work in CLI but silently degrade in Desktop.

Minimal custom-role example

# config.toml

[agents.english_reader]
description = "English reviewer"
config_file = "agents/english-reader.toml"
# agents/english-reader.toml

name = "english_reader"
model = "gpt-5.6-sol"
model_reasoning_effort = "max"
sandbox_mode = "read-only"

developer_instructions = """
Review one assigned novel scope and write the result to the specified
output file. Do not edit other scopes.
"""

Expected spawn shape:

{
  "agent_type": "english_reader",
  "task_name": "review_novel",
  "message": "Review the assigned visible-text snapshot.",
  "fork_turns": "none"
}

Expected result:

  • the configured role is selected;
  • all effective profile layers are applied;
  • the configuration is visible in child metadata;
  • follow-up turns retain the same configuration;
  • the child reaches a deterministic final lifecycle state.

Why this is distinct from existing reports

  • #31814 tracks forced inheritance and missing subagent routing controls.
  • #32749 restores model and reasoning_effort exposure.
  • #32782 requests the missing custom-agent selector.
  • #32831 tracks precedence when a selected role leaves model or reasoning unset.
  • #32988 tracks delivery of #32749 to the stable release.

This issue requests the remaining end-to-end contract: complete and verifiable profile application, continuity across later turns, explicit failure instead of silent fallback, and deterministic lifecycle finalisation.

Expected outcome

A production orchestration skill should be able to select a registered custom profile and prove that the same complete profile governed the child from spawn through finalisation.

What steps can reproduce the bug?

  1. Register a custom agent profile in C:\Users\<user>\.codex\config.toml:
[agents.english_reader]
description = "English reviewer"
config_file = "agents/english-reader.toml"
  1. Create the referenced role configuration:
name = "english_reader"
model = "gpt-5.6-sol"
model_reasoning_effort = "max"
sandbox_mode = "read-only"
developer_instructions = "Review one assigned document scope only."
  1. Fully restart Codex Desktop and start a fresh GPT-5.6 Sol / Multi-Agent V2 task.
  1. Ask the parent to spawn the registered english_reader role with no inherited history.
  1. Inspect the model-visible spawn_agent schema. In the affected session it exposes only:
task_name
message
fork_turns

It does not expose agent_type, profile_id, or another configured-role selector. PR #32749 may add model and reasoning_effort, but it does not add custom-profile selection.

  1. Using the profile name as task_name only labels the child task; it does not deterministically select the registered profile.
  1. Consequently, the parent cannot prove that the child loaded the profile’s developer instructions, configured reasoning effort, sandbox, and tool permissions.
  1. Inspect the available Multi-Agent V2 lifecycle tools. There is no exposed close_agent or clearly documented equivalent that provides deterministic finalisation and an auditable terminal state.

Expected:

  • spawn_agent accepts agent_type or profile_id;
  • the complete selected profile is applied;
  • effective role/model/effort/sandbox metadata is observable;
  • continuation turns retain the same configuration;
  • completed children have a deterministic final lifecycle state.

Actual:

  • the custom profile cannot be selected through the default V2 schema;
  • task_name is only a task label;
  • full-profile application and lifecycle finalisation cannot be verified.

The current default-session reproduction fails at the initial profile-selection boundary. The continuity and lifecycle requirements above are follow-on acceptance criteria for the end-to-end custom-agent contract once named selection is available; this report does not claim that every post-selection failure was independently reproduced in the same session.

What is the expected behavior?

Selecting a registered custom-agent profile should atomically apply the complete effective profile, including its role instructions, model, reasoning effort, sandbox and supported tool policy. The resolved configuration should remain stable across continuation turns, be observable in runtime metadata, fail explicitly instead of silently falling back, and reach a documented deterministic terminal lifecycle state.

Additional information

_No response_

View original on GitHub ↗

9 Comments

github-actions[bot] contributor · 1 month ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #32418

Powered by Codex Action

zhang8630 · 1 month ago

@jif-oai Thank you for working on the follow-up PR for custom subagent configuration.

Since this issue documents the requirements that may remain beyond exposing profile selection—particularly complete profile application, observable runtime metadata, continuation consistency, explicit failure instead of silent fallback, and deterministic lifecycle handling—I would greatly appreciate it if you could review #33314 when designing the follow-up implementation.

For reference, the GPT-5.5 / Multi-Agent V1 behavior already worked reliably for this use case: the orchestrator could select registered custom-agent roles and preserve role-specific delegation. It therefore provides a useful compatibility baseline. Ideally, Multi-Agent V2 should retain these deterministic V1 capabilities while adding the newer model-managed delegation features.

These guarantees are important for reproducible and high-stakes multi-agent workflows. Model-managed delegation can remain the default; the request here is for a reliable opt-in deterministic mode.

lonh-jing · 1 month ago

Additional macOS reproduction: role/model/effort apply, but the sandbox layer is replaced by the scheduled parent

I reproduced a narrower variant of the full-profile problem where custom-role selection succeeds and most of the profile is applied correctly, but the role's sandbox is not.

Environment
  • Codex Desktop: 26.707.72221 (build 5307)
  • Bundled/local Codex CLI: 0.144.3
  • macOS 26.2, arm64
  • Fresh local scheduled automation rooted in a trusted project
  • Parent: gpt-5.6-sol, reasoning max, Multi-Agent V2
  • Child spawns used the registered agent_type and fork_turns: "none"
Sanitized configuration

The project-local .codex/config.toml requested:

sandbox_mode = "workspace-write"
approval_policy = "never"

[sandbox_workspace_write]
network_access = true
# Two explicit non-project writable roots; paths omitted.

The registered custom reviewer profile requested:

name = "expression_reviewer_luna"
model = "gpt-5.6-luna"
model_reasoning_effort = "max"
sandbox_mode = "read-only"
developer_instructions = """
Read-only review role. Do not modify inputs or runtime state.
"""
Reproduction
  1. Start the scheduled automation as a fresh root task.
  2. Spawn three fresh children with the exact registered agent_type, canonical task names, and fork_turns: "none".
  3. Send only fixed calibration records and explicitly forbid tool use.
  4. Inspect saved runtime metadata rather than relying on child self-report.
Observed runtime metadata

The scheduled parent first turn resolved to:

model = gpt-5.6-sol
reasoning_effort = max
sandbox = danger-full-access
approval_policy = never
permission_profile = disabled

All three children independently recorded:

agent_role = expression_reviewer_luna
model = gpt-5.6-luna
reasoning_effort = max
multi_agent_version = v2
tool_call_count = 0
sandbox = danger-full-access

This is distinct from the missing-agent_type / generic-child case:

  • the registered role was selected;
  • the role-specific model was applied;
  • the role-specific reasoning effort was applied;
  • the role identity was present;
  • only the configured sandbox_mode = "read-only" was replaced by the parent's live danger-full-access policy.

The result was deterministic across all three fresh children.

Expected behavior

Either:

  1. an explicitly pinned custom-role sandbox should narrow the child to read-only; or
  2. if a parent live override is intentionally required to win, the precedence should be explicit and the spawn receipt should report that the selected profile was only partially applied before the child begins work.

For high-assurance workflows, silent widening is not safe. This run used a fail-closed runtime gate, so it stopped before sending production review chunks and performed no database write.

Relation to other reports

This looks like two policy layers interacting:

  • Automation/root policy resolution: the scheduled parent started as danger-full-access despite the project-local workspace-write policy, related to #15310.
  • Custom-agent profile application: the selected role's sandbox did not narrow the child even though its role/model/effort did apply, which directly supports this issue's atomic full-profile and verifiable effective-sandbox requirements.

Thread IDs, local usernames, private paths, hosts, and application data are intentionally omitted.

sunjiajunsunjiajun · 1 month ago

I also have a concrete need for this end-to-end contract around subagent effective configuration.

The issue I am seeing is not just whether a role/profile can be selected. A parent agent can be granted Full Access and report that permissions were updated, but when it dispatches a subagent, the child does not seem to carry the same effective permission state. The result is that delegated work behaves as if it is still under a stale or more restricted sandbox/approval context.

This makes it hard to trust multi-agent orchestration: the parent’s visible permission state says one thing, but the spawned child’s actual ability to act says another. It would be very helpful if spawned subagents exposed verifiable metadata for their effective sandbox/approval/tool permissions and if the runtime guaranteed that permission updates applied to the parent are either inherited by children or explicitly rejected with a clear explanation.

zhang8630 · 1 month ago
I also have a concrete need for this end-to-end contract around subagent effective configuration. The issue I am seeing is not just whether a role/profile can be selected. A parent agent can be granted Full Access and report that permissions were updated, but when it dispatches a subagent, the child does not seem to carry the same effective permission state. The result is that delegated work behaves as if it is still under a stale or more restricted sandbox/approval context. This makes it hard to trust multi-agent orchestration: the parent’s visible permission state says one thing, but the spawned child’s actual ability to act says another. It would be very helpful if spawned subagents exposed verifiable metadata for their effective sandbox/approval/tool permissions and if the runtime guaranteed that permission updates applied to the parent are either inherited by children or explicitly rejected with a clear explanation.

Thank you for adding this concrete reproduction. This is an important complementary case and further demonstrates why the effective child configuration needs an end-to-end, verifiable contract.

We now appear to have evidence of permission divergence in both directions:

  • a custom role requesting read-only may be silently widened by the parent/runtime policy;
  • as reported here, a parent granted Full Access may spawn a child that silently retains a stale or more restrictive sandbox/approval state.

The desired behavior should not necessarily be unconditional inheritance. A role explicitly pinned to read-only should remain narrowed for safety. However, the precedence must be deterministic:

  1. An explicitly pinned role permission should be honored.
  2. If the role leaves a permission unset, the parent’s current effective permission state should be inherited where supported.
  3. If the requested combination cannot be applied, spawning should fail explicitly or report the incompatibility before the child begins work.
  4. The spawn receipt should expose the child’s effective role, sandbox, approval policy, and supported tool policy.
  5. The same resolved configuration should remain stable across continuation turns, without silent widening, narrowing, or reversion to stale state.

@jif-oai, could the upcoming role/configuration follow-up please address this permission-propagation case together with the main requirements in #33314: complete profile application, observable effective metadata, explicit precedence, no silent fallback, continuation consistency, and deterministic lifecycle finalisation?

Restoring role selection is the essential first step, but these reports show that reliable role selection also needs a trustworthy effective-permission contract. Thank you again for looking into this.

zhang8630 · 1 month ago
### What version of the Codex App are you using (From “About Codex” dialog)? 26.707.72221 ### What subscription do you have? ChatGPT Pro ### What platform is your computer? Microsoft Windows NT 10.0.26200.0 x64 ### What issue are you seeing? ## Summary This is a follow-up to #32782, not a duplicate of its initial role-selection request. PR #32749 restores explicit model and reasoning_effort fields for Multi-Agent V2 spawns. Issue #32782 requests restoration of agent_type, or an equivalent configured-profile selector, so a parent can select a registered [agents.<role>] profile. Those changes address two important launch-time problems: 1. selecting a child model and reasoning effort; 2. selecting a named custom-agent profile. However, production multi-agent skills also need an end-to-end contract guaranteeing that the selected profile remains fully applied, observable, and stable for the complete child lifecycle. A successful agent_type call is not sufficient if only the role label is retained while other profile layers are dropped, inherited from the parent, or changed during follow-up turns. ## Production use case I maintain a workflow skill in Codex Desktop with 10 registered Writer profiles: 5 profiles use model_reasoning_effort = "max"; 5 profiles use model_reasoning_effort = "xhigh". The profiles represent independent roles. Each profile may carry: role-specific developer instructions; a configured model; configured reasoning effort; sandbox configuration; role-specific tool permissions or allowlists; a stable role identity used by the orchestration workflow. The workflow depends on the selected profile being applied as one complete configuration unit. Manually passing only model and reasoning_effort cannot replace the profile because the role instructions and permissions are also material. ## What #32749 solves PR #32749 restores model-routing inputs to the Multi-Agent V2 spawn_agent schema: `` model reasoning_effort ` This allows a generic child to be launched with an explicit model and reasoning level when using a compatible non-full-history fork. However, it does not by itself select a registered [agents.<role>] profile. ## What [#32782](https://github.com/openai/codex/issues/32782) would solve Issue [#32782](https://github.com/openai/codex/issues/32782) requests: ` agent_type ` or an equivalent named-profile selector. That would solve the initial selection boundary by allowing the parent to request a registered custom role instead of using task_name as a non-functional role label. This is necessary and should be implemented. ## Remaining contract needed after [#32782](https://github.com/openai/codex/issues/32782) After a named profile is selected, Codex should guarantee all of the following. ### 1. Atomic full-profile application The effective child configuration should apply the complete selected profile, including: * developer instructions; * model; * reasoning effort; * sandbox configuration; * tool permissions and allowlists supported by the profile; * profile/role identity. The runtime must not apply only agent_role while silently inheriting the remaining settings from the parent. ### 2. Explicit precedence rules Precedence should be deterministic and documented: 1. values explicitly pinned by the selected role should win; 2. when the role leaves a value unset, a valid spawn-time override should survive; 3. otherwise, inheritance from the parent may apply. Model and reasoning effort should be resolved independently. This is related to [#32831](https://github.com/openai/codex/issues/32831). ### 3. Verifiable spawn receipt and metadata The parent and user should be able to verify the effective configuration from runtime metadata rather than relying on the child’s self-report. At minimum, the child record should expose: ` agent_role effective_model effective_reasoning_effort effective_sandbox profile source or scope parent_thread_id multi_agent_version ` If tool permissions cannot be displayed in full, the metadata should at least indicate that the selected role’s tool policy was applied. ### 4. No silent fallback If the requested role is missing, invalid, unavailable, or incompatible with the selected fork mode, spawn_agent should return an explicit error. It must not silently spawn a generic child with: ` agent_role = null ` or silently inherit the parent model while preserving a misleading role-like task name. ### 5. Follow-up continuity followup_task or any equivalent continuation mechanism must preserve the child’s resolved role, model, reasoning effort, sandbox, developer instructions, and permissions. A child initially created with one profile must not silently switch to the parent configuration during a later turn. ### 6. Deterministic lifecycle finalisation Multi-Agent V2 should provide a documented and auditable way to finalise a completed or failed child. V1 workflows previously exposed lifecycle operations such as close_agent. If V2 intentionally uses a different lifecycle model, it should provide an equivalent contract that guarantees: * terminal completion status; * deterministic resource/slot reclamation; * abnormal-child reporting; * no continued turns after finalisation; * an observable final state for orchestration logs. interrupt_agent alone is not an obvious equivalent because interruption and final lifecycle closure have different meanings. ### 7. Desktop and CLI parity The same profile-selection and lifecycle contract should work through: * Codex CLI; * Codex Desktop/app-server; * fresh sessions using the same supported configuration. A profile should not work in CLI but silently degrade in Desktop. ## Minimal custom-role example # config.toml [agents.english_reader] description = "English reviewer" config_file = "agents/english-reader.toml" # agents/english-reader.toml name = "english_reader" model = "gpt-5.6-sol" model_reasoning_effort = "max" sandbox_mode = "read-only" developer_instructions = """ Review one assigned novel scope and write the result to the specified output file. Do not edit other scopes. """ Expected spawn shape: { "agent_type": "english_reader", "task_name": "review_novel", "message": "Review the assigned visible-text snapshot.", "fork_turns": "none" } Expected result: * the configured role is selected; * all effective profile layers are applied; * the configuration is visible in child metadata; * follow-up turns retain the same configuration; * the child reaches a deterministic final lifecycle state. ## Why this is distinct from existing reports * [GPT-5.6 Sol cannot specify subagent models, forcing all subagents to also be Sol instances #31814](https://github.com/openai/codex/issues/31814) tracks forced inheritance and missing subagent routing controls. * [Expose model overrides for multi-agent v2 spawns #32749](https://github.com/openai/codex/pull/32749) restores model and reasoning_effort exposure. * [GPT-5.6 Sol root exposes spawn_agent without agent_type, blocking custom agent routing #32782](https://github.com/openai/codex/issues/32782) requests the missing custom-agent selector. * [Custom agent roles discard explicit spawn model/reasoning when the role leaves them unset #32831](https://github.com/openai/codex/issues/32831) tracks precedence when a selected role leaves model or reasoning unset. * [[Release blocker] Backport #32749: stable Codex breaks model-routed subagent plugins #32988](https://github.com/openai/codex/issues/32988) tracks delivery of [Expose model overrides for multi-agent v2 spawns #32749](https://github.com/openai/codex/pull/32749) to the stable release. This issue requests the remaining end-to-end contract: complete and verifiable profile application, continuity across later turns, explicit failure instead of silent fallback, and deterministic lifecycle finalisation. ## Expected outcome A production orchestration skill should be able to select a registered custom profile and prove that the same complete profile governed the child from spawn through finalisation. ### What steps can reproduce the bug? 1. Register a custom agent profile in C:\Users\<user>\.codex\config.toml: [agents.english_reader] description = "English reviewer" config_file = "agents/english-reader.toml" 2. Create the referenced role configuration: name = "english_reader" model = "gpt-5.6-sol" model_reasoning_effort = "max" sandbox_mode = "read-only" developer_instructions = "Review one assigned document scope only." 3. Fully restart Codex Desktop and start a fresh GPT-5.6 Sol / Multi-Agent V2 task. 4. Ask the parent to spawn the registered english_reader role with no inherited history. 5. Inspect the model-visible spawn_agent schema. In the affected session it exposes only: ` task_name message fork_turns ` It does not expose agent_type, profile_id, or another configured-role selector. PR [#32749](https://github.com/openai/codex/pull/32749) may add model and reasoning_effort, but it does not add custom-profile selection. 6. Using the profile name as task_name only labels the child task; it does not deterministically select the registered profile. 7. Consequently, the parent cannot prove that the child loaded the profile’s developer instructions, configured reasoning effort, sandbox, and tool permissions. 8. Inspect the available Multi-Agent V2 lifecycle tools. There is no exposed close_agent or clearly documented equivalent that provides deterministic finalisation and an auditable terminal state. Expected: * spawn_agent accepts agent_type or profile_id; * the complete selected profile is applied; * effective role/model/effort/sandbox metadata is observable; * continuation turns retain the same configuration; * completed children have a deterministic final lifecycle state. Actual: * the custom profile cannot be selected through the default V2 schema; * task_name` is only a task label; * full-profile application and lifecycle finalisation cannot be verified. The current default-session reproduction fails at the initial profile-selection boundary. The continuity and lifecycle requirements above are follow-on acceptance criteria for the end-to-end custom-agent contract once named selection is available; this report does not claim that every post-selection failure was independently reproduced in the same session. ### What is the expected behavior? Selecting a registered custom-agent profile should atomically apply the complete effective profile, including its role instructions, model, reasoning effort, sandbox and supported tool policy. The resolved configuration should remain stable across continuation turns, be observable in runtime metadata, fail explicitly instead of silently falling back, and reach a documented deterministic terminal lifecycle state. ### Additional information _No response_

Update: custom-role selection and model/reasoning routing now work, but three isolation gaps remain

@jif-oai, Thank you for the recent Multi-Agent V2 improvements. I retested this issue in a fresh Codex Desktop session on Windows.

Environment

  • Codex Desktop: 26.715.9868.0
  • Bundled CLI: 0.145.0-alpha.30
  • OS: Windows x64
  • Multi-Agent version: v2
  • Test method: fresh session, custom role selected through agent_type
  • The spawn request did not explicitly pass model, reasoning effort, sandbox mode, or tool permissions.

What now works

The following parts are now working in my testing:

  1. agent_type is exposed and accepted by the V2 spawn interface.
  2. A registered custom role is genuinely selected rather than silently becoming a generic worker.
  3. The child rollout records the expected agent_role.
  4. fork_turns: "none" works.
  5. The model declared in the role TOML is applied:
  • Expected: gpt-5.6-sol
  • Effective: gpt-5.6-sol
  1. The role-specific reasoning effort is also applied without an explicit spawn override:
  • Expected: max
  • Effective effort: max
  • Effective collaboration_mode.reasoning_effort: max
  1. The child session now provides enough metadata to verify the selected role, model, reasoning effort, Multi-Agent version, and parent-child relationship.

These are meaningful improvements and resolve the original role-selection and model/reasoning-routing problems in my environment.

Three remaining issues

1. The role-specific sandbox is still overwritten by the parent runtime profile

The role TOML requested:

  • sandbox_mode = "workspace-write"

However, the child actually received:

  • sandbox_policy = {"type":"danger-full-access"}
  • permission_profile = {"type":"disabled"}
  • approval_policy = "never"

The child successfully created a file outside the workspace. Therefore, the role-specific sandbox was not applied.

This appears consistent with the macOS reproduction already reported in this issue: an explicitly configured child sandbox is replaced by the parent session’s effective permission profile.

2. Role-specific tool permissions are still not enforced as a runtime boundary

The tested role was not intended to have web access, but the child retained the hosted web-search tool and successfully performed a search.

A role-local PreToolUse Hook was configured, but no corresponding Hook record was produced during the child run. Therefore, I cannot treat the Hook configuration as an authoritative permission boundary.

The current result is that model and reasoning settings are role-specific, while the effective tool surface is still inherited from the parent session.

3. Documents/Word/DOCX capability isolation is still not enforceable or verifiable

Some of my roles require the dedicated Documents/Word capability, while many read-only review roles must not receive it.

At present, I cannot define and verify a role-level capability boundary that:

  • exposes Documents/DOCX tools only to roles that require them;
  • removes those tools from other roles;
  • prevents equivalent DOCX access through allowed shell tools; and
  • records the effective document capability in the child runtime metadata.

This DOCX capability was not exercised destructively in the probe, but the child still received the shared parent tool surface and no effective capability receipt showed that document access had been removed.

Evidence summary

Role configuration:

  • Role: editor
  • Model: gpt-5.6-sol
  • Reasoning effort: max
  • Sandbox: workspace-write

Effective child runtime:

  • agent_role: correct
  • multi_agent_version: v2
  • model: gpt-5.6-sol
  • effort: max
  • collaboration_mode.reasoning_effort: max
  • sandbox_policy: danger-full-access
  • permission_profile: disabled
  • Outside-workspace write: succeeded
  • Web search: succeeded
  • Role Hook record: not found

Therefore, I would describe #33314 as partially resolved, but not fully resolved.

The role-selection, model-routing, and reasoning-effort parts now work. The remaining problem is that the rest of the role profile is not applied atomically: sandbox, tool permissions, and Documents/DOCX capability restrictions do not currently form a verifiable per-role runtime boundary.

I did not retest follow-up continuity or deterministic lifecycle finalisation in this particular probe, so this update is limited to the verified profile-application results above.

@jif-oai, could you please review these three remaining isolation issues?

The expected behavior would be:

  1. An explicitly pinned role sandbox should override a broader parent sandbox, or spawning should fail with a clear incompatibility error.
  2. Role-specific tool and capability policies should be enforceable at runtime, including hosted tools.
  3. The child rollout should record the effective sandbox, tool policy, and Documents/DOCX capability so partial profile application cannot happen silently.

Thank you again for the progress on Multi-Agent V2.

ABSniper · 1 month ago

Additional clean-room audit use case and acceptance criteria

The remaining sandbox/tool-policy gaps also block a security-sensitive audit pattern: launching a fresh contradictory reviewer that must not discover or read prior-pass results.

fork_turns: "none" removes inherited conversation turns, but it is not a complete clean-room boundary when the child still inherits the parent's filesystem view and hosted/local tool surface. A child can still discover prior outputs through shell/file tools, project-wide search, agent inventories, browser/app connectors, or other inherited capabilities.

A minimal runtime contract that would make this use case enforceable is:

  1. Opaque, pre-registered launch profile
  • spawn_agent accepts a host-resolved identifier such as launch_profile_id or capability_profile_id.
  • The caller cannot submit arbitrary permissions inside the spawn payload.
  • Missing, unapproved, stale, or incompatible profiles fail explicitly; there is no generic-agent fallback.
  1. Atomic final application before child creation
  • Resolve and revalidate the profile after parent inheritance, role application, and spawn-time overrides.
  • Freeze the effective sandbox, filesystem view, tool registry, network/app access, and environment policy before the child thread and first turn become runnable.
  • A broader parent permission profile must not overwrite or widen a restrictive child profile.
  1. Constrained filesystem view
  • Allow approved source/ticket roots through a read-only mounted or brokered view.
  • Exclude prior audit outputs, pass reports, conversation artifacts, and unrelated project history.
  • Prevent traversal, symlink escape, alternate tool access, and equivalent access through shell commands.
  1. Exact capability allowlist
  • Expose only the tools registered by the selected profile.
  • Hosted web search, browser/computer use, MCP/apps/connectors, shell, patch/edit tools, multi-agent tools, and network access are absent unless explicitly allowed.
  • Denial should occur at runtime authorization, not only through prompt instructions or a child-local hook.
  1. Host-issued effective-surface receipt
  • The spawn result should include agent_id plus an attributable receipt or digest proving the effective profile.
  • Useful fields would include profile id/version/hash, effective sandbox, filesystem-view digest, allowed-tool/capability digest, external-access flags, and parent-child identity.
  • The receipt must come from the host/runtime, not from child self-report.
  1. Lifecycle and update continuity
  • Follow-up turns preserve the same frozen capability profile.
  • If a later Codex version does not support or cannot verify the requested profile contract, launch fails closed instead of silently degrading to a generic or broader-permission child.

Suggested negative acceptance tests:

  • A prior-pass output path is not discoverable or readable.
  • An undeclared hosted or local tool is absent or denied.
  • A permissive parent cannot widen the child after profile application.
  • A missing/stale profile cannot launch a same-named generic child.
  • The returned receipt matches the actual runtime surface and remains stable across follow-ups.

This is broader than selecting agent_type: it is a host-enforced, verifiable child capability boundary. It would support independent audits, untrusted-input review, least-privilege workers, and other workflows where prompt-only role separation is insufficient.

SmixNZL · 27 days ago

Additional macOS CLI 0.146.0 reproduction: explicit read-only parent, custom children report workspace-write

I reproduced the remaining sandbox/profile problem on a newer stable CLI, this time beneath an explicitly read-only parent rather than a permissive scheduled or Desktop parent.

Environment

  • Codex CLI: 0.146.0
  • Platform: macOS, Apple Silicon
  • Authentication: ChatGPT login; OPENAI_API_KEY was unset before launch
  • Project-local custom roles: reviewer and release_steward
  • Both role TOMLs declare sandbox_mode = "read-only"

Parent launch

codex --strict-config -s read-only -a never \
  -m gpt-5.6-sol -c 'model_reasoning_effort="high"'

No live sandbox override, approval, escalation, or later permission change occurred after launch.

Reproduction

  1. Start the parent with the exact command above.
  2. Through the native subagent interface, dispatch only the registered reviewer role with an explicit requested model/effort.
  3. Independently dispatch only the registered release_steward role with an explicit requested model/effort.
  4. Require each child to inspect and report its effective sandbox before doing any work, and stop on any value other than read-only.

Requested routes in this run were:

  • reviewer: GPT-5.6 Sol, xhigh
  • release steward: GPT-5.6 Sol, high

Actual result

Both children independently reported:

effective child sandbox = workspace-write

This occurred even though:

  • the parent was launched with the live CLI override -s read-only;
  • both selected custom roles declare sandbox_mode = "read-only";
  • no permission change or approval occurred.

The fail-closed prompt stopped both children immediately. No write probe was attempted under this explicit-read-only parent, so this reproduction does not claim to distinguish an enforcement defect from a runtime-metadata/reporting defect. Either result is blocking for least-privilege orchestration: the parent cannot attest that the child is read-only.

The same run also could not reliably attest the actual child model and reasoning effort from runtime metadata. One child could not expose either value; the other reported only a generic GPT-5 family label. Requested routing is therefore recorded above as requested, not proven effective routing.

Earlier enforcement observation

In a preceding CLI canary with a workspace-write parent, a selected custom explorer role declared sandbox_mode = "read-only" but successfully created the exact workspace probe it had been instructed to attempt. The probe was a zero-byte file and was removed immediately; no residue remained.

That earlier result may reflect documented parent live-policy precedence rather than the explicit-read-only-parent case above. I include it only because it demonstrates why a host-issued effective-sandbox receipt is necessary: the child declaration alone did not match its write capability.

Expected behavior

For a parent launched with -s read-only -a never, a spawned custom child should either:

  1. run under an effective read-only sandbox and expose that fact in host/runtime metadata; or
  2. fail to spawn with an explicit incompatibility error.

It should not report a broader workspace-write policy. The spawn receipt should also expose the actual effective child model and reasoning effort, separately from requested values and child self-report.

Local usernames, private project details, absolute paths, task contents, and session identifiers are intentionally omitted.

dyjagger · 25 days ago

Additional Linux/WSL reproduction: lifecycle observers cannot join dispatch to the selected custom role

I reproduced the missing custom-role contract from a privacy-minimized lifecycle observer on:

  • Codex CLI 0.146.0
  • Linux/WSL2 x86_64
  • Multi-agent collaboration tool path exposed to the current Codex session

The current collaboration.spawn_agent schema exposed task_name, message, fork_turns, model, and reasoning_effort, but no agent_type, agent_role, profile_id, or equivalent custom-profile selector.

Using a configured custom-agent name as task_name produced a model-visible result containing only a canonical task path. It did not expose the child agent_id or selected role/profile. The corresponding SubagentStart hook supplied the correct child agent_id, but agent_type was generic; the child runtime metadata independently recorded agent_role: null.

There was also no PostToolUse event for collaboration.spawn_agent, despite trusted matchers covering Agent, spawn_agent, and namespaced variants. In the same session, PostToolUse for update_plan and SubagentStart/SubagentStop fired normally. This is consistent with the documented caveat that specialized tool paths may opt out of the ordinary tool-hook path.

This leaves no stable, authoritative join between:

configured custom profile -> requested dispatch role -> child lifecycle identity

A local observer cannot safely infer that join from task_name, FIFO order, or timing when multiple children overlap. It also should not parse transcript bodies: the transcript format is not a stable hook interface and doing so would unnecessarily expand privacy exposure.

The smallest privacy-safe contract that would resolve this case is either:

  1. spawn_agent accepts a validated custom profile selector and returns structured {agent_id, task_name, agent_type}; or
  2. a reliable dispatch/PostToolUse lifecycle event supplies the same stable agent_id and selected role later emitted by SubagentStart and SubagentStop.

No prompt, task message, transcript body, command, source, or tool-output body is needed. Stable IDs and bounded role/task labels are sufficient.

This was reproduced across three independent custom-role-shaped tasks. The observer therefore reports configured roles as standby and generic lifecycle agents as role unavailable rather than claiming that a custom profile was active.