Tool-backed sessions cannot prove active root model and reasoning effort

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

Summary

A tool-backed Codex session cannot expose authoritative, parent-visible metadata proving the effective model and reasoning effort of the active root thread.

This makes fail-closed multi-agent orchestration impossible when a workflow requires an exact root model/effort before spawning custom agents. A project config can describe the intended model, but it does not prove what the already-running root thread is actually using.

In my case this caused five restart/preflight loops since the previous evening.

Environment

  • Surface: tool-backed Codex session / collaboration tools
  • Codex CLI: 0.144.5
  • OS: macOS 26.5.2
  • Architecture: arm64
  • Multi-agent enabled
  • Intended root: gpt-5.6-sol / high
  • Project-scoped custom agents under .codex/agents/*.toml

Minimal configuration

# .codex/config.toml
model = "gpt-5.6-sol"
model_reasoning_effort = "high"

[agents]
max_threads = 4
max_depth = 1
interrupt_message = true

Custom agent profiles parse correctly and specify role-specific model, effort, sandbox, and developer instructions.

Reproduction

  1. Create the project config above.
  2. Add valid project-scoped custom agent TOMLs under .codex/agents/.
  3. Start a tool-backed Codex session in the trusted project.
  4. Require the root orchestrator to prove that the active thread is gpt-5.6-sol/high before spawning agents.
  5. Run:
$ codex doctor --json

Relevant result:

{
  "config.load": {
    "status": "ok",
    "details": {
      "model": "gpt-5.6-sol",
      "model provider": "openai"
    }
  }
}

The report does not expose the active thread's effective reasoning effort, nor does it prove that the already-running thread was created from the currently loaded project config.

  1. Run:
$ codex debug prompt-input "probe custom agent discovery"

This renders model-visible prompt messages. It does not provide an authoritative runtime receipt for root model/effort or a discovery result for project-scoped agent profiles.

  1. Inspect the tool-backed collaboration surface:

spawn_agent exposes only:

  • task_name
  • message
  • fork_turns

list_agents exposes path/status/task data, but not the effective role, model, reasoning effort, sandbox, or profile provenance.

Actual behavior

The orchestrator can prove:

  • the TOML parses;
  • the requested models exist in the bundled catalog;
  • the project is trusted;
  • the configuration says gpt-5.6-sol/high.

It cannot prove:

  • the active root thread is actually using that model and effort;
  • which configuration layer produced the active root;
  • whether project-scoped custom profiles are discoverable through the current tool-backed spawn surface;
  • the effective role/model/effort/sandbox of a spawned child.

A fail-closed workflow therefore has two bad options:

  1. stop and request another restart indefinitely;
  2. trust configuration intent as if it were runtime evidence.

Expected behavior

Expose a canonical runtime receipt for the active root thread, available to the parent and diagnostic tooling:

thread_id
effective_model_provider
effective_model
effective_reasoning_effort
effective_sandbox
config_provenance
project_config_loaded
custom_agent_profiles_discovered
multi_agent_version

For child spawns, return the resolved profile plus effective model/effort/sandbox, and fail explicitly when the requested profile cannot be selected.

codex doctor --json should clearly distinguish:

  • configuration intent;
  • active runtime state;
  • values that cannot be verified.

Why this is operationally significant

Model/effort and sandbox selection are not cosmetic in an orchestrated workflow. They can be hard gates for:

  • read-only versus writer roles;
  • independent verification;
  • cost/latency allocation;
  • audit trails;
  • preventing silent fallback;
  • deciding whether implementation is authorized to start.

Without authoritative runtime metadata, strict orchestration specs become restart loops rather than executable controls.

Related issues

  • #32291 — tool-backed Desktop cannot select named custom agents
  • #32504 — canonical subagent activity omits effective identity/model/effort
  • #33314 — full-profile application and lifecycle continuity
  • #28113 — reasoning effort startup behavior

This report is specifically about root-thread runtime observability and preflight proof, before the first child is spawned.

View original on GitHub ↗

3 Comments

github-actions[bot] contributor · 1 month ago

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

  • #33314
  • #33244
  • #33092
  • #32703

Powered by Codex Action

PaulRBerg · 1 month ago

+1. A concrete use case beyond orchestration is conditional instructions keyed on reasoning effort. I want to say something like "when Ultra is active, do X; otherwise don't" and have Codex evaluate that against the effective runtime state.

That requires the active agent to receive an authoritative effective_reasoning_effort, not just have it available to the client UI or diagnostics. Today it can't reliably know whether Ultra is actually set, so those conditional instructions aren't enforceable.

vmffl1213-alt · 19 days ago

Additional current reproduction and concrete additive contract

I reproduced the remaining observability gap on a current Windows Codex
Desktop installation:

  • Codex Desktop package: 26.803.5235.0
  • bundled/active Codex CLI: 0.146.0
  • current spawn_agent request schema accepts explicit model and

reasoning_effort

  • the accepted tool result exposes only agent_id and nickname
  • there is still no parent-visible authoritative Root receipt or effective

child profile receipt

This means explicit profile selection has improved, but a fail-closed router
still cannot distinguish requested, accepted, and effective profiles. Config
text and child self-report are not sufficient because neither proves the
runtime-selected profile or a fallback.

Minimal additive seam

The following three interfaces would keep existing callers compatible:

  1. get_root_profile_receipt() returns the current request/thread's effective

model, reasoning effort, precedence source, user-lock state, Host proof,
and freshness interval.

  1. spawn_agent() preserves agent_id and nickname and additively returns

routing_request_id plus an accepted_profile_receipt containing the
accepted model and effort.

  1. get_agent_profile_receipt(agent_id, routing_request_id) returns the

effective model, effort, explicit nullable fallback reason, Host proof, and
freshness interval after child startup.

Required semantics:

  • bind every receipt to the exact request and, for child receipts, agent ID;
  • validate in the fixed order Root receipt -> plan -> accepted receipt ->

effective receipt;

  • expose silent substitution as an explicit fallback, never as a matching

receipt;

  • on accepted/effective mismatch, stale proof, reported fallback, or a bounded

effective-receipt timeout, close the child and let Root continue;

  • do not retry with another model after a mismatch or timeout;
  • keep receipt fields additive so clients that only consume agent_id and

nickname continue to work.

An optional Host/UI-only escape hatch for receipt-unavailable parallel work
should not be agent-mintable. The Host can inject a current-request grant with
a one-use batch nonce and bounded child count, consume it atomically for one
batch, reject replay/cross-request use, and label the result unverified rather
than counting it as successful model routing.

This extends the root observability requested here and the verifiable child
profile requirement in #33314 without requiring model-routing policy to live
inside Codex. The Host would own runtime truth and nonce consumption; callers
would remain free to own their routing policy.

Would maintainers prefer this metadata as multi-agent tool responses, app-server
JSON-RPC methods/events, or both? The important property for strict
orchestration is that the proof comes from the runtime owner and remains
available to the parent, rather than being inferred from configuration.