Skip to content

fix(tools): tell the model when a RestApiTool body is empty or not JSON - #8097

Open
elmaroun07-hub wants to merge 1 commit into
google:mainfrom
elmaroun07-hub:fix/rest-api-tool-non-json-warning
Open

elmaroun07-hub wants to merge 1 commit into
google:mainfrom
elmaroun07-hub:fix/rest-api-tool-non-json-warning

Conversation

@elmaroun07-hub

Copy link
Copy Markdown

Link to Issue or Description of Change

2. Or, if no issue exists, describe the change:

Problem:
When an API answers 2xx with a body that is empty or not valid JSON, RestApiTool.call returns only {"text": response.text}. With an empty body the model receives {"text": ""} and nothing tells it that the API returned no content, so it cannot distinguish "nothing came back" from data.

Solution:
Keep "text" exactly as it is and add one "message" key saying the body was empty, or was not valid JSON, with the status code. The call still counts as a success, so nothing is reported under "error" and _detect_error_in_response is unaffected. "message" is the key this file already uses for neutral notes ({"pending": True, "message": ...}). JSON responses and error statuses are unchanged.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally. (See below: the openapi_tool folder passes on four Python versions; the full tox run did not finish on my machine.)

Added to test_rest_api_tool.py: empty body, whitespace-only body, HTML body, plain-text body, and a JSON body returned unchanged. Each test compares the whole returned dict. Before the fix: 4 failed, 1 passed. After: 5 passed.

python -m pytest tests/unittests/tools/openapi_tool, run in each tox environment (Windows):

Python Result
3.11.17 440 passed
3.12.10 440 passed
3.13.18 440 passed
3.14.10 440 passed

Not completed: the full tox run. All four environments built, but the full suites were still running after 50 minutes on my Windows machine and I stopped them. Three pre-commit hooks (check-new-py-prefix, compliance-checks, check-docs) could not start under pre-commit on Windows; I ran their scripts directly and each exited 0. addlicense was not installed locally. ruff, isort, pyink and codespell passed.

Manual End-to-End (E2E) Tests:

Tool-level test: a local HTTP server on 127.0.0.1 and a direct RestApiTool.call against it (not run through adk web or a Runner).

code under test: upstream/main (098eefa24)
server: 200 text/plain, body=b''
  tool returned: {"text": ""}
server: 200 text/html; charset=utf-8, body=b'<html><body><h1>Saved</h1></body></html>'
  tool returned: {"text": "<html><body><h1>Saved</h1></body></html>"}

code under test: this branch
server: 200 text/plain, body=b''
  tool returned: {"text": "", "message": "The response body was empty. Status Code: 200"}
server: 200 text/html; charset=utf-8, body=b'<html><body><h1>Saved</h1></body></html>'
  tool returned: {"text": "<html><body><h1>Saved</h1></body></html>", "message": "The response body was not valid JSON. Status Code: 200"}

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. (The openapi_tool folder only, as above.)
  • I have manually tested my changes end-to-end. (Tool-level, as above.)
  • Any dependent changes have been merged and published in downstream modules. (None.)

Additional context

If you would rather flag only the empty body and leave non-empty non-JSON bodies as they are, I can narrow the change.

I found this while measuring how agents respond when a tool returns an empty 200 body; in my runs with another framework, models often answered with made-up values instead of reporting it: https://github.com/elmaroun07-hub/reported-or-invented

This change was written with AI assistance (Claude Code); I reviewed and tested it.

When an API answered 2xx with an empty or non-JSON body, RestApiTool
returned only {"text": response.text}. An empty body reached the model as
{"text": ""}, which it cannot tell apart from real data.

Keep "text" as it is and add a "message" saying the body was empty or was
not valid JSON, with the status code. The call still counts as a success,
so nothing is reported under "error". JSON bodies and error statuses are
unchanged.
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