From b0f8350c7fe3321f215ed591841dec4b146703cb Mon Sep 17 00:00:00 2001 From: Henry Su Date: Thu, 20 Aug 2026 12:49:18 -0500 Subject: [PATCH] fix(approvals): fail closed on empty tool arguments Missing or blank argument strings were coerced to {} before callable needs_approval ran, so content gates could skip interruption. --- src/agents/util/_approvals.py | 4 +++- tests/realtime/test_session.py | 1 + tests/test_hitl_error_scenarios.py | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/agents/util/_approvals.py b/src/agents/util/_approvals.py index 0aa86d9965..8992f5ada2 100644 --- a/src/agents/util/_approvals.py +++ b/src/agents/util/_approvals.py @@ -17,9 +17,11 @@ def _reject_nonstandard_json_constant(value: str) -> NoReturn: def parse_function_tool_arguments(arguments: str | None) -> dict[str, Any] | None: """Return parsed object arguments, or None when an approval policy cannot inspect them.""" + if arguments is None or not arguments.strip(): + return None try: parsed = json.loads( - arguments or "{}", + arguments, parse_constant=_reject_nonstandard_json_constant, ) except ValueError: diff --git a/tests/realtime/test_session.py b/tests/realtime/test_session.py index 9d8f813bae..ab0ac5ebfc 100644 --- a/tests/realtime/test_session.py +++ b/tests/realtime/test_session.py @@ -3125,6 +3125,7 @@ async def test_function_tool_needs_approval_emits_event( @pytest.mark.parametrize( "arguments", [ + "", '{"subject": "refund"', "null", "[]", diff --git a/tests/test_hitl_error_scenarios.py b/tests/test_hitl_error_scenarios.py index d8518088cf..eb59cb1ce1 100644 --- a/tests/test_hitl_error_scenarios.py +++ b/tests/test_hitl_error_scenarios.py @@ -919,6 +919,7 @@ def bad_tool() -> str: @pytest.mark.parametrize( "arguments", [ + "", '{"subject": "refund"', "null", "[]",