11
11
AgentToolUseTracker ,
12
12
NextStepFinalOutput ,
13
13
NextStepHandoff ,
14
+ NextStepHandoffReturnControl ,
14
15
NextStepRunAgain ,
15
16
QueueCompleteSentinel ,
16
17
RunImpl ,
@@ -119,6 +120,7 @@ async def run(
119
120
hooks : RunHooks [TContext ] | None = None ,
120
121
run_config : RunConfig | None = None ,
121
122
previous_response_id : str | None = None ,
123
+ previous_agents : list [Agent [TContext ]] | None = None ,
122
124
) -> RunResult :
123
125
"""Run a workflow starting at the given agent. The agent will run in a loop until a final
124
126
output is generated. The loop runs like so:
@@ -154,6 +156,8 @@ async def run(
154
156
hooks = RunHooks [Any ]()
155
157
if run_config is None :
156
158
run_config = RunConfig ()
159
+ if previous_agents is None :
160
+ previous_agents = []
157
161
158
162
tool_use_tracker = AgentToolUseTracker ()
159
163
@@ -235,6 +239,7 @@ async def run(
235
239
should_run_agent_start_hooks = should_run_agent_start_hooks ,
236
240
tool_use_tracker = tool_use_tracker ,
237
241
previous_response_id = previous_response_id ,
242
+ previous_agents = previous_agents ,
238
243
),
239
244
)
240
245
else :
@@ -249,6 +254,7 @@ async def run(
249
254
should_run_agent_start_hooks = should_run_agent_start_hooks ,
250
255
tool_use_tracker = tool_use_tracker ,
251
256
previous_response_id = previous_response_id ,
257
+ previous_agents = previous_agents ,
252
258
)
253
259
should_run_agent_start_hooks = False
254
260
@@ -273,8 +279,13 @@ async def run(
273
279
output_guardrail_results = output_guardrail_results ,
274
280
context_wrapper = context_wrapper ,
275
281
)
276
- elif isinstance (turn_result .next_step , NextStepHandoff ):
277
- current_agent = cast (Agent [TContext ], turn_result .next_step .new_agent )
282
+ elif isinstance (turn_result .next_step , NextStepHandoff ) or isinstance (
283
+ turn_result .next_step , NextStepHandoffReturnControl
284
+ ):
285
+ if isinstance (turn_result .next_step , NextStepHandoffReturnControl ):
286
+ current_agent = turn_result .next_step .previous_agent
287
+ else :
288
+ current_agent = cast (Agent [TContext ], turn_result .next_step .new_agent )
278
289
current_span .finish (reset_current = True )
279
290
current_span = None
280
291
should_run_agent_start_hooks = True
@@ -367,6 +378,7 @@ def run_streamed(
367
378
hooks : RunHooks [TContext ] | None = None ,
368
379
run_config : RunConfig | None = None ,
369
380
previous_response_id : str | None = None ,
381
+ previous_agents : list [Agent [TContext ]] | None = None ,
370
382
) -> RunResultStreaming :
371
383
"""Run a workflow starting at the given agent in streaming mode. The returned result object
372
384
contains a method you can use to stream semantic events as they are generated.
@@ -402,6 +414,8 @@ def run_streamed(
402
414
hooks = RunHooks [Any ]()
403
415
if run_config is None :
404
416
run_config = RunConfig ()
417
+ if previous_agents is None :
418
+ previous_agents = []
405
419
406
420
# If there's already a trace, we don't create a new one. In addition, we can't end the
407
421
# trace here, because the actual work is done in `stream_events` and this method ends
@@ -450,6 +464,7 @@ def run_streamed(
450
464
context_wrapper = context_wrapper ,
451
465
run_config = run_config ,
452
466
previous_response_id = previous_response_id ,
467
+ previous_agents = previous_agents ,
453
468
)
454
469
)
455
470
return streamed_result
@@ -508,6 +523,7 @@ async def _run_streamed_impl(
508
523
context_wrapper : RunContextWrapper [TContext ],
509
524
run_config : RunConfig ,
510
525
previous_response_id : str | None ,
526
+ previous_agents : list [Agent [TContext ]],
511
527
):
512
528
if streamed_result .trace :
513
529
streamed_result .trace .start (mark_as_current = True )
@@ -581,6 +597,7 @@ async def _run_streamed_impl(
581
597
tool_use_tracker ,
582
598
all_tools ,
583
599
previous_response_id ,
600
+ previous_agents ,
584
601
)
585
602
should_run_agent_start_hooks = False
586
603
@@ -590,8 +607,14 @@ async def _run_streamed_impl(
590
607
streamed_result .input = turn_result .original_input
591
608
streamed_result .new_items = turn_result .generated_items
592
609
593
- if isinstance (turn_result .next_step , NextStepHandoff ):
594
- current_agent = turn_result .next_step .new_agent
610
+ if isinstance (turn_result .next_step , NextStepHandoff ) or isinstance (
611
+ turn_result .next_step , NextStepHandoffReturnControl
612
+ ):
613
+ if isinstance (turn_result .next_step , NextStepHandoff ):
614
+ current_agent = turn_result .next_step .new_agent
615
+ else :
616
+ current_agent = turn_result .next_step .previous_agent
617
+
595
618
current_span .finish (reset_current = True )
596
619
current_span = None
597
620
should_run_agent_start_hooks = True
@@ -666,6 +689,7 @@ async def _run_single_turn_streamed(
666
689
tool_use_tracker : AgentToolUseTracker ,
667
690
all_tools : list [Tool ],
668
691
previous_response_id : str | None ,
692
+ previous_agents : list [Agent [TContext ]],
669
693
) -> SingleStepResult :
670
694
if should_run_agent_start_hooks :
671
695
await asyncio .gather (
@@ -746,6 +770,7 @@ async def _run_single_turn_streamed(
746
770
context_wrapper = context_wrapper ,
747
771
run_config = run_config ,
748
772
tool_use_tracker = tool_use_tracker ,
773
+ previous_agents = previous_agents ,
749
774
)
750
775
751
776
RunImpl .stream_step_result_to_queue (single_step_result , streamed_result ._event_queue )
@@ -765,6 +790,7 @@ async def _run_single_turn(
765
790
should_run_agent_start_hooks : bool ,
766
791
tool_use_tracker : AgentToolUseTracker ,
767
792
previous_response_id : str | None ,
793
+ previous_agents : list [Agent [TContext ]],
768
794
) -> SingleStepResult :
769
795
# Ensure we run the hooks before anything else
770
796
if should_run_agent_start_hooks :
@@ -809,6 +835,7 @@ async def _run_single_turn(
809
835
context_wrapper = context_wrapper ,
810
836
run_config = run_config ,
811
837
tool_use_tracker = tool_use_tracker ,
838
+ previous_agents = previous_agents ,
812
839
)
813
840
814
841
@classmethod
@@ -826,6 +853,7 @@ async def _get_single_step_result_from_response(
826
853
context_wrapper : RunContextWrapper [TContext ],
827
854
run_config : RunConfig ,
828
855
tool_use_tracker : AgentToolUseTracker ,
856
+ previous_agents : list [Agent [TContext ]],
829
857
) -> SingleStepResult :
830
858
processed_response = RunImpl .process_model_response (
831
859
agent = agent ,
@@ -847,6 +875,7 @@ async def _get_single_step_result_from_response(
847
875
hooks = hooks ,
848
876
context_wrapper = context_wrapper ,
849
877
run_config = run_config ,
878
+ previous_agents = previous_agents ,
850
879
)
851
880
852
881
@classmethod
0 commit comments