Skip to content

Add sticky environment API and thread state#18897

Merged
starr-openai merged 18 commits intomainfrom
starr/sticky-env-split-1-api-thread
Apr 24, 2026
Merged

Add sticky environment API and thread state#18897
starr-openai merged 18 commits intomainfrom
starr/sticky-env-split-1-api-thread

Conversation

@starr-openai
Copy link
Copy Markdown
Contributor

@starr-openai starr-openai commented Apr 21, 2026

Summary

  • add sticky environment selections to app-server v2 thread/start and turn/start request flow
  • carry thread-level selections through core session/thread state
  • add app-server coverage for sticky selections and turn overrides

Stack

  1. This PR: API and thread persistence
  2. Load named environments from config #18898: config.toml named environment loading
  3. Wire selected environments into tools #18899: downstream tool/runtime consumers

Validation

  • Not run locally; split only.

@starr-openai starr-openai force-pushed the starr/sticky-env-split-1-api-thread branch from ee1a5f1 to c3f1adb Compare April 21, 2026 22:11
@starr-openai starr-openai force-pushed the turn-environments-20260417 branch 2 times, most recently from 3fdd893 to 8dac6ca Compare April 21, 2026 23:41
@starr-openai starr-openai force-pushed the starr/sticky-env-split-1-api-thread branch 3 times, most recently from e04ef64 to 6edcdf2 Compare April 22, 2026 00:08
@starr-openai starr-openai changed the base branch from turn-environments-20260417 to starr/sticky-env-split-base-b49 April 22, 2026 00:08
@starr-openai starr-openai force-pushed the starr/sticky-env-split-1-api-thread branch from c8c8e86 to 47d2133 Compare April 22, 2026 01:16
@starr-openai starr-openai force-pushed the starr/sticky-env-split-1-api-thread branch 3 times, most recently from 25decb8 to 606663d Compare April 22, 2026 01:34
@starr-openai starr-openai marked this pull request as ready for review April 22, 2026 01:55
@starr-openai starr-openai requested a review from a team as a code owner April 22, 2026 01:55
@starr-openai starr-openai force-pushed the starr/sticky-env-split-1-api-thread branch 2 times, most recently from b810587 to a578544 Compare April 22, 2026 02:03
Copy link
Copy Markdown
Contributor

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

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: 606663dfae

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

Comment thread codex-rs/core/src/session/turn_context.rs Outdated
Comment thread codex-rs/core/src/thread_manager.rs Outdated
@starr-openai starr-openai force-pushed the starr/sticky-env-split-1-api-thread branch from a578544 to 309cfc8 Compare April 22, 2026 02:55
Comment thread codex-rs/core/src/session/mod.rs Outdated
Comment thread codex-rs/core/src/session/agent_task_lifecycle.rs Outdated
@starr-openai starr-openai force-pushed the starr/sticky-env-split-1-api-thread branch from 352cf40 to ca56b45 Compare April 22, 2026 20:01
@starr-openai starr-openai changed the base branch from starr/sticky-env-split-base-b49 to main April 22, 2026 20:03
@starr-openai starr-openai force-pushed the starr/sticky-env-split-1-api-thread branch 2 times, most recently from 45a8abf to 28231ef Compare April 22, 2026 21:21
Comment thread codex-rs/core/src/session/turn_context.rs Outdated
Comment thread codex-rs/core/src/session/turn_context.rs
Comment thread codex-rs/core/src/thread_manager.rs Outdated
Comment thread codex-rs/core/src/session/turn_context.rs Outdated
starr-openai and others added 15 commits April 23, 2026 11:23
Allow thread/start to configure sticky environment selections that are used by turns when no per-turn override is supplied. Per-turn environments continue to take precedence, while omitted thread selections preserve the existing default behavior.

Co-authored-by: Codex <noreply@openai.com>
Cover sticky thread environment selections and turn-level overrides through the app-server v2 thread/start and turn/start JSON-RPC flow. The matrix mirrors the manual smoke cases for omitted, empty, local, remote, and local plus remote selections.

Co-authored-by: Codex <noreply@openai.com>
Group thread-start options for lint-friendly callsites and update generated v2 schema for sticky environment selections.

Co-authored-by: Codex <noreply@openai.com>
Introduce a core-owned EnvironmentSelection type so app-server converts API environment params at the core boundary instead of passing protocol operation structs through session/thread state. Rename the internal sticky field from environment_selections to environments to match the v2 API shape.

Co-authored-by: Codex <noreply@openai.com>
Reject named turn and sticky environments when environment access is disabled, while preserving explicit empty environment selections as no-environment turns. Validate sticky environment state before storing it so invalid selections cannot poison future turns.

Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <noreply@openai.com>
Resume and fork should not recover thread environment overrides from persisted rollout state; sticky environment selection stays scoped to the live thread/session configuration.

Co-authored-by: Codex <noreply@openai.com>
Remove the duplicate SessionConfiguration environments initializer left by the rebase.

Co-authored-by: Codex <noreply@openai.com>
Avoid requiring TurnEnvironment to implement PartialEq in the resume/fork test that verifies sticky environments are not restored from rollout history.

Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <noreply@openai.com>
Co-authored-by: Codex <noreply@openai.com>
Move default thread environment selection into a shared helper, validate explicit environment IDs at spawn, and resolve selections only when constructing turns. This keeps app-server optionality at the API edge while preserving sticky thread state as explicit selections.

Co-authored-by: Codex <noreply@openai.com>
Use the EnvironmentManager default environment id when materializing default thread selections, carry environment ids through resolved turn environments, and make subagents inherit the parent turn environment list instead of re-defaulting. Keep turn-local environment overrides on SessionSettingsUpdate so turn context updates flow through one settings payload.

Co-authored-by: Codex <noreply@openai.com>
Keep the effective turn environment selections on TurnContext so child agents can inherit selections directly without rebuilding them from resolved environments. Route app-server validation through ThreadManager and preserve turn-scoped selections for agent job workers.

Co-authored-by: Codex <noreply@openai.com>
@starr-openai starr-openai force-pushed the starr/sticky-env-split-1-api-thread branch from ce102d0 to a1ec341 Compare April 23, 2026 18:27
@starr-openai starr-openai requested a review from pakrym-oai April 23, 2026 19:03
Remove the unused resolved turn environment id field now that effective selections are stored separately, and collapse app-server environment validation guards for clippy.

Co-authored-by: Codex <noreply@openai.com>
pub(crate) struct SpawnAgentOptions {
pub(crate) fork_parent_spawn_call_id: Option<String>,
pub(crate) fork_mode: Option<SpawnAgentForkMode>,
pub(crate) environments: Option<Vec<TurnEnvironmentSelection>>,
Copy link
Copy Markdown
Collaborator

@pakrym-oai pakrym-oai Apr 23, 2026

Choose a reason for hiding this comment

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

nit: non optional? non blocking

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this one still need Option for the 'use defaults' mode, which a few other callsites still use (e.g. memories/phase2.rs)

Comment thread codex-rs/core/src/session/review.rs Outdated
reasoning_summary,
session_source,
environment: parent_turn_context.environment.clone(),
environment_selections: parent_turn_context.environment_selections.clone(),
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.

nit: why are we storing both environment_selections and environments? should we store only materialized list?

Comment thread codex-rs/core/src/session/session.rs Outdated
/// Turn-local environment override. This is consumed while building a turn
/// context and does not mutate the sticky thread environments stored on
/// `SessionConfiguration`.
pub(crate) environments: TurnEnvironmentOverride,
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.

Should this be Option<> ? like other fields/

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

good call - swapped to Option, which means we can drop what was previously an enum class serving pretty much the same purpose

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

(codex used an enum class to be more explicit on the two modes, but Option<> is more consistent with how we're using env everywehre else)

sub_id,
session_configuration,
updates.final_output_json_schema,
effective_environments,
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.

doesn't feel like we should put effective_environments on turn considering we have the entire resolved list.

let mut state = self.state.lock().await;
match state.session_configuration.clone().apply(&updates) {
Ok(next) => {
let effective_environments =
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.

Not sure I understand what is happening here.

In theory state.session_configuration.clone().apply(&updates) will apply updates to the config and return the new environment list as part of next. Why do we need to resolve_ref here ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

^ that's just the thread level settings - don't we still need to apply the turn level overrides?

starr-openai and others added 2 commits April 23, 2026 16:04
Store the selected environment id on each resolved turn environment so turn context does not need to carry a parallel selection list. Sub-agent inheritance now projects selections from the materialized turn environments.

Co-authored-by: Codex <noreply@openai.com>
Use Option<Vec<TurnEnvironmentSelection>> directly for turn-local environment overrides. None inherits sticky thread environments, while Some([]) explicitly disables environments for the turn.

Co-authored-by: Codex <noreply@openai.com>
@starr-openai starr-openai merged commit 49fb259 into main Apr 24, 2026
25 checks passed
@starr-openai starr-openai deleted the starr/sticky-env-split-1-api-thread branch April 24, 2026 01:57
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 24, 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