Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

RestApiTool: integer / boolean / array header and cookie parameters crash the agent run (httpx: Header value must be str or bytes)

Đang mở
#7,164 1 bình luận 0 reaction 1 người được giao Xem trên GitHub

@llalitkumarrr đang làm issue này rồi.

Từ ngày 18/9/2026.

Đánh giá

Issue này chưa được đánh giá.

Mô tả

tools

🔴 Required Information

Describe the Bug:

RestApiTool._prepare_request_params() passes header and cookie parameter values to httpx unchanged:

elif param_location == "header":
  header_params[original_k] = v
elif param_location == "cookie":
  cookie_params[original_k] = v

httpx serializes query values itself (5 becomes "5", False becomes "false"), but it only accepts str/bytes for headers and cookies. So when an OpenAPI spec declares an integer, number, boolean, or array header or cookie parameter, which is common in enterprise APIs (X-Page-Size, X-Api-Version, X-Dry-Run, ...), and the model fills it with a value of that type, the request can't be built. The TypeError isn't turned into a tool error, so the whole agent run fails.

This is separate from #7099, which handles None values for the same parameters.

Steps to Reproduce:

  1. pip install google-adk (reproduced on main @ f33d4923 / 2.9.0).
  2. Run the script below: a real Runner plus LlmAgent plus OpenAPIToolset whose spec has an integer and a boolean header parameter. The model is mocked and HTTP goes to an httpx.MockTransport.

Expected Behavior:
The request is sent with X-Page-Size: 50 and X-Include-Archived: false (OpenAPI's default simple style, and how httpx already encodes query values), and the tool result goes back to the model.

Observed Behavior:

  File ".../httpx/_models.py", line 81, in _normalize_header_value
    raise TypeError(f"Header value must be str or bytes, not {type(value)}")
TypeError: Header value must be str or bytes, not <class 'int'>

The exception propagates out of Runner.run_async(). An integer cookie parameter fails the same way (TypeError: expected string or bytes-like object, got 'int' from http.cookiejar). A boolean header would be sent as True/False even if it got through, rather than true/false.

Environment Details:

  • ADK Library Version (pip show google-adk): 2.9.0 (main @ f33d4923)
  • Desktop OS: Windows 11
  • Python Version (python -V): 3.12.10

Model Information:

  • Are you using LiteLLM: No
  • Which model is being used: N/A (mocked model; the bug is in request building)

🟡 Optional Information

Minimal Reproduction Code:

import asyncio

import httpx
from google.adk.agents.llm_agent import LlmAgent
from google.adk.models.base_llm import BaseLlm
from google.adk.models.llm_response import LlmResponse
from google.adk.runners import InMemoryRunner
from google.adk.tools.openapi_tool.openapi_spec_parser.openapi_toolset import OpenAPIToolset
from google.genai import types

spec = {
    "openapi": "3.0.0",
    "info": {"title": "Invoices", "version": "1"},
    "servers": [{"url": "https://erp.example.com"}],
    "paths": {"/invoices": {"get": {
        "operationId": "listInvoices",
        "parameters": [
            {"name": "X-Page-Size", "in": "header", "required": True, "schema": {"type": "integer"}},
            {"name": "X-Include-Archived", "in": "header", "schema": {"type": "boolean"}},
        ],
        "responses": {"200": {"description": "ok"}},
    }}},
}
sent = {}


def handler(request: httpx.Request):
  sent.update(request.headers)
  return httpx.Response(200, json={"invoices": []})


class FakeModel(BaseLlm):
  model: str = "fake"
  calls: int = 0

  async def generate_content_async(self, llm_request, stream=False):
    self.calls += 1
    part = (types.Part.from_function_call(
                name="list_invoices", args={"x_page_size": 50, "x_include_archived": False})
            if self.calls == 1 else types.Part.from_text(text="done"))
    yield LlmResponse(content=types.Content(role="model", parts=[part]))


agent = LlmAgent(
    name="ap_agent",
    model=FakeModel(),
    tools=[OpenAPIToolset(
        spec_dict=spec,
        httpx_client_factory=lambda: httpx.AsyncClient(transport=httpx.MockTransport(handler)),
    )],
)


async def main():
  runner = InMemoryRunner(agent=agent)
  session = await runner.session_service.create_session(app_name=runner.app_name, user_id="u")
  async for _ in runner.run_async(
      user_id="u", session_id=session.id,
      new_message=types.Content(role="user", parts=[types.Part(text="list invoices")])):
    pass
  print("headers sent:", {k: v for k, v in sent.items() if k.startswith("x-")})


asyncio.run(main())

Suggested fix: serialize header and cookie values before handing them to httpx: numbers as str(v), booleans as true/false, arrays comma-joined. Leave other values alone, so None stays #7099's concern. I have a PR ready with tests.

How often has this issue occurred?:

  • Always (100%): any non-string header or cookie parameter value.
Ngôn ngữ chính
Python
Star
21.6k
Fork
4k
Merge trung bình
13 giờ 49 phút
Pull request đã merge (30 ngày)
10

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của google/adk-python

Tất cả issue của google/adk-python

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.