@@ -723,9 +723,10 @@ async def test_azure_ai_client_agent_creation_with_response_format(
723723 mock_agent .version = "1.0"
724724 mock_project_client .agents .create_version = AsyncMock (return_value = mock_agent )
725725
726- run_options = {"model" : "test-model" , "response_format" : ResponseFormatModel }
726+ run_options = {"model" : "test-model" }
727+ chat_options = ChatOptions (response_format = ResponseFormatModel )
727728
728- await client ._get_agent_reference_or_create (run_options , None ) # type: ignore
729+ await client ._get_agent_reference_or_create (run_options , None , chat_options ) # type: ignore
729730
730731 # Verify agent was created with response format configuration
731732 call_args = mock_project_client .agents .create_version .call_args
@@ -776,19 +777,18 @@ async def test_azure_ai_client_agent_creation_with_mapping_response_format(
776777 "additionalProperties" : False ,
777778 }
778779
779- run_options = {
780- "model" : "test-model" ,
781- "response_format" : {
782- "type" : "json_schema" ,
783- "json_schema" : {
784- "name" : runtime_schema ["title" ],
785- "strict" : True ,
786- "schema" : runtime_schema ,
787- },
780+ run_options = {"model" : "test-model" }
781+ response_format_mapping = {
782+ "type" : "json_schema" ,
783+ "json_schema" : {
784+ "name" : runtime_schema ["title" ],
785+ "strict" : True ,
786+ "schema" : runtime_schema ,
788787 },
789788 }
789+ chat_options = ChatOptions (response_format = response_format_mapping ) # type: ignore
790790
791- await client ._get_agent_reference_or_create (run_options , None ) # type: ignore
791+ await client ._get_agent_reference_or_create (run_options , None , chat_options ) # type: ignore
792792
793793 call_args = mock_project_client .agents .create_version .call_args
794794 created_definition = call_args [1 ]["definition" ]
@@ -805,7 +805,7 @@ async def test_azure_ai_client_agent_creation_with_mapping_response_format(
805805async def test_azure_ai_client_prepare_options_excludes_response_format (
806806 mock_project_client : MagicMock ,
807807) -> None :
808- """Test that prepare_options excludes response_format from final run options."""
808+ """Test that prepare_options excludes response_format, text, and text_format from final run options."""
809809 client = create_test_azure_ai_client (mock_project_client , agent_name = "test-agent" , agent_version = "1.0" )
810810
811811 messages = [ChatMessage (role = Role .USER , contents = [TextContent (text = "Hello" )])]
@@ -815,7 +815,12 @@ async def test_azure_ai_client_prepare_options_excludes_response_format(
815815 patch .object (
816816 client .__class__ .__bases__ [0 ],
817817 "_prepare_options" ,
818- return_value = {"model" : "test-model" , "response_format" : ResponseFormatModel },
818+ return_value = {
819+ "model" : "test-model" ,
820+ "response_format" : ResponseFormatModel ,
821+ "text" : {"format" : {"type" : "json_schema" , "name" : "test" }},
822+ "text_format" : ResponseFormatModel ,
823+ },
819824 ),
820825 patch .object (
821826 client ,
@@ -825,8 +830,11 @@ async def test_azure_ai_client_prepare_options_excludes_response_format(
825830 ):
826831 run_options = await client ._prepare_options (messages , chat_options )
827832
828- # response_format should be excluded from final run options
833+ # response_format, text, and text_format should be excluded from final run options
834+ # because they are configured at agent level, not request level
829835 assert "response_format" not in run_options
836+ assert "text" not in run_options
837+ assert "text_format" not in run_options
830838 # But extra_body should contain agent reference
831839 assert "extra_body" in run_options
832840 assert run_options ["extra_body" ]["agent" ]["name" ] == "test-agent"
@@ -1009,3 +1017,91 @@ async def test_azure_ai_chat_client_agent_with_tools() -> None:
10091017 assert response .text is not None
10101018 assert len (response .text ) > 0
10111019 assert any (word in response .text .lower () for word in ["sunny" , "25" ])
1020+
1021+
1022+ class ReleaseBrief (BaseModel ):
1023+ """Structured output model for release brief."""
1024+
1025+ title : str = Field (description = "A short title for the release." )
1026+ summary : str = Field (description = "A brief summary of what was released." )
1027+ highlights : list [str ] = Field (description = "Key highlights from the release." )
1028+ model_config = ConfigDict (extra = "forbid" )
1029+
1030+
1031+ @pytest .mark .flaky
1032+ @skip_if_azure_ai_integration_tests_disabled
1033+ async def test_azure_ai_chat_client_agent_with_response_format () -> None :
1034+ """Test ChatAgent with response_format (structured output) using AzureAIClient."""
1035+ async with (
1036+ temporary_chat_client (agent_name = "ResponseFormatAgent" ) as chat_client ,
1037+ ChatAgent (chat_client = chat_client ) as agent ,
1038+ ):
1039+ response = await agent .run (
1040+ "Summarize the following release notes into a ReleaseBrief:\n \n "
1041+ "Version 2.0 Release Notes:\n "
1042+ "- Added new streaming API for real-time responses\n "
1043+ "- Improved error handling with detailed messages\n "
1044+ "- Performance boost of 50% in batch processing\n "
1045+ "- Fixed memory leak in connection pooling" ,
1046+ response_format = ReleaseBrief ,
1047+ )
1048+
1049+ # Validate response
1050+ assert isinstance (response , AgentRunResponse )
1051+ assert response .value is not None
1052+ assert isinstance (response .value , ReleaseBrief )
1053+
1054+ # Validate structured output fields
1055+ brief = response .value
1056+ assert len (brief .title ) > 0
1057+ assert len (brief .summary ) > 0
1058+ assert len (brief .highlights ) > 0
1059+
1060+
1061+ @pytest .mark .flaky
1062+ @skip_if_azure_ai_integration_tests_disabled
1063+ async def test_azure_ai_chat_client_agent_with_runtime_json_schema () -> None :
1064+ """Test ChatAgent with runtime JSON schema (structured output) using AzureAIClient."""
1065+ runtime_schema = {
1066+ "title" : "WeatherDigest" ,
1067+ "type" : "object" ,
1068+ "properties" : {
1069+ "location" : {"type" : "string" },
1070+ "conditions" : {"type" : "string" },
1071+ "temperature_c" : {"type" : "number" },
1072+ "advisory" : {"type" : "string" },
1073+ },
1074+ "required" : ["location" , "conditions" , "temperature_c" , "advisory" ],
1075+ "additionalProperties" : False ,
1076+ }
1077+
1078+ async with (
1079+ temporary_chat_client (agent_name = "RuntimeSchemaAgent" ) as chat_client ,
1080+ ChatAgent (chat_client = chat_client ) as agent ,
1081+ ):
1082+ response = await agent .run (
1083+ "Give a brief weather digest for Seattle." ,
1084+ additional_chat_options = {
1085+ "response_format" : {
1086+ "type" : "json_schema" ,
1087+ "json_schema" : {
1088+ "name" : runtime_schema ["title" ],
1089+ "strict" : True ,
1090+ "schema" : runtime_schema ,
1091+ },
1092+ },
1093+ },
1094+ )
1095+
1096+ # Validate response
1097+ assert isinstance (response , AgentRunResponse )
1098+ assert response .text is not None
1099+
1100+ # Parse JSON and validate structure
1101+ import json
1102+
1103+ parsed = json .loads (response .text )
1104+ assert "location" in parsed
1105+ assert "conditions" in parsed
1106+ assert "temperature_c" in parsed
1107+ assert "advisory" in parsed
0 commit comments