Skip to content

fix(items): empty list/tuple tool output dropped via all([]) == True#3554

Open
vidigoat wants to merge 1 commit into
openai:mainfrom
vidigoat:fix-empty-list-tool-output
Open

fix(items): empty list/tuple tool output dropped via all([]) == True#3554
vidigoat wants to merge 1 commit into
openai:mainfrom
vidigoat:fix-empty-list-tool-output

Conversation

@vidigoat
Copy link
Copy Markdown

@vidigoat vidigoat commented Jun 1, 2026

Problem

ItemHelpers._convert_tool_output (in src/agents/items.py, reached via the public ItemHelpers.tool_call_output_item) decides whether a tool's list/tuple return value is structured output or should be stringified:

if isinstance(output, list | tuple):
    maybe_converted_output_list = [
        cls._maybe_get_output_as_structured_function_output(item) for item in output
    ]
    if all(maybe_converted_output_list):   # <-- all([]) is True
        return [ ... structured ... ]
    else:
        return str(output)

For an empty list or tuple, the comprehension yields [] and all([]) == True, so the empty collection wrongly takes the structured-output branch and returns an empty ResponseFunctionCallOutputItemListParam ([]). Sent to the Responses API as a function_call_output, an empty structured list drops the tool result entirely — the model sees no output for that tool call — instead of the expected stringified "[]" / "()".

A non-empty plain list like [1, 2, 3] correctly stringifies to "[1, 2, 3]"; only the empty case misbehaves.

Fix

if maybe_converted_output_list and all(maybe_converted_output_list):

Empty collections now fall through to str(output).

Verification

before:  pytest tests/test_tool_output_conversion.py -k empty_list_not_converted or empty_tuple_not_converted
         2 failed  (isinstance([], str) is False -- output was [] not '[]')
after :  26 passed (24 existing + 2 new regression tests)
full suite green:  tests/test_items_helpers.py tests/test_tool_output_conversion.py
                   tests/test_tool_origin.py tests/test_output_tool.py  -> 86 passed

ruff check, ruff format --check, and mypy all pass on the changed files.

Adds test_tool_call_output_item_empty_list_not_converted and ..._empty_tuple_not_converted mirroring the existing "not_converted" test style.

ItemHelpers._convert_tool_output stringifies a tool's list/tuple return
value unless every element is a structured output type, gated on
'if all(maybe_converted_output_list)'. For an empty list/tuple the
comprehension yields [] and all([]) is True, so the empty collection
wrongly takes the structured-output branch and returns an empty
ResponseFunctionCallOutputItemListParam. Sent to the Responses API as a
function_call_output, that empty list drops the tool result entirely
instead of producing the expected stringified '[]' / '()'.

Guard the branch with a truthiness check so empty collections fall
through to str(output). Non-empty lists were already stringified
correctly; only the empty case is fixed. Adds regression tests for
empty list and empty tuple.

Signed-off-by: Vidit Patankar <vidit.patankar16@gmail.com>
@vidigoat vidigoat changed the title Fix empty list/tuple tool output being dropped (all([]) is True) fix(items): empty list/tuple tool output dropped via all([]) == True Jun 1, 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.

1 participant