Skip to content

fix(openai): keep the keys beside "result" in a Responses tool output - #7837

Open
adityasingh2400 wants to merge 1 commit into
google:mainfrom
adityasingh2400:fix/openai-responses-keep-result-siblings
Open

adityasingh2400 wants to merge 1 commit into
google:mainfrom
adityasingh2400:fix/openai-responses-keep-result-siblings

Conversation

@adityasingh2400

Copy link
Copy Markdown
Contributor

Please ensure you have read the contribution guide before creating a pull request.

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

Problem:
_serialize_json_value unwrapped any tool dict with a non-None "result" key and sent only that value as the function_call_output. A tool returning {"result": "found 2 contracts", "contracts": [...], "next_page_token": "abc"} therefore reached the model as just found 2 contracts, and the rest of the data was silently lost.

Solution:
Unwrap only when the keys are exactly {"result"}, which is ADK's wrapper for a non-dict tool return. Any other dict is JSON-encoded whole. This is the same rule AnthropicLlm uses since #7073. Bare {"result": value} returns, MCP content lists and plain strings are serialized as before.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

Added to tests/unittests/integrations/openai/test_openai_responses_llm.py:

  • test_function_response_unwraps_adk_result_wrapper: {"result": "sunny"} → sunny, and {"result": [1, 2]} → [1, 2]. This behavior is unchanged.
  • test_function_response_keeps_keys_beside_result: the full dict round-trips.
# On main (before the fix)
json.decoder.JSONDecodeError: Expecting value   # output was only "found 2 contracts"
1 failed, 1 passed

# With the fix
$ pytest tests/unittests/integrations/openai
227 passed

pre-commit run passes on the changed files, and mypy reports no issues in _openai_responses_llm.py.

Manual End-to-End (E2E) Tests:

I ran a Runner with LlmAgent(model=OpenAIResponsesLlm(model="gpt-5"), tools=[search_contracts]). The function tool returns the dict above. Only the client's responses.create is replaced: it records each request, asks for search_contracts first and answers second. The output below is the function_call_output in the second request:

=== BEFORE (main) ===
function_call_output sent to OpenAI: found 2 contracts
=== AFTER (this PR) ===
function_call_output sent to OpenAI: {"result": "found 2 contracts", "contracts": ["NDA-12", "MSA-7"], "next_page_token": "abc"}

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

Additional context

None.

_serialize_json_value unwrapped any tool dict with a non-None "result" key
and sent only that value, so a tool returning
{"result": ..., "contracts": [...], "next_page_token": ...} lost
everything but the result text. Unwrap only ADK's own {"result": value}
wrapper for non-dict returns and send other dicts whole, as AnthropicLlm
already does.

Fixes google#7836
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.

OpenAIResponsesLlm drops the keys beside "result" in a tool's dict return

2 participants