@@ -330,43 +330,40 @@ async def execute_tools_and_side_effects(
330330 ItemHelpers .extract_last_text (message_items [- 1 ].raw_item ) if message_items else None
331331 )
332332
333- # There are two possibilities that lead to a final output:
334- # 1. Structured output schema => always leads to a final output
335- # 2. Plain text output schema => only leads to a final output if there are no tool calls
336- if output_schema and not output_schema .is_plain_text () and potential_final_output_text :
337- final_output = output_schema .validate_json (potential_final_output_text )
338- return await cls .execute_final_output (
339- agent = agent ,
340- original_input = original_input ,
341- new_response = new_response ,
342- pre_step_items = pre_step_items ,
343- new_step_items = new_step_items ,
344- final_output = final_output ,
345- hooks = hooks ,
346- context_wrapper = context_wrapper ,
347- )
348- elif (
349- not output_schema or output_schema .is_plain_text ()
350- ) and not processed_response .has_tools_or_approvals_to_run ():
351- return await cls .execute_final_output (
352- agent = agent ,
353- original_input = original_input ,
354- new_response = new_response ,
355- pre_step_items = pre_step_items ,
356- new_step_items = new_step_items ,
357- final_output = potential_final_output_text or "" ,
358- hooks = hooks ,
359- context_wrapper = context_wrapper ,
360- )
361- else :
362- # If there's no final output, we can just run again
363- return SingleStepResult (
364- original_input = original_input ,
365- model_response = new_response ,
366- pre_step_items = pre_step_items ,
367- new_step_items = new_step_items ,
368- next_step = NextStepRunAgain (),
369- )
333+ # Generate final output only when there are no pending tool calls or approval requests.
334+ if not processed_response .has_tools_or_approvals_to_run ():
335+ if output_schema and not output_schema .is_plain_text () and potential_final_output_text :
336+ final_output = output_schema .validate_json (potential_final_output_text )
337+ return await cls .execute_final_output (
338+ agent = agent ,
339+ original_input = original_input ,
340+ new_response = new_response ,
341+ pre_step_items = pre_step_items ,
342+ new_step_items = new_step_items ,
343+ final_output = final_output ,
344+ hooks = hooks ,
345+ context_wrapper = context_wrapper ,
346+ )
347+ elif not output_schema or output_schema .is_plain_text ():
348+ return await cls .execute_final_output (
349+ agent = agent ,
350+ original_input = original_input ,
351+ new_response = new_response ,
352+ pre_step_items = pre_step_items ,
353+ new_step_items = new_step_items ,
354+ final_output = potential_final_output_text or "" ,
355+ hooks = hooks ,
356+ context_wrapper = context_wrapper ,
357+ )
358+
359+ # If there's no final output, we can just run again
360+ return SingleStepResult (
361+ original_input = original_input ,
362+ model_response = new_response ,
363+ pre_step_items = pre_step_items ,
364+ new_step_items = new_step_items ,
365+ next_step = NextStepRunAgain (),
366+ )
370367
371368 @classmethod
372369 def maybe_reset_tool_choice (
0 commit comments