Skip to content

fix(handoffs): summarize all tool item types in nest_handoff_history#3412

Closed
adityasingh2400 wants to merge 1 commit into
openai:mainfrom
adityasingh2400:fix-nest-handoff-summary-tool-types
Closed

fix(handoffs): summarize all tool item types in nest_handoff_history#3412
adityasingh2400 wants to merge 1 commit into
openai:mainfrom
adityasingh2400:fix-nest-handoff-summary-tool-types

Conversation

@adityasingh2400
Copy link
Copy Markdown
Contributor

Summary

Extends the precedent set by #3095 (custom_tool_call) and #3386 (hosted_tool_call) into the sibling helper that powers RunConfig.nest_handoff_history. The _SUMMARY_ONLY_INPUT_TYPES set in src/agents/handoffs/history.py:30-37 only marked function_call, function_call_output, and reasoning as summarized-only. Every other tool kind the SDK can emit (computer, file_search, web_search, mcp_*, code_interpreter, image_generation, local_shell, shell, apply_patch, custom, hosted, tool_search) was included in the JSON conversation summary built by _format_transcript_item_json and re-forwarded verbatim as a raw RunItem in pre_handoff_items / input_items, duplicating it for the next agent.

Repro (passes pre-fix, fails post-fix without the new set entries):

>>> data = HandoffInputData(
...     input_history=(user_msg,),
...     pre_handoff_items=(custom_tool_call_run_item, custom_tool_output_run_item),
... )
>>> nested = nest_handoff_history(data)
>>> # Summary contains the tool call:
>>> "my_custom" in nested.input_history[0]["content"]
True
>>> # But the raw items also survive, so the next agent sees them twice:
>>> len(nested.pre_handoff_items)
2  # was expected to be 0

The fix expands _SUMMARY_ONLY_INPUT_TYPES to mirror the comprehensive list maintained by extensions.handoff_filters._remove_tool_types_from_input. The two lists exist for adjacent reasons (one for remove_all_tools, one for nest_handoff_history) but should agree on what counts as a tool item; the comment block documents that intent.

Test plan

  • New tests test_nest_handoff_history_filters_hosted_tool_pre_items and test_nest_handoff_history_filters_hosted_tool_new_items in tests/test_extension_filters.py cover every hosted-tool call and output type for both the pre_handoff_items and new_itemsinput_items paths.
  • uv run pytest tests/test_extension_filters.py — 42 passed (was 40, +2 regressions).
  • uv run pytest tests/test_agent_runner.py tests/test_agent_runner_streamed.py -k handoff_history — 7 passed.
  • make format, make lint, uv run mypy src/agents/handoffs/history.py tests/test_extension_filters.py — clean.

Issue number

N/A — found while auditing for the same gap that #3095 and #3386 fixed in the sibling remove_all_tools filter.

The _SUMMARY_ONLY_INPUT_TYPES set in src/agents/handoffs/history.py
only filtered out function_call, function_call_output, and reasoning
from forwarded items after nest_handoff_history built its conversation
summary. Hosted, computer, shell, apply_patch, custom, MCP, file/web/
tool search, code interpreter, and image generation tool calls and
outputs were therefore included in the JSON summary *and* re-forwarded
as raw RunItems, duplicating them for the next agent.

Mirror the comprehensive tool-type list maintained by the sibling
extensions.handoff_filters._remove_tool_types_from_input filter so
every tool kind the SDK can emit (including the recently audited
hosted_tool_call from openai#3386 and the custom_tool_call from openai#3095) is
summarized once and dropped from the forwarded items. Tests in
tests/test_extension_filters.py cover the pre_handoff_items and
input_items (mapped from new_items) paths.
@seratch
Copy link
Copy Markdown
Member

seratch commented May 15, 2026

This may be relevant for some use cases, but it could be a breaking change for existing apps. Thus, we won't make this change.

@seratch seratch closed this May 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants