[codex] Load AGENTS.md from all bound environments (#27696)

## Why

We already have the machinery to support multiple environments on a
single thread, but we only show the model the contents of `AGENTS.md`
files in the primary environment.

We should show the model all of the relevant project instructions when
we know there's more than one environment.

## Known Gaps

As discussed in the RFC, this implementation:

1. doesn't handle environments being added/removed to/from the thread
after its creation
2. it doesn't enforce an aggregate context budget across environments,
and instead applies the configured project maximum independently to each
environment

## Implementation

- Discover project instructions in environment order with an independent
byte budget per environment and preserve source provenance/order.
- Keep the legacy fragment byte-for-byte when exactly one environment
contributes project instructions; use environment-labeled sections when
two or more environments contribute.
- Freeze the complete rendered fragment in `LoadedAgentsMd`, insert it
directly into requests, and recognize both layouts in contextual and
memory filtering.
- Add exact rendering, independent-budget, source-order,
creation-snapshot, and consumer coverage without changing app-server
schemas.
This commit is contained in:
Adam Perry @ OpenAI
2026-06-12 00:10:06 -07:00
committed by GitHub
Unverified
parent 7a19b14229
commit bf667c7003
15 changed files with 641 additions and 77 deletions
+3 -15
View File
@@ -294,7 +294,6 @@ use crate::SkillLoadOutcome;
use crate::SkillMetadata;
use crate::SkillsManager;
use crate::agents_md::load_project_instructions;
use crate::context::UserInstructions;
use crate::exec_policy::ExecPolicyUpdateError;
use crate::guardian::GuardianReviewSessionManager;
use crate::mcp::McpManager;
@@ -527,13 +526,9 @@ impl Codex {
config
.startup_warnings
.extend(user_instruction_provider_warnings);
// TODO(anp) assemble instructions from multiple environments
let primary_environment = environment_selections.primary_environment();
let primary_fs = primary_environment
.as_ref()
.map(|environment| environment.get_filesystem());
let loaded_agents_md =
load_project_instructions(&mut config, user_instructions, primary_fs.as_deref()).await;
load_project_instructions(&mut config, user_instructions, &environment_selections)
.await;
let exec_policy = if crate::guardian::is_guardian_reviewer_source(&session_source) {
// Guardian review should rely on the built-in shell safety checks,
@@ -2978,14 +2973,7 @@ impl Session {
}
}
if let Some(user_instructions) = turn_context.user_instructions.as_deref() {
contextual_user_sections.push(
UserInstructions {
text: user_instructions.to_string(),
#[allow(deprecated)]
directory: turn_context.cwd.to_string_lossy().into_owned(),
}
.render(),
);
contextual_user_sections.push(user_instructions.to_string());
}
// This is full-context metadata. Steady-state context diffs should not re-emit it.
if turn_context.features.enabled(Feature::TokenBudget)
+1 -1
View File
@@ -553,7 +553,7 @@ impl Session {
user_instructions: session_configuration
.loaded_agents_md
.as_ref()
.map(LoadedAgentsMd::text),
.map(LoadedAgentsMd::render),
collaboration_mode: session_configuration.collaboration_mode.clone(),
multi_agent_version,
personality: session_configuration.personality,