[apps] Add gated instructions for Apps. (#10924)

- [x] Add gated instructions for Apps.
This commit is contained in:
Matthew Zeng
2026-02-09 14:48:09 -08:00
committed by GitHub
parent ed977dbeda
commit d90df4761b
6 changed files with 111 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
mod render;
pub(crate) use render::render_apps_section;
+7
View File
@@ -0,0 +1,7 @@
use crate::mcp::CODEX_APPS_MCP_SERVER_NAME;
pub(crate) fn render_apps_section() -> String {
format!(
"## Apps\nApps are mentioned in the prompt in the format `[$app-name](apps://{{connector_id}})`.\nAn app is equivalent to a set of MCP tools within the `{CODEX_APPS_MCP_SERVER_NAME}` MCP.\nWhen you see an app mention, the app's MCP tools are either already provided in `{CODEX_APPS_MCP_SERVER_NAME}`, or do not exist because the user did not install it.\nDo not additionally call list_mcp_resources for apps that are already mentioned."
)
}
+4
View File
@@ -15,6 +15,7 @@ use crate::agent::MAX_THREAD_SPAWN_DEPTH;
use crate::agent::agent_status_from_event;
use crate::analytics_client::AnalyticsEventsClient;
use crate::analytics_client::build_track_events_context;
use crate::apps::render_apps_section;
use crate::compact;
use crate::compact::run_inline_auto_compact_task;
use crate::compact::should_use_remote_compact_task;
@@ -2280,6 +2281,9 @@ impl Session {
);
}
}
if turn_context.features.enabled(Feature::Apps) {
items.push(DeveloperInstructions::new(render_apps_section()).into());
}
if let Some(user_instructions) = turn_context.user_instructions.as_deref() {
items.push(
UserInstructions {
+1
View File
@@ -8,6 +8,7 @@
mod analytics_client;
pub mod api_bridge;
mod apply_patch;
mod apps;
pub mod auth;
pub mod bash;
mod client;
+24
View File
@@ -547,6 +547,30 @@ mod tests {
assert_eq!(res, expected);
}
#[tokio::test]
async fn apps_feature_does_not_emit_user_instructions_by_itself() {
let tmp = tempfile::tempdir().expect("tempdir");
let mut cfg = make_config(&tmp, 4096, None).await;
cfg.features.enable(Feature::Apps);
let res = get_user_instructions(&cfg, None).await;
assert_eq!(res, None);
}
#[tokio::test]
async fn apps_feature_does_not_append_to_project_doc_user_instructions() {
let tmp = tempfile::tempdir().expect("tempdir");
fs::write(tmp.path().join("AGENTS.md"), "base doc").unwrap();
let mut cfg = make_config(&tmp, 4096, None).await;
cfg.features.enable(Feature::Apps);
let res = get_user_instructions(&cfg, None)
.await
.expect("instructions expected");
assert_eq!(res, "base doc");
}
fn create_skill(codex_home: PathBuf, name: &str, description: &str) {
let skill_dir = codex_home.join(format!("skills/{name}"));
fs::create_dir_all(&skill_dir).unwrap();