Python: Preserve null arguments during tool invocation - #5944
Python: Preserve null arguments during tool invocation#5944Shubham Singh (shusingh) wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates Python core tool invocation to preserve explicitly supplied null values through Pydantic argument validation, addressing required nullable tool parameters during direct and automatic invocation.
Changes:
- Adds a helper for dumping Pydantic argument models while restoring explicit top-level
Nonevalues. - Applies the helper in
FunctionTool.invoke()and automatic function calling. - Adds regression tests for direct and automatic nullable required arguments.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
python/packages/core/agent_framework/_tools.py |
Updates argument dumping in tool invocation paths to preserve explicit None values. |
python/packages/core/tests/core/test_tools.py |
Adds direct FunctionTool.invoke() regression coverage. |
python/packages/core/tests/core/test_function_invocation_logic.py |
Adds automatic function calling regression coverage. |
35a9f72 to
c0fedbb
Compare
|
Updated the PR to handle nested explicit null values as well. The argument dump helper now recursively restores explicitly provided nulls in nested Pydantic models, mappings, and lists/tuples, and I added regression coverage for both direct tool invocation and automatic function calling with nested nullable arguments. |
Python Test Coverage Report •
Python Unit Test Overview
|
||||||||||||||||||||||||||||||
|
Pushed a follow-up that keeps the explicit-null helper behavior unchanged while making the mapping and sequence narrowing explicit for Pyright. Locally verified the touched file with Pyright 1.1.408 and reran the focused nullable-argument regression tests. |
|
Shubham Singh (@shusingh) please fix the failing CI/CD checks. |
|
Fixed the failing type checks by changing the helper narrowing from Any container casts to concrete object container casts, which keeps Pyright from seeing unknown element types while avoiding Mypy redundant-cast errors. Locally verified the touched file with Pyright 1.1.408, Mypy on �gent_framework/_tools.py, and the focused nullable-argument regression tests. |
|
Hi! Just checking in on this PR. The review feedback has been addressed, and it’s ready for another look when you have a chance. I’m happy to update the branch or make any further adjustments. Thanks! |
|
Hi again! Just following up on this PR when you have a chance. It should be ready for review, and I’m happy to update the branch or address anything else needed. Thanks! |
…ents # Conflicts: # python/packages/core/tests/core/test_function_invocation_logic.py
| """Dump a model without dropping fields that were explicitly set to None.""" | ||
| # Pydantic's exclude_none removes both default None values and explicit null arguments. | ||
| # Restore only fields present in model_fields_set so omitted optional fields stay omitted. | ||
| dumped = model.model_dump(exclude_none=True) |
There was a problem hiding this comment.
there is also a exclude_defaults keyword on model_dump could that be used instead? I am not a fan of this extra function doing a bunch of dict manipulation.
There was a problem hiding this comment.
Good call. exclude_defaults compares values, so an explicit null on a None-default field would still be dropped. exclude_unset keys off model_fields_set instead, keeping anything explicitly provided (nested included). Replaced the helper with a plain model_dump(exclude_unset=True); tests and type checks pass.
|
Please re-open when ready to address comments and move forward. Thanks. |
|
Evan Mattson (@moonbox3) Apologies for the delay, I was traveling and missed the last round of feedback. It's addressed now: the custom dict-manipulation helper is gone, replaced with a plain |
|
Hi Evan Mattson (@moonbox3), a gentle follow-up on this one. The latest revision addresses the review comments: the custom dict-manipulation helper is gone, replaced with a plain |
Summary
nullvalues when dumping validated tool argumentsFunctionTool.invoke()and automatic function callingFixes #5934
Tests
python -m pytest tests/core/test_tools.py::test_tool_invoke_preserves_explicit_null_for_required_nullable_argument tests/core/test_function_invocation_logic.py::test_auto_function_calling_preserves_explicit_null_arguments -qpython -m pytest tests/core/test_tools.py tests/core/test_function_invocation_logic.py -qpython -m ruff check agent_framework/_tools.py tests/core/test_tools.py tests/core/test_function_invocation_logic.py