move plugin/skill instructions into dev msg and reorder (#14609)

Move the general `Apps`, `Skills` and `Plugins` instructions blocks out
of `user_instructions` and into the developer message, with new `Apps ->
Skills -> Plugins` order for better clarity.

Also wrap those sections in stable XML-style instruction tags (like
other sections) and update prompt-layout tests/snapshots. This makes the
tests less brittle in snapshot output (we can parse the sections), and
it consolidates the capability instructions in one place.

#### Tests
Updated snapshots, added tests.

`<AGENTS_MD>` disappearing in snapshots is expected: before this change,
the wrapped user-instructions message was kept alive by `Skills`
content. Now that `Skills` and `Plugins` are in the developer message,
that wrapper only appears when there is real
project-doc/user-instructions content.

---------

Co-authored-by: Charley Cunningham <ccunningham@openai.com>
This commit is contained in:
sayan-oai
2026-03-13 20:51:01 -07:00
committed by GitHub
parent 7f571396c8
commit d272f45058
44 changed files with 344 additions and 362 deletions

View File

@@ -189,9 +189,10 @@ fn tool_description(body: &serde_json::Value, tool_name: &str) -> Option<String>
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn plugin_skills_append_to_instructions() -> Result<()> {
async fn capability_sections_render_in_developer_message_in_order() -> Result<()> {
skip_if_no_network!(Ok(()));
let server = MockServer::start().await;
let server = start_mock_server().await;
let apps_server = AppsTestServer::mount_with_connector_name(&server, "Google Calendar").await?;
let resp_mock = mount_sse_once(
&server,
@@ -201,7 +202,13 @@ async fn plugin_skills_append_to_instructions() -> Result<()> {
let codex_home = Arc::new(TempDir::new()?);
write_plugin_skill_plugin(codex_home.as_ref());
let codex = build_plugin_test_codex(&server, Arc::clone(&codex_home)).await?;
write_plugin_app_plugin(codex_home.as_ref());
let codex = build_apps_enabled_plugin_test_codex(
&server,
Arc::clone(&codex_home),
apps_server.chatgpt_base_url,
)
.await?;
codex
.submit(Op::UserInput {
@@ -216,29 +223,36 @@ async fn plugin_skills_append_to_instructions() -> Result<()> {
wait_for_event(&codex, |ev| matches!(ev, EventMsg::TurnComplete(_))).await;
let request = resp_mock.single_request();
let request_body = request.body_json();
let instructions_text = request_body["input"][1]["content"][0]["text"]
.as_str()
.expect("instructions text");
let developer_messages = request.message_input_texts("developer");
let developer_text = developer_messages.join("\n\n");
let apps_pos = developer_text
.find("## Apps")
.expect("expected apps section in developer message");
let skills_pos = developer_text
.find("## Skills")
.expect("expected skills section in developer message");
let plugins_pos = developer_text
.find("## Plugins")
.expect("expected plugins section in developer message");
assert!(
instructions_text.contains("## Plugins"),
"expected plugins section present"
apps_pos < skills_pos && skills_pos < plugins_pos,
"expected Apps -> Skills -> Plugins order: {developer_messages:?}"
);
assert!(
instructions_text.contains("`sample`"),
"expected enabled plugin name in instructions"
developer_text.contains("`sample`"),
"expected enabled plugin name in developer message: {developer_messages:?}"
);
assert!(
instructions_text.contains("`sample`: inspect sample data"),
"expected plugin description in instructions"
developer_text.contains("`sample`: inspect sample data"),
"expected plugin description in developer message: {developer_messages:?}"
);
assert!(
instructions_text.contains("skill entries are prefixed with `plugin_name:`"),
"expected plugin skill naming guidance"
developer_text.contains("skill entries are prefixed with `plugin_name:`"),
"expected plugin skill naming guidance in developer message: {developer_messages:?}"
);
assert!(
instructions_text.contains("sample:sample-search: inspect sample data"),
"expected namespaced plugin skill summary"
developer_text.contains("sample:sample-search: inspect sample data"),
"expected namespaced plugin skill summary in developer message: {developer_messages:?}"
);
Ok(())