@@ -1041,6 +1041,98 @@ async def test_max_content_length_tool_result_no_truncation(
10411041 assert content_dict ["tool" ] == "MyTool"
10421042 assert content_dict ["result" ]["res" ] == "A" * 100
10431043
1044+ @pytest .mark .asyncio
1045+ async def test_after_tool_callback_logs_agent_response_for_final_tool (
1046+ self ,
1047+ mock_write_client ,
1048+ tool_context ,
1049+ mock_auth_default ,
1050+ mock_bq_client ,
1051+ mock_to_arrow_schema ,
1052+ dummy_arrow_schema ,
1053+ mock_asyncio_to_thread ,
1054+ ):
1055+ """A configured final-response tool also logs AGENT_RESPONSE from its args."""
1056+ _ = mock_auth_default
1057+ _ = mock_bq_client
1058+ _ = mock_to_arrow_schema
1059+ _ = mock_asyncio_to_thread
1060+ config = bigquery_agent_analytics_plugin .BigQueryLoggerConfig (
1061+ final_response_tool_names = frozenset ({"submit_final_response" })
1062+ )
1063+ async with managed_plugin (
1064+ PROJECT_ID , DATASET_ID , table_id = TABLE_ID , config = config
1065+ ) as plugin :
1066+ await plugin ._ensure_started ()
1067+ mock_write_client .append_rows .reset_mock ()
1068+ mock_tool = mock .create_autospec (
1069+ base_tool_lib .BaseTool , instance = True , spec_set = True
1070+ )
1071+ type(mock_tool ).name = mock .PropertyMock (
1072+ return_value = "submit_final_response"
1073+ )
1074+ bigquery_agent_analytics_plugin .TraceManager .push_span (tool_context )
1075+ await plugin .after_tool_callback (
1076+ tool = mock_tool ,
1077+ tool_args = {"answer" : "The table has 241 rows." },
1078+ tool_context = tool_context ,
1079+ result = {"status" : "SUCCESS" },
1080+ )
1081+ await plugin .flush ()
1082+ rows = await _get_captured_rows_async (
1083+ mock_write_client , dummy_arrow_schema
1084+ )
1085+ event_types = [r ["event_type" ] for r in rows ]
1086+ assert "TOOL_COMPLETED" in event_types
1087+ assert event_types .count ("AGENT_RESPONSE" ) == 1
1088+ agent_resp = next (r for r in rows if r ["event_type" ] == "AGENT_RESPONSE" )
1089+ content_dict = json .loads (agent_resp ["content" ])
1090+ assert content_dict ["response" ] == {"answer" : "The table has 241 rows." }
1091+ attributes = json .loads (agent_resp ["attributes" ])
1092+ assert attributes ["source_tool" ] == "submit_final_response"
1093+
1094+ @pytest .mark .asyncio
1095+ async def test_after_tool_callback_no_agent_response_by_default (
1096+ self ,
1097+ mock_write_client ,
1098+ tool_context ,
1099+ mock_auth_default ,
1100+ mock_bq_client ,
1101+ mock_to_arrow_schema ,
1102+ dummy_arrow_schema ,
1103+ mock_asyncio_to_thread ,
1104+ ):
1105+ """With the default empty set, a tool never emits AGENT_RESPONSE."""
1106+ _ = mock_auth_default
1107+ _ = mock_bq_client
1108+ _ = mock_to_arrow_schema
1109+ _ = mock_asyncio_to_thread
1110+ config = bigquery_agent_analytics_plugin .BigQueryLoggerConfig ()
1111+ async with managed_plugin (
1112+ PROJECT_ID , DATASET_ID , table_id = TABLE_ID , config = config
1113+ ) as plugin :
1114+ await plugin ._ensure_started ()
1115+ mock_write_client .append_rows .reset_mock ()
1116+ mock_tool = mock .create_autospec (
1117+ base_tool_lib .BaseTool , instance = True , spec_set = True
1118+ )
1119+ type(mock_tool ).name = mock .PropertyMock (
1120+ return_value = "submit_final_response"
1121+ )
1122+ bigquery_agent_analytics_plugin .TraceManager .push_span (tool_context )
1123+ await plugin .after_tool_callback (
1124+ tool = mock_tool ,
1125+ tool_args = {"answer" : "hi" },
1126+ tool_context = tool_context ,
1127+ result = {"status" : "SUCCESS" },
1128+ )
1129+ await plugin .flush ()
1130+ rows = await _get_captured_rows_async (
1131+ mock_write_client , dummy_arrow_schema
1132+ )
1133+ event_types = [r ["event_type" ] for r in rows ]
1134+ assert "AGENT_RESPONSE" not in event_types
1135+
10441136 @pytest .mark .asyncio
10451137 async def test_max_content_length_tool_error (
10461138 self ,
0 commit comments