@@ -783,7 +783,7 @@ fn apply_chat_model_settings(
783783 payload. insert ( "parallel_tool_calls" . to_owned ( ) , json ! ( value) ) ;
784784 }
785785 if let Some ( value) = & settings. tool_choice {
786- payload. insert ( "tool_choice" . to_owned ( ) , Value :: String ( value. clone ( ) ) ) ;
786+ payload. insert ( "tool_choice" . to_owned ( ) , chat_tool_choice_value ( value) ) ;
787787 } else if has_tools {
788788 payload. insert ( "tool_choice" . to_owned ( ) , Value :: String ( "auto" . to_owned ( ) ) ) ;
789789 }
@@ -797,6 +797,18 @@ fn apply_chat_model_settings(
797797 Ok ( ( ) )
798798}
799799
800+ fn chat_tool_choice_value ( tool_choice : & str ) -> Value {
801+ match tool_choice {
802+ "auto" | "required" | "none" => Value :: String ( tool_choice. to_owned ( ) ) ,
803+ _ => json ! ( {
804+ "type" : "function" ,
805+ "function" : {
806+ "name" : tool_choice,
807+ } ,
808+ } ) ,
809+ }
810+ }
811+
800812fn validate_extra_body_keys (
801813 extra_body : & std:: collections:: BTreeMap < String , Value > ,
802814 reserved : & [ & str ] ,
@@ -2077,6 +2089,43 @@ mod tests {
20772089 assert_eq ! ( payload[ "tool_choice" ] , "auto" ) ;
20782090 }
20792091
2092+ #[ test]
2093+ fn chat_payload_converts_named_function_tool_choice ( ) {
2094+ let model = OpenAIChatCompletionsModel :: new (
2095+ "gpt-4.1" ,
2096+ OpenAIClientOptions :: new ( Some ( "sk-test" . to_owned ( ) ) ) ,
2097+ ) ;
2098+ let payload = model
2099+ . build_payload ( & ModelRequest {
2100+ model : Some ( "gpt-4.1" . to_owned ( ) ) ,
2101+ instructions : None ,
2102+ previous_response_id : None ,
2103+ conversation_id : None ,
2104+ settings : agents_core:: ModelSettings {
2105+ tool_choice : Some ( "search" . to_owned ( ) ) ,
2106+ ..Default :: default ( )
2107+ } ,
2108+ input : vec ! [ InputItem :: from( "hello" ) ] ,
2109+ tools : vec ! [
2110+ ToolDefinition :: new( "search" , "Search" )
2111+ . with_input_json_schema( json!( { "type" : "object" } ) ) ,
2112+ ] ,
2113+ output_schema : None ,
2114+ trace_id : None ,
2115+ } )
2116+ . expect ( "chat payload should build" ) ;
2117+
2118+ assert_eq ! (
2119+ payload[ "tool_choice" ] ,
2120+ json!( {
2121+ "type" : "function" ,
2122+ "function" : {
2123+ "name" : "search"
2124+ }
2125+ } )
2126+ ) ;
2127+ }
2128+
20802129 #[ test]
20812130 fn chat_payload_ignores_server_managed_state_by_default ( ) {
20822131 let model = OpenAIChatCompletionsModel :: new (
0 commit comments