Skip to content

.Net: Python: Bug: OpenAPI plugin sends array and boolean query parameters as Python repr (tags=['a', 'b'], active=True) #14788

Open

Description

Describe the bug

The OpenAPI plugin builds the query string with urlencode(segments) and passes argument values through unchanged:

def build_query_string(self, arguments: dict[str, Any]) -> str:
"""Build the query string for the operation."""
segments = []
parameters = [p for p in self.parameters if p.location == RestApiParameterLocation.QUERY]
for parameter in parameters:
argument = arguments.get(parameter.name)
if argument is None:
if parameter.is_required:
raise FunctionExecutionException(
f"No argument or value is provided for the `{parameter.name}` "
f"required parameter of the operation - `{self.id}`."
)
continue
segments.append((parameter.name, argument))
return urlencode(segments)

Without doseq=True, urlencode calls str() on each value. So an array query parameter is sent as Python's list repr (['red', 'blue']), and a boolean is sent as True/False. APIs can't parse either. OpenAPI's default for query parameters is style: form, explode: true, which means tags=red&tags=blue and active=true. The .NET OpenAPI plugin already serializes arrays this way.

The schema advertised to the model says {"type": "array", "items": {"type": "string"}}, so a tool call from the model hits this.

Header and path parameters have the same problem, since they use str(argument) (L218, L331).

To Reproduce

semantic-kernel 1.47.0. rest_api_operation.py is the same on main (25bd1bb). This runs offline: httpx.MockTransport captures the request, and the server is an IP literal so the URL validator doesn't need DNS.

import asyncio, httpx
from semantic_kernel import Kernel
from semantic_kernel.connectors.openapi_plugin import OpenAPIFunctionExecutionParameters

spec = {
    "openapi": "3.0.1", "info": {"title": "t", "version": "1"},
    "servers": [{"url": "https://93.184.216.34"}],
    "paths": {"/items": {"get": {
        "operationId": "listItems",
        "parameters": [
            {"name": "tags", "in": "query", "schema": {"type": "array", "items": {"type": "string"}}},
            {"name": "active", "in": "query", "schema": {"type": "boolean"}},
        ],
        "responses": {"200": {"description": "ok"}},
    }}},
}

seen = []
def handler(request):
    seen.append(str(request.url))
    return httpx.Response(200, json={})

async def main():
    client = httpx.AsyncClient(transport=httpx.MockTransport(handler))
    kernel = Kernel()
    plugin = kernel.add_plugin_from_openapi(
        "api", openapi_parsed_spec=spec,
        execution_settings=OpenAPIFunctionExecutionParameters(http_client=client),
    )
    await kernel.invoke(plugin["listItems"], tags=["red", "blue"], active=True)
    print(seen[0])

asyncio.run(main())

Output:

https://93.184.216.34/items?tags=%5B%27red%27%2C+%27blue%27%5D&active=True

Expected behavior

https://93.184.216.34/items?tags=red&tags=blue&active=true

(form/explode, the OpenAPI default for query parameters), with booleans written as JSON true/false.

Platform

  • Language: Python
  • Source: semantic-kernel 1.47.0 (pip) / main at 25bd1bb
  • AI model: n/a (no model call needed)
  • IDE: n/a
  • OS: Windows 11, Python 3.12

Additional context

The parser doesn't read style/explode from the spec yet (RestApiParameter is always built without them), so the smallest fix is to serialize lists as repeated keys (doseq=True) and booleans as lowercase. Happy to send a fix if that helps.

Activity

  1. changed the title [-]Python: Bug: OpenAPI plugin sends array and boolean query parameters as Python repr (tags=['a', 'b'], active=True)[/-] [+].Net: Python: Bug: OpenAPI plugin sends array and boolean query parameters as Python repr (tags=['a', 'b'], active=True)[/+] on Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    .NETIssue or Pull requests regarding .NET codepythonPull requests for the Python Semantic Kerneltriage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions