Skip to content

[codex] Honor role-defined spawn service tiers#22169

Merged
aibrahim-oai merged 10 commits into
mainfrom
dev/agent-role-service-tier
May 19, 2026
Merged

[codex] Honor role-defined spawn service tiers#22169
aibrahim-oai merged 10 commits into
mainfrom
dev/agent-role-service-tier

Conversation

@aibrahim-oai

@aibrahim-oai aibrahim-oai commented May 11, 2026

Copy link
Copy Markdown
Collaborator

Why

Custom agent roles are ordinary config layers, so a role file can already express service_tier just like other config values. The spawned-agent tier path needs to preserve that effective role config and follow the same precedence pattern as model/reasoning.

What changed

  • Apply an explicit spawn-time service_tier onto the child config before role application, so a role config layer can override it just like role-defined model/reasoning settings do.
  • Validate the final effective child tier after the final child model is known, while still falling back to the parent tier when no child tier survives.
  • Add focused integration coverage for both v1 and v2 proving role TOML loads a service tier, spawned children keep that role-configured tier, and a role tier wins over a conflicting spawn-time tier.

Validation

  • just fmt
  • git diff --check
  • Local Rust tests not run, per repo guidance; CI should exercise the new coverage.

@aibrahim-oai aibrahim-oai marked this pull request as ready for review May 11, 2026 17:24
@aibrahim-oai aibrahim-oai requested a review from a team as a code owner May 11, 2026 17:24

@jif-oai jif-oai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that a role-provided service_tier can override the explicit spawn argument, can we surface that in the role guidance too?

.await;
let mut config =
build_agent_spawn_config(&session.get_base_instructions().await, turn.as_ref())?;
if let Some(service_tier) = args.service_tier.as_ref() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this survives role application. apply_role_to_config() rebuilds Config from the layer stack
This should be preserved through the role reload

.await;
let mut config =
build_agent_spawn_config(&session.get_base_instructions().await, turn.as_ref())?;
if let Some(service_tier) = args.service_tier.as_ref() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

requested_service_tier: Option<&str>,
) -> Result<(), FunctionCallError> {
let Some(candidate_service_tier) = requested_service_tier.or(parent_service_tier) else {
let requested_service_tier_is_effective =

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes validation of the explicit spawn argument role-dependent. Invalid request like service_tier=wtf stops failing if the selected role overwrite the field
I think we should always error. Mainly in 0-shot

let Some(candidate_service_tier) = config
.service_tier
.clone()
.or_else(|| parent_service_tier.map(str::to_string))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(found by Codex)
This only falls back to the parent before support validation. If the role contributes an unsupported child tier, we never retry a still-valid parent tier; we clear the field below and spawn with no tier instead

}

if requested_service_tier.is_none() {
if !requested_service_tier_is_effective {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Silently drops unsupported role-authored tiers. Same comment as before

Base automatically changed from dev/spawn-agent-service-tier to main May 13, 2026 15:11
@aibrahim-oai

Copy link
Copy Markdown
Collaborator Author

@codex review this

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2d64b20f1e

ℹ️ 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".

}
let (preserve_current_profile, preserve_current_provider) =
preservation_policy(config, &role_layer_toml);
let preserve_current_service_tier = role_layer_toml.get("service_tier").is_none();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor profile-scoped role service tiers

This only checks for a top-level service_tier, but role files can select or define profiles, and ConfigProfile has its own service_tier; Config::load_config_with_layer_stack only reads config_profile.service_tier when the service-tier override is None. With a role such as profile = "tiered" plus [profiles.tiered] service_tier = "priority" (or a role update to the active profile), this line preserves the parent/request tier as an override, so the profile-defined role tier is ignored instead of being honored.

Useful? React with 👍 / 👎.

Comment thread codex-rs/core/src/agent/role.rs Outdated
let service_tier_note = service_tier
.map(|service_tier| {
format!(
"\n- This role's service tier is set to `{service_tier}` and overrides any spawn request service tier."

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Under validation constraints right?

@aibrahim-oai aibrahim-oai enabled auto-merge (squash) May 19, 2026 19:16
@aibrahim-oai aibrahim-oai merged commit c53da02 into main May 19, 2026
45 of 47 checks passed
@aibrahim-oai aibrahim-oai deleted the dev/agent-role-service-tier branch May 19, 2026 22:40
@github-actions github-actions Bot locked and limited conversation to collaborators May 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants