@@ -1224,6 +1224,119 @@ async def test_default_send_all_items_streamed():
12241224 assert function_result .get ("call_id" ) is not None
12251225
12261226
1227+ @pytest .mark .asyncio
1228+ async def test_bootstrap_mode_multi_turn ():
1229+ """Test that bootstrap mode (previous_response_id='bootstrap') enables
1230+ chaining from the first internal turn."""
1231+ model = FakeModel ()
1232+ agent = Agent (
1233+ name = "test" ,
1234+ model = model ,
1235+ tools = [get_function_tool ("test_func" , "tool_result" )],
1236+ )
1237+
1238+ model .add_multiple_turn_outputs (
1239+ [
1240+ # First turn: a message and tool call
1241+ [get_text_message ("a_message" ), get_function_tool_call ("test_func" , '{"arg": "foo"}' )],
1242+ # Second turn: final text message
1243+ [get_text_message ("done" )],
1244+ ]
1245+ )
1246+
1247+ result = await Runner .run (agent , input = "user_message" , previous_response_id = "bootstrap" )
1248+ assert result .final_output == "done"
1249+
1250+ # Check the first call
1251+ assert model .first_turn_args is not None
1252+ first_input = model .first_turn_args ["input" ]
1253+
1254+ # First call should include the original user input
1255+ assert isinstance (first_input , list )
1256+ assert len (first_input ) == 1 # Should contain the user message
1257+
1258+ # The input should be the user message
1259+ user_message = first_input [0 ]
1260+ assert user_message .get ("role" ) == "user"
1261+ assert user_message .get ("content" ) == "user_message"
1262+
1263+ # In bootstrap mode, first call should NOT have previous_response_id
1264+ assert model .first_turn_args .get ("previous_response_id" ) is None
1265+
1266+ # Check the input from the second turn (after function execution)
1267+ last_input = model .last_turn_args ["input" ]
1268+
1269+ # In bootstrap mode, the second turn should only contain the tool output
1270+ assert isinstance (last_input , list )
1271+ assert len (last_input ) == 1 # Only the function result
1272+
1273+ # The single item should be a tool result
1274+ tool_result_item = last_input [0 ]
1275+ assert tool_result_item .get ("type" ) == "function_call_output"
1276+ assert tool_result_item .get ("call_id" ) is not None
1277+
1278+ # In bootstrap mode, second call should have previous_response_id set to the first response
1279+ assert model .last_turn_args .get ("previous_response_id" ) == "resp-789"
1280+
1281+
1282+ @pytest .mark .asyncio
1283+ async def test_bootstrap_mode_multi_turn_streamed ():
1284+ """Test that bootstrap mode (previous_response_id='bootstrap') enables
1285+ chaining from the first internal turn (streamed mode)."""
1286+ model = FakeModel ()
1287+ agent = Agent (
1288+ name = "test" ,
1289+ model = model ,
1290+ tools = [get_function_tool ("test_func" , "tool_result" )],
1291+ )
1292+
1293+ model .add_multiple_turn_outputs (
1294+ [
1295+ # First turn: a message and tool call
1296+ [get_text_message ("a_message" ), get_function_tool_call ("test_func" , '{"arg": "foo"}' )],
1297+ # Second turn: final text message
1298+ [get_text_message ("done" )],
1299+ ]
1300+ )
1301+
1302+ result = Runner .run_streamed (agent , input = "user_message" , previous_response_id = "bootstrap" )
1303+ async for _ in result .stream_events ():
1304+ pass
1305+
1306+ assert result .final_output == "done"
1307+
1308+ # Check the first call
1309+ assert model .first_turn_args is not None
1310+ first_input = model .first_turn_args ["input" ]
1311+
1312+ # First call should include the original user input
1313+ assert isinstance (first_input , list )
1314+ assert len (first_input ) == 1 # Should contain the user message
1315+
1316+ # The input should be the user message
1317+ user_message = first_input [0 ]
1318+ assert user_message .get ("role" ) == "user"
1319+ assert user_message .get ("content" ) == "user_message"
1320+
1321+ # In bootstrap mode, first call should NOT have previous_response_id
1322+ assert model .first_turn_args .get ("previous_response_id" ) is None
1323+
1324+ # Check the input from the second turn (after function execution)
1325+ last_input = model .last_turn_args ["input" ]
1326+
1327+ # In bootstrap mode, the second turn should only contain the tool output
1328+ assert isinstance (last_input , list )
1329+ assert len (last_input ) == 1 # Only the function result
1330+
1331+ # The single item should be a tool result
1332+ tool_result_item = last_input [0 ]
1333+ assert tool_result_item .get ("type" ) == "function_call_output"
1334+ assert tool_result_item .get ("call_id" ) is not None
1335+
1336+ # In bootstrap mode, second call should have previous_response_id set to the first response
1337+ assert model .last_turn_args .get ("previous_response_id" ) == "resp-789"
1338+
1339+
12271340@pytest .mark .asyncio
12281341async def test_dynamic_tool_addition_run () -> None :
12291342 """Test that tools can be added to an agent during a run."""
0 commit comments