Repository navigation
FIX: Return a tool error when arguments don't match a FunctionTool's signature - #3669
Conversation
…signature OpenAIResponseTarget returns malformed_arguments for tool arguments that are not valid JSON or not a JSON object, but a JSON object that failed the FunctionTool's argument model raised ValidationError out of the send. Tool.validate_arguments now runs before execution. It accepts any arguments by default, and FunctionTool checks them against its argument model, so the dispatcher can return malformed_arguments with invoked=False, or re-raise when fail_on_missing_function=True, without calling the function. Fixes microsoft#3668
|
@microsoft-github-policy-service agree |
Only validate_arguments is inside the try that returns malformed_arguments. The new test fails if execute_async is moved into it, so an error raised by the function itself can't be reported to the model as an argument error.
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues are reported for the change that makes invalid tool arguments recoverable.
No open issues 🎉
What changed in this PR
Addresses #3668 by letting the OpenAI Responses tool loop return recoverable errors for arguments that do not match a FunctionTool signature, rather than failing the entire send.
Changes:
- Adds a default argument-validation hook to
Tooland schema validation toFunctionTool. - Returns
malformed_argumentswithinvoked=Falsefor rejected arguments, while preserving strict-mode failures and exceptions raised during execution. - Adds regression tests for invalid arguments, execution metadata, replay validation, and function-error propagation.
| File | Description |
|---|---|
tests/unit/prompt_target/target/test_tool.py |
Tests argument rejection, recoverable tool errors, and exception propagation. |
pyrit/prompt_target/openai/openai_response_target.py |
Validates tool arguments before execution and handles rejected calls. |
pyrit/prompt_target/common/tool_provider.py |
Adds the validation hook and implements function-signature validation. |
Review effort: Balanced
hannahwestra25
left a comment
There was a problem hiding this comment.
thanks for contributing!
|
The failing checks aren't from this change. |
Description
Fixes #3668.
With
fail_on_missing_function=False,_execute_call_section_asyncreturns amalformed_argumentsfunction output for arguments that are not valid JSON or not a JSON object, so the model can correct the call. Arguments that are a JSON object but don't match aFunctionTool's signature (a wrong type, a missing required argument or an unexpected key) were only checked insideFunctionTool.execute_async, and theValidationErrorfailed the whole send.Toolnow has avalidate_argumentsmethod, which_execute_call_section_asynccalls beforeexecute_async. It accepts any arguments by default, since MCP servers report input errors in the tool result, andFunctionToolimplements it with its argument model. When it raises, the dispatcher returns the samemalformed_argumentsoutput withinvoked=False, or re-raises whenfail_on_missing_function=True, which is what that mode already did. Only the validation call is guarded, so an exception raised by the function itself is not reported as an argument error.MessageToolCallScorerkeeps counting these calls as not executed.Tests and Documentation
Added tests in
tests/unit/prompt_target/target/test_tool.py:FunctionTool.validate_argumentsraisesValidationErrorfor a wrong type, a missing required argument and an unexpected key.send_prompt_async, the same three cases reach the model as amalformed_argumentsoutput in the next request. The function is never called, the output is recorded withinvoked=False, and the stored history still validates for replay. Withfail_on_missing_function=Truethe send raisesValidationErrorafter one request.ValueErrorraised by the tool function itself still propagates instead of being returned asmalformed_arguments.No docs or notebooks changed, so JupyText was not needed.