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 ,
@@ -282,6 +282,38 @@ async def execute_final_output(
282282 )
283283
284284
285+ def _resolve_server_managed_handoff_behavior (
286+ * ,
287+ handoff : Handoff [Any , Agent [Any ]],
288+ from_agent : Agent [Any ],
289+ to_agent : Agent [Any ],
290+ run_config : RunConfig ,
291+ server_manages_conversation : bool ,
292+ input_filter : HandoffInputFilter | None ,
293+ should_nest_history : bool ,
294+ ) -> tuple [HandoffInputFilter | None , bool ]:
295+ if not server_manages_conversation :
296+ return input_filter , should_nest_history
297+
298+ if input_filter is not None :
299+ raise UserError (
300+ "Server-managed conversations do not support handoff input filters. "
301+ "Remove Handoff.input_filter or RunConfig.handoff_input_filter, "
302+ "or disable conversation_id, previous_response_id, and auto_previous_response_id."
303+ )
304+
305+ if not should_nest_history :
306+ return input_filter , should_nest_history
307+
308+ logger .warning (
309+ "Server-managed conversations do not support nest_handoff_history for handoff "
310+ "%s -> %s. Disabling nested handoff history and continuing with delta-only input." ,
311+ from_agent .name ,
312+ to_agent .name ,
313+ )
314+ return input_filter , False
315+
316+
285317async def execute_handoffs (
286318 * ,
287319 agent : Agent [TContext ],
@@ -293,6 +325,7 @@ async def execute_handoffs(
293325 hooks : RunHooks [TContext ],
294326 context_wrapper : RunContextWrapper [TContext ],
295327 run_config : RunConfig ,
328+ server_manages_conversation : bool = False ,
296329 nest_handoff_history_fn : Callable [..., HandoffInputData ] | None = None ,
297330) -> SingleStepResult :
298331 """Execute a handoff and prepare the next turn for the new agent."""
@@ -372,6 +405,15 @@ def nest_history(data: HandoffInputData, mapper: Any | None = None) -> HandoffIn
372405 if handoff_nest_setting is not None
373406 else run_config .nest_handoff_history
374407 )
408+ input_filter , should_nest_history = _resolve_server_managed_handoff_behavior (
409+ handoff = handoff ,
410+ from_agent = agent ,
411+ to_agent = new_agent ,
412+ run_config = run_config ,
413+ server_manages_conversation = server_manages_conversation ,
414+ input_filter = input_filter ,
415+ should_nest_history = should_nest_history ,
416+ )
375417 handoff_input_data : HandoffInputData | None = None
376418 session_step_items : list [RunItem ] | None = None
377419 if input_filter or should_nest_history :
@@ -507,6 +549,7 @@ async def execute_tools_and_side_effects(
507549 hooks : RunHooks [TContext ],
508550 context_wrapper : RunContextWrapper [TContext ],
509551 run_config : RunConfig ,
552+ server_manages_conversation : bool = False ,
510553) -> SingleStepResult :
511554 """Run one turn of the loop, coordinating tools, approvals, guardrails, and handoffs."""
512555
@@ -596,6 +639,7 @@ async def execute_tools_and_side_effects(
596639 hooks = hooks ,
597640 context_wrapper = context_wrapper ,
598641 run_config = run_config ,
642+ server_manages_conversation = server_manages_conversation ,
599643 )
600644
601645 tool_final_output = await _maybe_finalize_from_tool_results (
@@ -672,6 +716,7 @@ async def resolve_interrupted_turn(
672716 hooks : RunHooks [TContext ],
673717 context_wrapper : RunContextWrapper [TContext ],
674718 run_config : RunConfig ,
719+ server_manages_conversation : bool = False ,
675720 run_state : RunState | None = None ,
676721 nest_handoff_history_fn : Callable [..., HandoffInputData ] | None = None ,
677722) -> SingleStepResult :
@@ -1241,6 +1286,7 @@ def _add_unmatched_pending(approval: ToolApprovalItem) -> None:
12411286 hooks = hooks ,
12421287 context_wrapper = context_wrapper ,
12431288 run_config = run_config ,
1289+ server_manages_conversation = server_manages_conversation ,
12441290 nest_handoff_history_fn = nest_history ,
12451291 )
12461292
@@ -1695,6 +1741,7 @@ async def get_single_step_result_from_response(
16951741 context_wrapper : RunContextWrapper [TContext ],
16961742 run_config : RunConfig ,
16971743 tool_use_tracker ,
1744+ server_manages_conversation : bool = False ,
16981745 event_queue : asyncio .Queue [StreamEvent | QueueCompleteSentinel ] | None = None ,
16991746) -> SingleStepResult :
17001747 processed_response = process_model_response (
@@ -1725,4 +1772,5 @@ async def get_single_step_result_from_response(
17251772 hooks = hooks ,
17261773 context_wrapper = context_wrapper ,
17271774 run_config = run_config ,
1775+ server_manages_conversation = server_manages_conversation ,
17281776 )
0 commit comments