4343from ..agent_output import AgentOutputSchemaBase
4444from ..agent_tool_state import get_agent_tool_state_scope , peek_agent_tool_run_result
4545from ..exceptions import ModelBehaviorError , UserError
46- from ..handoffs import Handoff , HandoffInputData , nest_handoff_history
46+ from ..handoffs import Handoff , HandoffInputData , HandoffInputFilter , nest_handoff_history
4747from ..items import (
4848 CompactionItem ,
4949 HandoffCallItem ,
@@ -285,6 +285,38 @@ async def execute_final_output(
285285 )
286286
287287
288+ def _resolve_server_managed_handoff_behavior (
289+ * ,
290+ handoff : Handoff [Any , Agent [Any ]],
291+ from_agent : Agent [Any ],
292+ to_agent : Agent [Any ],
293+ run_config : RunConfig ,
294+ server_manages_conversation : bool ,
295+ input_filter : HandoffInputFilter | None ,
296+ should_nest_history : bool ,
297+ ) -> tuple [HandoffInputFilter | None , bool ]:
298+ if not server_manages_conversation :
299+ return input_filter , should_nest_history
300+
301+ if input_filter is not None :
302+ raise UserError (
303+ "Server-managed conversations do not support handoff input filters. "
304+ "Remove Handoff.input_filter or RunConfig.handoff_input_filter, "
305+ "or disable conversation_id, previous_response_id, and auto_previous_response_id."
306+ )
307+
308+ if not should_nest_history :
309+ return input_filter , should_nest_history
310+
311+ logger .warning (
312+ "Server-managed conversations do not support nest_handoff_history for handoff "
313+ "%s -> %s. Disabling nested handoff history and continuing with delta-only input." ,
314+ from_agent .name ,
315+ to_agent .name ,
316+ )
317+ return input_filter , False
318+
319+
288320async def execute_handoffs (
289321 * ,
290322 public_agent : Agent [TContext ],
@@ -296,6 +328,7 @@ async def execute_handoffs(
296328 hooks : RunHooks [TContext ],
297329 context_wrapper : RunContextWrapper [TContext ],
298330 run_config : RunConfig ,
331+ server_manages_conversation : bool = False ,
299332 nest_handoff_history_fn : Callable [..., HandoffInputData ] | None = None ,
300333) -> SingleStepResult :
301334 """Execute a handoff and prepare the next turn for the new agent."""
@@ -375,6 +408,15 @@ def nest_history(data: HandoffInputData, mapper: Any | None = None) -> HandoffIn
375408 if handoff_nest_setting is not None
376409 else run_config .nest_handoff_history
377410 )
411+ input_filter , should_nest_history = _resolve_server_managed_handoff_behavior (
412+ handoff = handoff ,
413+ from_agent = public_agent ,
414+ to_agent = new_agent ,
415+ run_config = run_config ,
416+ server_manages_conversation = server_manages_conversation ,
417+ input_filter = input_filter ,
418+ should_nest_history = should_nest_history ,
419+ )
378420 handoff_input_data : HandoffInputData | None = None
379421 session_step_items : list [RunItem ] | None = None
380422 if input_filter or should_nest_history :
@@ -510,6 +552,7 @@ async def execute_tools_and_side_effects(
510552 hooks : RunHooks [TContext ],
511553 context_wrapper : RunContextWrapper [TContext ],
512554 run_config : RunConfig ,
555+ server_manages_conversation : bool = False ,
513556) -> SingleStepResult :
514557 """Run one turn of the loop, coordinating tools, approvals, guardrails, and handoffs."""
515558 public_agent = bindings .public_agent
@@ -603,6 +646,7 @@ async def execute_tools_and_side_effects(
603646 hooks = hooks ,
604647 context_wrapper = context_wrapper ,
605648 run_config = run_config ,
649+ server_manages_conversation = server_manages_conversation ,
606650 )
607651
608652 tool_final_output = await _maybe_finalize_from_tool_results (
@@ -679,6 +723,7 @@ async def resolve_interrupted_turn(
679723 hooks : RunHooks [TContext ],
680724 context_wrapper : RunContextWrapper [TContext ],
681725 run_config : RunConfig ,
726+ server_manages_conversation : bool = False ,
682727 run_state : RunState | None = None ,
683728 nest_handoff_history_fn : Callable [..., HandoffInputData ] | None = None ,
684729) -> SingleStepResult :
@@ -1337,6 +1382,7 @@ def _add_unmatched_pending(approval: ToolApprovalItem) -> None:
13371382 hooks = hooks ,
13381383 context_wrapper = context_wrapper ,
13391384 run_config = run_config ,
1385+ server_manages_conversation = server_manages_conversation ,
13401386 nest_handoff_history_fn = nest_history ,
13411387 )
13421388
@@ -1807,6 +1853,7 @@ async def get_single_step_result_from_response(
18071853 context_wrapper : RunContextWrapper [TContext ],
18081854 run_config : RunConfig ,
18091855 tool_use_tracker ,
1856+ server_manages_conversation : bool = False ,
18101857 event_queue : asyncio .Queue [StreamEvent | QueueCompleteSentinel ] | None = None ,
18111858) -> SingleStepResult :
18121859 item_agent = bindings .public_agent
@@ -1838,4 +1885,5 @@ async def get_single_step_result_from_response(
18381885 hooks = hooks ,
18391886 context_wrapper = context_wrapper ,
18401887 run_config = run_config ,
1888+ server_manages_conversation = server_manages_conversation ,
18411889 )
0 commit comments