diff --git a/src/agents/function_schema.py b/src/agents/function_schema.py index 8fe52df320..c0d8652b7c 100644 --- a/src/agents/function_schema.py +++ b/src/agents/function_schema.py @@ -404,6 +404,21 @@ def function_schema( ) # 3. Dynamically build a Pydantic model + # Pydantic raises ValueError for field names that match built-in BaseModel methods in a + # protected namespace (e.g. model_dump, model_validate). Catch these early. + _PYDANTIC_PROTECTED_NAMES = { + "model_dump", + "model_dump_json", + "model_validate", + "model_validate_json", + "model_validate_strings", + } + colliding = _PYDANTIC_PROTECTED_NAMES.intersection(fields) + if colliding: + raise UserError( + f"Function '{func_name}' has parameter(s) {sorted(colliding)} whose name(s) conflict " + "with Pydantic BaseModel built-in methods. Rename the parameter(s) to avoid this." + ) dynamic_model = create_model(f"{func_name}_args", __base__=BaseModel, **fields) # 4. Build JSON schema from that model diff --git a/tests/test_function_schema.py b/tests/test_function_schema.py index 9771bda99d..8aec1692e9 100644 --- a/tests/test_function_schema.py +++ b/tests/test_function_schema.py @@ -885,3 +885,13 @@ def func_with_annotated_multiple_field_constraints( with pytest.raises(ValidationError): # zero factor fs.params_pydantic_model(**{"score": 50, "factor": 0.0}) + + +def test_pydantic_protected_namespace_param_raises_user_error(): + # Parameters named after Pydantic's protected BaseModel methods must raise UserError, + # not an opaque ValueError from inside Pydantic's create_model(). + def func_with_model_validate(model_validate: str, query: str) -> str: + return query + + with pytest.raises(UserError, match="model_validate"): + function_schema(func_with_model_validate, use_docstring_info=False)