feat(tools): parameter descriptions via Annotated and docstring Args - #271
jaygupta17 wants to merge 1 commit into
Conversation
|
@jaygupta17 is attempting to deploy a commit to the Vercel Labs Team on Vercel. A member of the Team first needs to authorize it. |
|
Could a maintainer add the |
|
hey folks quick ping on #271 and #273 when you get a sec, been open since Aug 26. both are mergeable and green across 3.12-3.15 and Socket. the two reds are just fork perms (Vercel needs collaborator auth and changelog-label needs the |
204f90e to
9528108
Compare
|
Rebased onto latest main. The only conflict was in test_tools.py (upstream added to_model_input tests where mine go), kept both suites. Ruff, mypy, ty, and pytest all green locally. The two reds still need a maintainer: the feature label and Vercel auth. |
Tool schemas stripped Annotated metadata because get_type_hints() was called without include_extras=True, so `city: Annotated[str, Field(description=...)]` lost its description and the model picked tools with undocumented arguments. - resolve hints with include_extras=True; pydantic already carries Field metadata through create_model().model_json_schema() - parse a Google-style Args: section from the docstring and fill in descriptions for parameters that have no Field description; Field wins - no behavior change for tools without descriptions: plain-hint schemas are byte-identical to before The schema is embedded verbatim by every provider protocol (openai, anthropic, gateway), so descriptions reach all models without per-provider changes.
9528108 to
aa74ab1
Compare
|
Rebased onto latest main, no code changes. Ruff, ty, mypy, and pytest green locally. Still needs a maintainer for the feature label and Vercel auth. |
Closes #270
What
Two mechanisms for parameter descriptions on
@ai.toolfunctions:Annotated[str, Field(description=...)]now survives into the schema — the fix isget_type_hints(fn, include_extras=True); pydantic carries the metadata throughcreate_model().model_json_schema()unchanged.Args:docstring section fills descriptions for parameters without aFielddescription.Fieldwins when both exist.Why
Descriptions are how the model judges which tool to call and what each argument means. Both idiomatic typed-Python patterns were silently dropped, so every tool built this way shipped undocumented arguments.
Notes
agent.py, Google-style only).Args:block from it felt like a separate behavior decision, happy to follow up if wanted.spec.paramsverbatim (openai/protocol.py,anthropic/protocol.py,ai_gateway/protocol.py), so descriptions reach all models with no per-provider changes.Validation
uv run pytest: 768 passed (8 new tests covering annotated fields, nestedAnnotated[...] | Noneunions keeping constraints + description, multiline Args entries, Field-over-docstring precedence, unknown-name tolerance, and the byte-identical regression)uv run ruff format --check/ruff check: cleanuv run mypy: 35 errors, identical to baseline onmain(all pre-existing, none in touched code)uv run ty check: clean