Skip to content

fix: support Pydantic Field in Annotated tool parameters - #12982

Open
MohammadHijjawi97 wants to merge 2 commits into
deepset-ai:mainfrom
MohammadHijjawi97:fix/tool-from-function-annotated-pydantic-field
Open

MohammadHijjawi97 wants to merge 2 commits into
deepset-ai:mainfrom
MohammadHijjawi97:fix/tool-from-function-annotated-pydantic-field

Conversation

@MohammadHijjawi97

Copy link
Copy Markdown
Contributor

Related Issues

  • fixes: no existing issue (searched open/closed issues and PRs for Annotated + Field in tools, no match)

Proposed Changes:

create_tool_from_function (and therefore @tool) took the first typing.Annotated metadata item and wrote it into the JSON schema as the parameter description, whatever its type. With the common Pydantic pattern Annotated[int, Field(ge=1)] (or Annotated[str, Field(description="...")]), a FieldInfo object ended up in the schema and creating the tool failed:

from typing import Annotated
from pydantic import Field
from haystack.tools import tool

@tool
def forecast(city: str, days: Annotated[int, Field(ge=1)] = 1) -> str:
    """Get the forecast."""
    return ""
# ValueError: The provided parameters do not define a valid JSON schema

Now only a string metadata item is used as the description; other metadata is left to Pydantic, so Field constraints (minimum, minLength, ...) and a Field(description=...) show up in the tool schema. The plain Annotated[str, "description"] behavior is unchanged, and the docstring is updated accordingly.

How did you test it?

  • Added test_from_function_annotated_with_pydantic_field (a Field plus a string description, a Field with its own description, and a Field without description). It fails on main with the error above and passes with the fix.
  • pytest test/tools -m "not integration": 272 passed.
  • ruff check / ruff format --check and mypy on the changed files.

Notes for the reviewer

When both a string and a Field(description=...) are present, the string wins, consistent with the documented Annotated[T, "description"] convention.

I used an AI coding assistant (Claude Code) while writing the fix and tests; I reviewed the changes and ran the checks listed above.

Checklist

create_tool_from_function and the @tool decorator wrote the first
Annotated metadata item into the schema as the parameter description,
even when it was not a string. A parameter annotated with a Pydantic
Field, e.g. Annotated[int, Field(ge=1)], therefore put a FieldInfo
object into the schema and Tool creation failed with "The provided
parameters do not define a valid JSON schema".

Use only a string metadata item as the description and leave other
metadata to Pydantic, so Field constraints and descriptions end up in
the tool schema.
@MohammadHijjawi97
MohammadHijjawi97 requested a review from a team as a code owner September 27, 2026 10:04
@MohammadHijjawi97
MohammadHijjawi97 requested review from bogdankostic and removed request for a team September 27, 2026 10:04
@vercel

vercel Bot commented Sep 27, 2026

Copy link
Copy Markdown
Contributor

@MohammadHijjawi97 is attempting to deploy a commit to the deepset Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions

Copy link
Copy Markdown
Contributor

Hi @MohammadHijjawi97, thanks for your interest in contributing to Haystack! 🙏

⚠️ You currently have 3 open pull requests in this repository (#12793, #12790 and this one). Our review capacity is limited, so please hold off opening more PRs until we've had a chance to review your first 2 open PRs. This helps us give each contribution the attention it deserves. Thank you!

This is an automated message to help us keep the review queue healthy.

@github-actions github-actions Bot added topic:tests type:documentation Improvements on the docs labels Sep 27, 2026
@github-actions

github-actions Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  haystack/tools
  from_function.py
Project Total  

This report was generated by python-coverage-comment-action

@sjrl

sjrl commented Sep 28, 2026

Copy link
Copy Markdown
Contributor

@MohammadHijjawi97 thanks for looking into this! Could I ask you if this is something you ran into while building tools with Haystack?

@MohammadHijjawi97

MohammadHijjawi97 commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor Author

Not in a production project, no. I came across it while going through how create_tool_from_function handles Annotated metadata and trying the Annotated[int, Field(ge=1)] pattern from the Pydantic docs, which fails at tool creation today.

@MohammadHijjawi97

Copy link
Copy Markdown
Contributor Author

@sjrl following up on your question with a concrete case where this comes up: functions written for MCP servers. FastMCP documents parameters as Annotated[int, Field(description=..., ge=1)], so reusing such a function as a Haystack tool (create_tool_from_function / @tool) currently fails at tool creation with The provided parameters do not define a valid JSON schema. With this change the Field description and constraints (minimum, maxLength, ...) end up in the tool schema the LLM sees, and plain Annotated[T, "description"] keeps working as before. I've merged current main into the branch. @bogdankostic, it's ready for review whenever you have time.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:tests type:documentation Improvements on the docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants