[codex] Add configurable multi-agent mode hint text#30493
Conversation
ce63391 to
8e2d3a0
Compare
8e2d3a0 to
58a3a77
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 58a3a77edd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if let Some(hint_text) = &self.hint_text { | ||
| return hint_text.clone(); |
There was a problem hiding this comment.
Cap configured multi-agent hint text
When features.multi_agent_v2.multi_agent_mode_hint_text is configured, this branch returns the raw config string as one developer fragment. The new TOML/schema field is an unconstrained String, so a large value can become a single model-visible item that crosses the >1k manual-review threshold or even the 10K-token hard limit; add a hard cap/truncation at config resolution or render time before injecting it.
AGENTS.md reference: AGENTS.md:L97-L100
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Looked around and no cap enforcement for the other and I am okay with keep it as is for now.
| .multi_agent_v2 | ||
| .multi_agent_mode_hint_text | ||
| { | ||
| Some(_) => MultiAgentMode::None, |
There was a problem hiding this comment.
Track configured hint changes in baseline
When a thread already has a configured multi_agent_mode_hint_text, every configured value is collapsed to MultiAgentMode::None here, while the durable TurnContextItem records only that enum. If the app-server reloads config or a rollout is resumed after the configured policy text changes, previous.multi_agent_mode == effective_multi_agent_mode and no incremental developer update is emitted, so the model keeps following the stale policy until a full context reinjection happens; include a bounded hint version/hash in the diff baseline or otherwise force an update when the rendered fragment changes.
AGENTS.md reference: AGENTS.md:L102-L110
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
that is okay too - if it was None previously it indicates that we do not have any specific sub agent delegation instruction. And a later resumed None would indicate the same.
| if let Some(hint_text) = &self.hint_text { | ||
| return hint_text.clone(); |
There was a problem hiding this comment.
Clear proactive mode for empty hint overrides
When an existing thread already has the proactive mode message in history and config is changed or resumed with multi_agent_mode_hint_text = "", this returns the empty hint verbatim, so the only new model-visible item is <multi_agent_mode></multi_agent_mode>. Because the context is incremental, the earlier proactive text remains in the request and explicitly says it stays active until a later mode message changes it; emit an explicit inactive/override message for the empty override instead of relying on empty tags to clear that prior policy.
AGENTS.md reference: AGENTS.md:L95-L96
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
This is acceptable.
| use codex_protocol::protocol::MULTI_AGENT_MODE_OPEN_TAG; | ||
|
|
||
| const EXPLICIT_REQUEST_ONLY_MULTI_AGENT_MODE_TEXT: &str = "Do not spawn sub-agents unless the user or applicable AGENTS.md/skill instructions explicitly ask for sub-agents, delegation, or parallel agent work."; | ||
| const NO_MULTI_AGENT_MODE_TEXT: &str = "Multi-agent delegation mode instructions are inactive. Any earlier multi-agent mode developer message no longer applies."; |
There was a problem hiding this comment.
Why are we removing this?
There was a problem hiding this comment.
This is only used by multi_agent_mode:None but that particular option is not reachable. Ultra breaks down to max + multi_agent_mode:proactive and non-ultra breaks down to effort + multi_agent_mode:explicitRequestOnly.
This is a relic when we were supporting multi_agent_mode as an independent param in various location like thread/start or turn/start before folding it into a reasoning effort transformation.
There was a problem hiding this comment.
Can we mark None as deprecated then? Ideally we'd remove it as well
There was a problem hiding this comment.
I am reusing it - if a custom hint text is provided, multi_agent_mode on the turn is marked as None. But tying to the conversation below maybe we should implement a custom enum type?
There was a problem hiding this comment.
Yep, I don't think we should conflate None vs. Custom
| #[derive(Debug, Clone, PartialEq, Eq)] | ||
| pub(crate) struct MultiAgentModeInstructions { | ||
| multi_agent_mode: MultiAgentMode, | ||
| hint_text: Option<String>, |
There was a problem hiding this comment.
It feels like it might be simpler to create MultiAgentMode::Custom and store hint_text inside that enum variant?
3a9ca01 to
a3c3ed3
Compare
| } | ||
|
|
||
| fn configure_custom_mode_hint(config: &mut Config) { | ||
| configure_multi_agent_v2(config); |
There was a problem hiding this comment.
We should document that this function implicitly enables v2
Why
Multi-agent V2 normally derives its mode instructions from reasoning effort: Ultra enables proactive delegation, while other efforts require an explicit request. Some deployments need to provide one configured delegation policy that replaces those built-ins and remains stable when reasoning effort changes.
What changed
features.multi_agent_v2.multi_agent_mode_hint_textalongside the existing root and subagent hint settings.MultiAgentMode::Custom(hint_text), so the configured text replaces the built-in explicit-only and proactive policies.MultiAgentMode::Nonevariant withMultiAgentMode::Custom(String)in new rollouts and API schemas. A compatibility wire type maps legacy serializednonevalues toCustom("")when resuming existing rollouts.Configuration examples
The distinction is whether
multi_agent_mode_hint_textis present. An empty string is still a configured value and intentionally suppresses the built-in mode instructions.Unset: preserve existing effort-derived behavior
Empty: suppress all mode hint text
This selects effective mode
customat every reasoning effort and injects an empty mode body, suppressing both built-in policies.Set: always use the configured text
This selects effective mode
customat every reasoning effort and injects the configured text verbatim instead of either built-in policy.Verification
just test -p codex-core multi_agent_modejust test -p codex-protocol -p codex-app-server-protocolnoneturn-context deserialization asCustom("")and verifies the regenerated schemas.