Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions docs-site/src/content/docs/guides/sub-agent-surface.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,14 @@ The dashboard's **Sub-agent delegation** controls three related settings:

- `injectionModel` is the preferred worker model named in CodexCommander guidance.
- `injectionEffort` is the optional `reasoning_effort` to request for that model.
- `injectionPrompt` replaces the built-in V2 guidance text.
- `injectionPrompt` customizes the V2 guidance body. When a preferred model or eligible roster resolves, explicit spawn-model instructions are retained.

`multiAgentGuidanceEnabled` defaults to on and is the master switch for CodexCommander-authored guidance
on both surfaces. Turning it off suppresses both the V2 designation block and V1 proactive text.

These are instructions to the main agent, not a proxy-side spawn router. On V2, a full-history fork
inherits the parent model and rejects model or effort overrides. Guidance therefore tells Codex to
use `fork_turns: "none"` (or a positive partial turn count such as `"3"`) when passing `model` or
use `fork_turns: "none"` when passing `model` or
`reasoning_effort`, and to make the task message self-contained.

### Native continuation and caching
Expand All @@ -151,7 +151,8 @@ Guidance is optional, sanitized operator text. Empty text is omitted; nonempty t
Unicode code points. Treat it as untrusted advisory context, not as an effort, quota, role, or
fallback control. On eligible V2 turns CodexCommander first applies live picker, surface, route, and
encrypted-task compatibility filters, then adds every surviving row annotation to the built-in
developer message without an aggregate character budget. Row guidance is not injected on V1 and is
developer message or custom `{{roster}}` expansion without an aggregate character budget.
Row guidance is not injected on V1 and is
never copied into the managed skill or global `AGENTS.md` policy.

Custom `injectionPrompt` text can use all four placeholders:
Expand All @@ -160,13 +161,19 @@ Custom `injectionPrompt` text can use all four placeholders:
| --- | --- |
| `{{model}}` | The effective preferred model for this request. A bare native `injectionModel` is account-qualified only when the request itself targets an explicit account selector. An unresolved or ambiguous bare value becomes an empty string; an unresolved explicit account-qualified or routed id remains unchanged |
| `{{effort}}` | The configured `injectionEffort`, or an empty string |
| `{{roster}}` | The resolved picker-visible, surface-compatible roster |
| `{{roster}}` | The resolved picker-visible, surface-compatible roster and its eligible per-model guidance |
| `{{fallback}}` | The configured global fallback guidance |

Built-in V2 guidance includes every accepted roster annotation that survives the compatibility
filters. Built-in guidance fires only when a preferred model, eligible roster, or fallback chain
resolves. A configured `injectionModel` is sufficient to render a custom prompt; if a bare value
cannot resolve uniquely, `{{model}}` expands to an empty string.
resolves. An eligible `injectionModel` is sufficient to render a custom prompt. If a bare value
cannot resolve uniquely, `{{model}}` expands to an empty string when another eligible roster or
fallback keeps the custom prompt active; otherwise guidance stays silent.

When a preferred model or eligible roster resolves, built-in and custom guidance explain that a selected model must be passed explicitly in
`spawn_agent.model`; leaving it out inherits the native default or parent model. The managed skill
and `AGENTS.md` policy explicitly request task-fit overrides from the fresh, compatible live roster.
They contain no fixed model IDs, and native validation remains authoritative.

On V1, CodexCommander injects only the upstream-style proactive delegation guidance at `max` or `ultra`
effort. It does not add a preferred model, roster, fallback list, or custom prompt on V1.
Expand Down Expand Up @@ -326,8 +333,9 @@ main agent still decides whether to delegate.

### Why did my V2 child use the parent model?

A full-history V2 fork inherits the parent model. Use a spawn that sets `fork_turns` to `"none"` or
a positive partial count before passing a model or effort override.
A full-history V2 fork inherits the parent model. Choose an eligible model from the live roster,
pass its exact ID in `spawn_agent.model`, and set `fork_turns` to `"none"` when using an override.
Refresh the managed delegation setup so its policy explicitly requests roster selection.

### Why is a configured model missing from the V2 roster?

Expand Down
13 changes: 8 additions & 5 deletions docs-site/src/content/docs/guides/web-dashboard.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,8 @@ than overwritten, so they may continue to override the requested defaults.

Per-row roster guidance is separate live V2 developer text. It is optional sanitized operator text
(empty omitted, at most 160 Unicode code points), advisory and untrusted rather than an effort, quota,
role, or fallback control. The built-in developer message includes every accepted annotation that
role, or fallback control. The built-in developer message and custom `{{roster}}` expansion include
every accepted annotation that
survives the live V2 compatibility filters; it is not copied into the managed skill or `AGENTS.md`.

:::caution
Expand All @@ -224,10 +225,12 @@ they have been synchronized. See
[Sub-agent Surface](/guides/sub-agent-surface/) for the canonical V1/base/V2 behavior.
:::

The spawn override guarantee applies to the **built-in** V2 guidance text. A custom
`injectionPrompt` replaces that text entirely and must include `{{model}}` and `{{effort}}`
placeholders (and optionally `{{roster}}`) or those values will not appear in the injected
guidance.
When a preferred model or eligible roster resolves, built-in and custom V2 guidance explain how to pass the selected model explicitly to
`spawn_agent.model`; omission inherits the native default or parent model. The managed delegation
skill and `AGENTS.md` policy explicitly request task-fit overrides when the live catalog is fresh
and the target is compatible. A custom `injectionPrompt` must still include `{{model}}`, `{{effort}}`,
or `{{roster}}` to include those configured values. The roster placeholder also includes eligible
per-model guidance.

The picker offers enabled native and routed models plus the global Codex effort ladder. The API
validates the selected effort globally; Codex still validates a spawn effort against the target
Expand Down
16 changes: 11 additions & 5 deletions docs-site/src/content/docs/reference/configuration/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ routes, and limits delegated work.
| `subagentModels?` | `{ model: string, guidance?: string }[] \| string[]` (on disk) | `gpt-5.5`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.4-mini` | Up to five ordered bare native, account-qualified `<selector>/<native-openai-model>`, or routed `provider/model` entries advertised first in the sub-agent picker. Reads accept either legacy strings or objects, but CodexCommander canonicalizes in memory and writes objects. The first object write is a migration point: older binaries that only understand `string[]` fail when they read the config. Optional `guidance` is sanitized operator text, capped at 160 Unicode code points; empty guidance is omitted. The dashboard preserves configured exact selectors and reports which saved entries are advertised or excluded. Use `ccx agent subagents set` or edit the configuration for choices that are not in the current catalog. An explicit empty list is preserved. |
| `injectionModel?` | `string` | — | Preferred native or routed sub-agent model used in proxy-authored V2 delegation guidance. |
| `injectionEffort?` | `string` | — | Preferred effort (`low` through `ultra`), meaningful only with `injectionModel`. |
| `injectionPrompt?` | `string` | — | Replaces the built-in V2 guidance body. Supports `{{model}}`, `{{effort}}`, `{{roster}}`, and `{{fallback}}`. A configured `injectionModel` is sufficient to render the custom prompt. |
| `injectionPrompt?` | `string` | — | Customizes the V2 guidance body. When a preferred model or eligible roster resolves, the explicit spawn-model instructions are retained. Supports `{{model}}`, `{{effort}}`, `{{roster}}`, and `{{fallback}}`; the roster includes eligible per-model guidance. An eligible `injectionModel` is sufficient to render the custom prompt. |
| `multiAgentGuidanceEnabled` | `boolean` | `true` | Controls only CodexCommander-authored V1/V2 developer guidance; it does not change native agent defaults, tools, routing, rosters, or effort caps. |
| `syncCodexSubagentDefaults?` | `boolean` | `false` | Opt into writing `injectionModel` and optional `injectionEffort` as Codex's native defaults during sync/restart. Requires `injectionModel`. |
| `subagentModelFallback?` | `string[]` | `[]` | Priority-ordered global fallback models for spawned child turns. |
Expand Down Expand Up @@ -58,21 +58,27 @@ Surface detection uses tool shape. A namespaced `spawn_agent` with `send_input`,

V1 guidance is proactive text only at `max` or `ultra`. V2 receives a proxy-authored developer
message only when a preferred model, eligible roster, or fallback chain exists. Built-in V2 guidance
includes every accepted eligible roster annotation; it has no aggregate character budget. Guidance
and the custom `{{roster}}` placeholder include every accepted eligible roster annotation; there is no
aggregate character budget. Guidance
is deduplicated across replay prefixes and inserted before a trailing `compaction_trigger`.

`injectionModel` and `injectionEffort` are advisory unless native-default sync is enabled. The built-in
V2 text treats the featured roster as suggestions, allows a known exact compatible catalog ID to be
passed to native `spawn_agent`, and asks Codex to pass supported model/effort overrides with
`fork_turns: "none"`. A custom `injectionPrompt` substitutes missing values with an empty string and
replaces that built-in exact-ID wording.
`fork_turns: "none"`. A custom `injectionPrompt` substitutes missing values with an empty string.
When a preferred model or eligible roster exists, both paths explain that the selected exact ID must
be passed in `spawn_agent.model`: omission inherits the native default or parent rather than selecting
from the roster. The managed delegation skill and `AGENTS.md` policy explicitly request these task-fit
overrides, satisfying native Codex's requirement for a user, policy, or skill instruction. Catalog
freshness, compatibility, and native validation still apply.

Each roster row may also carry optional `guidance`. This is untrusted operator text for the live
delegation message, not a policy control: it cannot set effort, quotas, roles, or fallback behavior.
After normalization (NFC plus trim), empty text is omitted; nonempty text is limited to 160 Unicode
code points and sanitized before persistence. Row guidance is considered only on eligible V2 turns,
after live picker, route, surface, and encrypted-task compatibility filters. Every accepted annotation
that survives those filters is included in built-in V2 guidance. It is not injected on V1 and is
that survives those filters is included in built-in V2 guidance and custom `{{roster}}` expansion.
It is not injected on V1 and is
never copied into the managed skill or global `AGENTS.md` block.

## Managed advisory setup
Expand Down
1 change: 1 addition & 0 deletions src/codex/delegation-templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function agentsBlock(mode: CodexDelegationMode): string {
`Mode: ${mode}`,
"Before spawning subagents, use $codexcommander-delegation and reread its SKILL.md if its details were compacted.",
"Consult the active collaboration roster and spawn-tool contract. Never hardcode model IDs. Match each spawn to task complexity, uncertainty, risk, and how tightly you can check the result; reassess on failed evidence, scope expansion, uncertainty, or capability mismatch—not on timeout alone. Give workers self-contained tasks.",
"This policy explicitly requests model overrides: when a fresh Commander roster or preferred model provides a task-fit choice compatible with the active tool and task delivery, pass its exact ID in spawn_agent.model. Omitting model inherits the configured default or parent; it does not select from the roster. Respect stale or unknown catalogs and unsupported overrides; on V2 use fork_turns none when setting an override.",
"A wait_agent timeout is neutral; never interrupt solely because one or more waits timed out. Use the managed skill for reconciliation and interruption gates.",
delegationSentence,
"This guidance is advisory and does not create collaboration tools. User and repository instructions outrank it for whether to spawn.",
Expand Down
26 changes: 16 additions & 10 deletions src/server/responses/collaboration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,25 +424,31 @@ export async function multiAgentGuidanceText(
const fallbackGuidance = subagentFallbackGuidanceText({ subagentModelFallback: compatibleFallback } as CodexCommanderConfig);
const hasCompatibleGuidance = preferred !== undefined || compactRoster !== "" || fallbackGuidance !== "";
if (!hasCompatibleGuidance) return null;
const modelSelectionContract = preferred !== undefined || compactRoster !== ""
? "When the active spawn_agent tool supports optional \"model\" or \"reasoning_effort\" overrides, "
+ "pass the chosen exact model in spawn_agent.model. "
+ "Omitting model inherits the configured default or parent; it does not select from the Commander roster. "
+ "When setting either override, use fork_turns \"none\" and a self-contained task."
: "";
if (injectionPrompt) {
return `<multi_agent_mode>${applyInjectionPlaceholders(injectionPrompt, preferred?.model, injectionEffort, compactRoster, fallbackGuidance)}</multi_agent_mode>`;
const custom = applyInjectionPlaceholders(injectionPrompt, preferred?.model, injectionEffort, annotatedRoster, fallbackGuidance);
return `<multi_agent_mode>${custom}${modelSelectionContract ? ` ${modelSelectionContract}` : ""}</multi_agent_mode>`;
}
let text = modelSelectionContract;
if (modelSelectionContract) {
text += " Listed models are featured suggestions, not an exhaustive allowlist. "
+ "A known exact catalog ID that is fresh, routable, and compatible with this surface and task delivery "
+ "may be passed directly to native spawn_agent; native validation remains authoritative. "
+ "Do not invent IDs or substitute another family.";
}
let text = "When the active spawn_agent tool supports optional \"model\" or \"reasoning_effort\" overrides, "
+ "listed models are featured suggestions, not an exhaustive allowlist. "
+ "A known exact catalog ID that is fresh, routable, and compatible with this surface and task delivery "
+ "may be passed directly to native spawn_agent; native validation remains authoritative. "
+ "Do not invent IDs or substitute another family. "
+ "When setting either override, set fork_turns to \"none\" "
+ "(or a positive turn count such as \"3\"; full-history forks reject overrides) "
+ "and make the task message self-contained.";
if (preferred) {
text += ` Preferred sub-agent: model "${preferred.model}"`
+ (injectionEffort ? `, reasoning_effort "${injectionEffort}"` : "")
+ " — use it unless the user names another.";
}
text += fallbackGuidance;
text += annotatedRoster;
return `<multi_agent_mode>${text}</multi_agent_mode>`;
return `<multi_agent_mode>${text.trim()}</multi_agent_mode>`;
}

const effort = parsed.options.reasoning;
Expand Down
2 changes: 1 addition & 1 deletion src/skills/codexcommander-delegation/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Give every child a self-contained brief with its goal, paths or inputs, owned fi

Match each spawn to task fit: complexity, uncertainty, risk, and how tightly you can check the result. Live featured models are suggestions, not an exhaustive allowlist. Prefer the configured preferred worker when it fits. Escalate capability only when the brief needs it; do not default to the cheapest or smallest model, and do not spawn solely to delegate.

Omitting `model` inherits the configured default or parent choice. When the live contract permits a deliberate override and you know an exact compatible catalog ID that is fresh, routable, and compatible with this surface and task delivery, pass that known exact ID as `model`. Add `reasoning_effort` only when the target advertises supported values and the brief benefits from it. On V2, set `fork_turns` to `"none"` or a positive partial count when passing `model` or `reasoning_effort`; full-history forks reject overrides. Omit overrides when the catalog is stale, unknown, or uncertain. Native validation remains authoritative. Do not invent IDs, substitute another family, or remember IDs.
This skill explicitly requests model overrides when a fresh Commander roster or preferred model provides a task-fit choice compatible with the active tool and task delivery. Choose using the live model guidance and pass the selected known exact catalog ID as `model` in `spawn_agent.model`; listing a roster alone does not select a worker. Omitting `model` inherits the configured default or parent choice, so do not omit it merely because the native tool inherits by default. Add `reasoning_effort` only when the target advertises supported values and the brief benefits from it. On V2, set `fork_turns` to `"none"` when passing `model` or `reasoning_effort`; full-history forks reject overrides. Omit overrides when the catalog is stale, unknown, or uncertain, the tool does not support them, or no compatible choice fits. Native validation remains authoritative. Do not invent IDs, substitute another family, or remember IDs.

## Root review and reassessment

Expand Down
9 changes: 8 additions & 1 deletion structure/03_catalog-and-subagents.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ the requested model id only; effort remains owned by the caps described under
On eligible V2 turns, a surviving row's guidance is included in the live developer message only
after the current catalog's surface, visibility, route, and encrypted-task compatibility filters
have run. Every accepted annotation that survives those filters is included in the built-in V2
message, which has no aggregate character budget. It is never copied into the managed delegation
message and custom `{{roster}}` expansion, with no aggregate character budget. It is never copied into the managed delegation
skill or global `AGENTS.md` block, and it does not change native Codex behavior on V1.

`injectionModel` and `injectionEffort` are shared selections with two independent consumers.
Expand All @@ -342,6 +342,13 @@ Native `[agents]` defaults remain limited to `injectionModel` and `injectionEffo
per-row guidance are not persisted there. The managed skill and bounded global `AGENTS.md` policy are
also deliberately roster-free and consult the live collaboration contract instead.

The managed skill and global policy explicitly request an exact model override for a fresh,
compatible task-fit roster choice. This supplies the instruction source required by native Codex's
model-override contract. Both built-in and custom V2 model guidance explain that omission inherits
the native default or parent; merely advertising a roster does not select a worker. Custom prompts
retain that instruction when an eligible model is designated. Native validation and the stale/unknown
catalog gates remain authoritative, and full-history forks still reject overrides.

Claude Code `ccx-*` agent definitions consume the same effective `claudeCode.blockedSkills` policy
as inbound bundle elision. When the list is non-empty (default: `claude-api`), generated definitions
whose marker-stripped model resolves to a routed id receive a preventive instruction not to invoke
Expand Down
Loading
Loading