Skip to content

[Bug] Pydantic tool schemas are named after the metaclass or the last docstring param, never the model (#1848) - #1870

Merged
kyegomez merged 1 commit into
kyegomez:masterfrom
ayaangazali:fix/pydantic-schema-function-name
Aug 11, 2026
Merged

[Bug] Pydantic tool schemas are named after the metaclass or the last docstring param, never the model (#1848)#1870
kyegomez merged 1 commit into
kyegomez:masterfrom
ayaangazali:fix/pydantic-schema-function-name

Conversation

@ayaangazali

Copy link
Copy Markdown
Contributor

Fixes the bug half of #1848 (the part the issue says to fix regardless of the dedup).

What

base_model_to_openai_function emitted the wrong function name into the schema handed to the LLM. Two independent bugs compounded:

  1. swarms/tools/pydantic_to_json.py:58name = type(pydantic_type).__name__. pydantic_type is the class, not an instance, so this reads the metaclass: "ModelMetaclass".
  2. The docstring loop's walrusif (name := param.arg_name) in parameters["properties"] rebinds name on every match, so whenever the model's docstring documents its fields, the emitted name becomes whichever parameter matched last.

The second one masks the first, which is why this reads as "wrong name" rather than a constant. On a model with a documented docstring:

master:  function_call.name: units          <- the last documented field
fixed:   function_call.name: WeatherQuery

Strip the docstring params and it falls through to ModelMetaclass instead. Either way the model is told the tool has a name it does not have — and the name is what the LLM emits back to call it.

This is not an internal helper: it is exported from swarms.tools and used by base_tool.py (:281, :673), so it reaches real tool schemas.

Fix

  • name = pydantic_type.__name__
  • The walrus binds prop_name instead of name, so attaching per-parameter descriptions can no longer overwrite the function name. Those descriptions still attach — asserted in the test.
  • Deleted check_pydantic_name (:20-37): it has zero callers, is not exported from swarms/tools/__init__.py, and carried the same type(...) mistake, so leaving it there is a live copy of the bug waiting to be picked up.

Deliberately out of scope

#1848 also covers the three-way duplication of pydantic→OpenAI schema conversion and the legacy {"function_call": …, "functions": […]} envelope. Those change the shape callers receive; this PR does not touch them, so it stays reviewable on its own and safe to land first. Happy to take the consolidation separately.

Test

Appended to tests/tools/test_output_str_fix.py — no new file, it already owns this function. It uses a model whose docstring documents its fields, so it covers the walrus path (the one that actually fires in practice) and asserts the parameter descriptions survive.

master source + this test:   1 failed
this branch:                 5 passed  (tests/tools/test_output_str_fix.py)
black --check --line-length 70, ruff:  clean

Red checks are the repo-wide pre-existing ones (build never installs the package; test-main-features dies on Poetry 2.x --no-dev), both addressed in #1812.

@ayaangazali
ayaangazali requested a review from kyegomez as a code owner August 10, 2026 20:22
Copilot AI lite review requested due to automatic review settings August 10, 2026 20:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

Copy link
Copy Markdown

Hello there, thank you for opening an PR ! 🙏🏻 The team was notified and they will get back to you asap.

@kyegomez
kyegomez merged commit d450d70 into kyegomez:master Aug 11, 2026
6 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants