diff --git a/codex-rs/core/src/tools/handlers/request_plugin_install_spec.rs b/codex-rs/core/src/tools/handlers/request_plugin_install_spec.rs index ed143283e7..6b10fbce3d 100644 --- a/codex-rs/core/src/tools/handlers/request_plugin_install_spec.rs +++ b/codex-rs/core/src/tools/handlers/request_plugin_install_spec.rs @@ -32,7 +32,7 @@ pub(crate) fn create_request_plugin_install_tool() -> ToolSpec { ]); let description = format!( - "# Request plugin/connector install\n\nUse this tool only after `{LIST_AVAILABLE_PLUGINS_TO_INSTALL_TOOL_NAME}` returns a plugin or connector that exactly matches the user's explicit request.\n\nDo not use it for adjacent capabilities, broad recommendations, or tools that merely seem useful. Pass the returned `tool_type` through directly, and pass the returned `id` as `tool_id`.\n\nIMPORTANT: DO NOT call this tool in parallel with other tools." + "# Request plugin/connector install\n\nUse this tool only when either:\n- `{LIST_AVAILABLE_PLUGINS_TO_INSTALL_TOOL_NAME}` returns a plugin or connector that exactly matches the user's explicit request.\n- An active plugin's invocation guidance provides an exact concrete app ID for a connector required by the user's explicit request.\n\nDo not use it for adjacent capabilities, broad recommendations, or tools that merely seem useful. When using a list result, pass the returned `tool_type` through directly and pass the returned `id` as `tool_id`. When using an active plugin's invocation guidance, use `connector` as `tool_type` and pass the concrete app ID as `tool_id`. Do not pass template IDs such as `templated_apps_*`.\n\nIMPORTANT: DO NOT call this tool in parallel with other tools." ); ToolSpec::Function(ResponsesApiTool { @@ -65,8 +65,10 @@ mod tests { fn create_request_plugin_install_tool_uses_expected_wire_shape() { let expected_description = concat!( "# Request plugin/connector install\n\n", - "Use this tool only after `list_available_plugins_to_install` returns a plugin or connector that exactly matches the user's explicit request.\n\n", - "Do not use it for adjacent capabilities, broad recommendations, or tools that merely seem useful. Pass the returned `tool_type` through directly, and pass the returned `id` as `tool_id`.\n\n", + "Use this tool only when either:\n", + "- `list_available_plugins_to_install` returns a plugin or connector that exactly matches the user's explicit request.\n", + "- An active plugin's invocation guidance provides an exact concrete app ID for a connector required by the user's explicit request.\n\n", + "Do not use it for adjacent capabilities, broad recommendations, or tools that merely seem useful. When using a list result, pass the returned `tool_type` through directly and pass the returned `id` as `tool_id`. When using an active plugin's invocation guidance, use `connector` as `tool_type` and pass the concrete app ID as `tool_id`. Do not pass template IDs such as `templated_apps_*`.\n\n", "IMPORTANT: DO NOT call this tool in parallel with other tools.", ); diff --git a/codex-rs/core/src/tools/spec_plan_tests.rs b/codex-rs/core/src/tools/spec_plan_tests.rs index e059b5f4af..992a26326a 100644 --- a/codex-rs/core/src/tools/spec_plan_tests.rs +++ b/codex-rs/core/src/tools/spec_plan_tests.rs @@ -652,7 +652,7 @@ async fn install_suggestion_tools_stay_visible_without_tool_search() { } #[tokio::test] -async fn request_plugin_install_description_defers_inventory_to_list_tool() { +async fn request_plugin_install_description_accepts_list_or_active_plugin_guidance() { let plan = probe_with( |turn| { set_features( @@ -686,7 +686,10 @@ async fn request_plugin_install_description_defers_inventory_to_list_tool() { panic!("expected request_plugin_install function spec"); }; assert!(request_description.contains( - "Use this tool only after `list_available_plugins_to_install` returns a plugin or connector that exactly matches the user's explicit request." + "- `list_available_plugins_to_install` returns a plugin or connector that exactly matches the user's explicit request." + )); + assert!(request_description.contains( + "- An active plugin's invocation guidance provides an exact concrete app ID for a connector required by the user's explicit request." )); assert!(!request_description.contains("github")); }