Skip to content

tuple or namedtuple as a tool parameter type generates invalid schema #302

Closed
@markns

Description

@markns

Describe the bug

Using tuple or namedtuple as a function_tool parameter type

LatLong = namedtuple('LatLong', "lat long")

@function_tool
def get_weather(lat_long: LatLong) -> Weather:

@function_tool
def get_weather(lat_long: tuple[float, float]) -> Weather:

leads to the following error during function schema creation:

Error getting response: Error code: 400 - 
{'error': {'message': "Invalid schema for function 'get_weather': In context=(), 'minItems' is not permitted.", 
'type': 'invalid_request_error', 'param': 'tools[0].parameters', 'code': 'invalid_function_parameters'}}. 

Debug information

  • Agents SDK version: v0.0.6
  • Python version = 3.13

Repro steps

import asyncio
from collections import namedtuple
from pydantic import BaseModel

from agents import Agent, Runner, function_tool

class Weather(BaseModel):
    lat_long: tuple[float, float]
    temperature_range: str
    conditions: str

LatLong = namedtuple('LatLong', "lat long")

@function_tool
def get_weather(lat_long: LatLong) -> Weather:
    return Weather(lat_long=lat_long, temperature_range="14-20C", conditions="Sunny with wind.")

agent = Agent(
    name="Hello world",
    instructions="You are a helpful agent.",
    tools=[get_weather],
)

async def main():
    result = await Runner.run(agent, input="What's the weather in Tokyo?")
    print(result.final_output)
    # The weather in Tokyo is sunny.

await main()

Expected behavior

Using a tuple or namedtuple as type annotation should work.

I've previously used this function to normalize a schema generated by LLMEasyTools, but not sure how to make that work with the agents sdk yet.

def normalize_for_openai(obj: dict):
    if isinstance(obj, dict):
        # Create a new dict to avoid mutating while iterating
        new_obj = {}
        for k, v in obj.items():
            if k in ("minItems", "maxItems"):
                continue
            elif k == "prefixItems":
                # Assumes all prefixItems are the same type
                first_type = v[0].get("type", "number")
                new_obj["items"] = {"type": first_type}
            else:
                new_obj[k] = normalize_for_openai(v)
        return new_obj
    elif isinstance(obj, list):
        return [normalize_for_openai(i) for i in obj]
    else:
        return obj

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions