@@ -41,6 +41,10 @@ use codex_protocol::protocol::SandboxPolicy;
4141use codex_protocol:: protocol:: SessionSource ;
4242use codex_protocol:: protocol:: SubAgentSource ;
4343use codex_tools:: CommandToolOptions ;
44+ use codex_tools:: FreeformTool ;
45+ use codex_tools:: FreeformToolFormat ;
46+ use codex_tools:: ResponsesApiNamespace ;
47+ use codex_tools:: ResponsesApiNamespaceTool ;
4448use codex_tools:: ResponsesApiTool ;
4549use codex_tools:: ShellToolOptions ;
4650use codex_tools:: SpawnAgentToolOptions ;
@@ -86,6 +90,7 @@ use serde::Serialize;
8690use std:: collections:: BTreeMap ;
8791use std:: collections:: HashMap ;
8892use std:: path:: PathBuf ;
93+ use std:: sync:: Arc ;
8994use std:: sync:: LazyLock ;
9095
9196pub type JsonSchema = codex_tools:: JsonSchema ;
@@ -96,6 +101,8 @@ pub(crate) use codex_tools::mcp_call_tool_result_output_schema;
96101const TOOL_SEARCH_DESCRIPTION_TEMPLATE_SOURCE : & str =
97102 include_str ! ( "../../templates/search_tool/tool_description.md" ) ;
98103const TOOL_SEARCH_DESCRIPTION_TEMPLATE_KEY : & str = "app_descriptions" ;
104+ const AGENT_TOOLS_NAMESPACE : & str = "agents" ;
105+ const AGENT_TOOLS_NAMESPACE_DESCRIPTION : & str = "Agent collaboration tools for spawning, messaging, waiting on, listing, and closing subagents." ;
99106static TOOL_SEARCH_DESCRIPTION_TEMPLATE : LazyLock < Template > = LazyLock :: new ( || {
100107 Template :: parse ( TOOL_SEARCH_DESCRIPTION_TEMPLATE_SOURCE )
101108 . unwrap_or_else ( |err| panic ! ( "tool_search description template must parse: {err}" ) )
@@ -390,7 +397,10 @@ fn create_tool_search_tool(app_tools: &HashMap<String, ToolInfo>) -> ToolSpec {
390397 } ,
391398 ) ,
392399 ] ) ;
393- let mut app_descriptions = BTreeMap :: new ( ) ;
400+ let mut app_descriptions = BTreeMap :: from ( [ (
401+ AGENT_TOOLS_NAMESPACE . to_string ( ) ,
402+ Some ( AGENT_TOOLS_NAMESPACE_DESCRIPTION . to_string ( ) ) ,
403+ ) ] ) ;
394404 for tool in app_tools. values ( ) {
395405 if tool. server_name != CODEX_APPS_MCP_SERVER_NAME {
396406 continue ;
@@ -611,6 +621,30 @@ fn push_tool_spec(
611621 }
612622}
613623
624+ fn create_agent_tools_namespace ( tools : Vec < ToolSpec > ) -> ToolSpec {
625+ let tools = tools
626+ . into_iter ( )
627+ . filter_map ( |tool| match tool {
628+ ToolSpec :: Function ( tool) => Some ( ResponsesApiNamespaceTool :: Function ( tool) ) ,
629+ _ => None ,
630+ } )
631+ . collect ( ) ;
632+
633+ ToolSpec :: Namespace ( ResponsesApiNamespace {
634+ name : AGENT_TOOLS_NAMESPACE . to_string ( ) ,
635+ description : AGENT_TOOLS_NAMESPACE_DESCRIPTION . to_string ( ) ,
636+ tools,
637+ } )
638+ }
639+
640+ fn register_agent_tool_handler < H > ( builder : & mut ToolRegistryBuilder , name : & str , handler : Arc < H > )
641+ where
642+ H : crate :: tools:: registry:: ToolHandler + ' static ,
643+ {
644+ builder. register_handler ( name, handler. clone ( ) ) ;
645+ builder. register_handler ( tool_handler_key ( name, Some ( AGENT_TOOLS_NAMESPACE ) ) , handler) ;
646+ }
647+
614648/// Builds the tool registry builder while collecting tool specs for later serialization.
615649#[ cfg( test) ]
616650pub ( crate ) fn build_specs (
@@ -665,8 +699,6 @@ pub(crate) fn build_specs_with_discoverable_tools(
665699 use crate :: tools:: handlers:: multi_agents_v2:: SendMessageHandler as SendMessageHandlerV2 ;
666700 use crate :: tools:: handlers:: multi_agents_v2:: SpawnAgentHandler as SpawnAgentHandlerV2 ;
667701 use crate :: tools:: handlers:: multi_agents_v2:: WaitAgentHandler as WaitAgentHandlerV2 ;
668- use std:: sync:: Arc ;
669-
670702 let mut builder = ToolRegistryBuilder :: new ( ) ;
671703
672704 let shell_handler = Arc :: new ( ShellHandler ) ;
@@ -855,9 +887,8 @@ pub(crate) fn build_specs_with_discoverable_tools(
855887 builder. register_handler ( "request_permissions" , request_permissions_handler) ;
856888 }
857889
858- if config. search_tool
859- && let Some ( app_tools) = app_tools
860- {
890+ if config. search_tool && ( app_tools. is_some ( ) || config. collab_tools ) {
891+ let app_tools = app_tools. unwrap_or_default ( ) ;
861892 let search_tool_handler = Arc :: new ( ToolSearchHandler :: new ( app_tools. clone ( ) ) ) ;
862893 push_tool_spec (
863894 & mut builder,
@@ -1001,102 +1032,67 @@ pub(crate) fn build_specs_with_discoverable_tools(
10011032
10021033 if config. collab_tools {
10031034 if config. multi_agent_v2 {
1004- push_tool_spec (
1005- & mut builder,
1035+ let agent_tools = vec ! [
10061036 create_spawn_agent_tool_v2( SpawnAgentToolOptions {
10071037 available_models: & config. available_models,
10081038 agent_type_description: crate :: agent:: role:: spawn_tool_spec:: build(
10091039 & config. agent_roles,
10101040 ) ,
10111041 } ) ,
1012- /*supports_parallel_tool_calls*/ false ,
1013- config. code_mode_enabled ,
1014- ) ;
1015- push_tool_spec (
1016- & mut builder,
10171042 create_send_message_tool( ) ,
1018- /*supports_parallel_tool_calls*/ false ,
1019- config. code_mode_enabled ,
1020- ) ;
1021- push_tool_spec (
1022- & mut builder,
10231043 create_assign_task_tool( ) ,
1024- /*supports_parallel_tool_calls*/ false ,
1025- config. code_mode_enabled ,
1026- ) ;
1027- push_tool_spec (
1028- & mut builder,
10291044 create_wait_agent_tool_v2( WaitAgentTimeoutOptions {
10301045 default_timeout_ms: DEFAULT_WAIT_TIMEOUT_MS ,
10311046 min_timeout_ms: MIN_WAIT_TIMEOUT_MS ,
10321047 max_timeout_ms: MAX_WAIT_TIMEOUT_MS ,
10331048 } ) ,
1034- /*supports_parallel_tool_calls*/ false ,
1035- config . code_mode_enabled ,
1036- ) ;
1049+ create_close_agent_tool_v2 ( ) ,
1050+ create_list_agents_tool ( ) ,
1051+ ] ;
10371052 push_tool_spec (
10381053 & mut builder,
1039- create_close_agent_tool_v2 ( ) ,
1054+ create_agent_tools_namespace ( agent_tools ) ,
10401055 /*supports_parallel_tool_calls*/ false ,
10411056 config. code_mode_enabled ,
10421057 ) ;
1043- push_tool_spec (
1058+ register_agent_tool_handler ( & mut builder, "spawn_agent" , Arc :: new ( SpawnAgentHandlerV2 ) ) ;
1059+ register_agent_tool_handler (
10441060 & mut builder,
1045- create_list_agents_tool ( ) ,
1046- /*supports_parallel_tool_calls*/ false ,
1047- config. code_mode_enabled ,
1061+ "send_message" ,
1062+ Arc :: new ( SendMessageHandlerV2 ) ,
10481063 ) ;
1049- builder. register_handler ( "spawn_agent" , Arc :: new ( SpawnAgentHandlerV2 ) ) ;
1050- builder. register_handler ( "send_message" , Arc :: new ( SendMessageHandlerV2 ) ) ;
1051- builder. register_handler ( "assign_task" , Arc :: new ( AssignTaskHandlerV2 ) ) ;
1052- builder. register_handler ( "wait_agent" , Arc :: new ( WaitAgentHandlerV2 ) ) ;
1053- builder. register_handler ( "close_agent" , Arc :: new ( CloseAgentHandlerV2 ) ) ;
1054- builder. register_handler ( "list_agents" , Arc :: new ( ListAgentsHandlerV2 ) ) ;
1064+ register_agent_tool_handler ( & mut builder, "assign_task" , Arc :: new ( AssignTaskHandlerV2 ) ) ;
1065+ register_agent_tool_handler ( & mut builder, "wait_agent" , Arc :: new ( WaitAgentHandlerV2 ) ) ;
1066+ register_agent_tool_handler ( & mut builder, "close_agent" , Arc :: new ( CloseAgentHandlerV2 ) ) ;
1067+ register_agent_tool_handler ( & mut builder, "list_agents" , Arc :: new ( ListAgentsHandlerV2 ) ) ;
10551068 } else {
1056- push_tool_spec (
1057- & mut builder,
1069+ let agent_tools = vec ! [
10581070 create_spawn_agent_tool_v1( SpawnAgentToolOptions {
10591071 available_models: & config. available_models,
10601072 agent_type_description: crate :: agent:: role:: spawn_tool_spec:: build(
10611073 & config. agent_roles,
10621074 ) ,
10631075 } ) ,
1064- /*supports_parallel_tool_calls*/ false ,
1065- config. code_mode_enabled ,
1066- ) ;
1067- push_tool_spec (
1068- & mut builder,
10691076 create_send_input_tool_v1( ) ,
1070- /*supports_parallel_tool_calls*/ false ,
1071- config. code_mode_enabled ,
1072- ) ;
1073- push_tool_spec (
1074- & mut builder,
10751077 create_resume_agent_tool( ) ,
1076- /*supports_parallel_tool_calls*/ false ,
1077- config. code_mode_enabled ,
1078- ) ;
1079- builder. register_handler ( "resume_agent" , Arc :: new ( ResumeAgentHandler ) ) ;
1080- push_tool_spec (
1081- & mut builder,
10821078 create_wait_agent_tool_v1( WaitAgentTimeoutOptions {
10831079 default_timeout_ms: DEFAULT_WAIT_TIMEOUT_MS ,
10841080 min_timeout_ms: MIN_WAIT_TIMEOUT_MS ,
10851081 max_timeout_ms: MAX_WAIT_TIMEOUT_MS ,
10861082 } ) ,
1087- /*supports_parallel_tool_calls*/ false ,
1088- config. code_mode_enabled ,
1089- ) ;
1083+ create_close_agent_tool_v1( ) ,
1084+ ] ;
10901085 push_tool_spec (
10911086 & mut builder,
1092- create_close_agent_tool_v1 ( ) ,
1087+ create_agent_tools_namespace ( agent_tools ) ,
10931088 /*supports_parallel_tool_calls*/ false ,
10941089 config. code_mode_enabled ,
10951090 ) ;
1096- builder. register_handler ( "spawn_agent" , Arc :: new ( SpawnAgentHandler ) ) ;
1097- builder. register_handler ( "send_input" , Arc :: new ( SendInputHandler ) ) ;
1098- builder. register_handler ( "wait_agent" , Arc :: new ( WaitAgentHandler ) ) ;
1099- builder. register_handler ( "close_agent" , Arc :: new ( CloseAgentHandler ) ) ;
1091+ register_agent_tool_handler ( & mut builder, "spawn_agent" , Arc :: new ( SpawnAgentHandler ) ) ;
1092+ register_agent_tool_handler ( & mut builder, "send_input" , Arc :: new ( SendInputHandler ) ) ;
1093+ register_agent_tool_handler ( & mut builder, "resume_agent" , Arc :: new ( ResumeAgentHandler ) ) ;
1094+ register_agent_tool_handler ( & mut builder, "wait_agent" , Arc :: new ( WaitAgentHandler ) ) ;
1095+ register_agent_tool_handler ( & mut builder, "close_agent" , Arc :: new ( CloseAgentHandler ) ) ;
11001096 }
11011097 }
11021098
0 commit comments