From a409cce10edf1a8f62e3751763f1018fa4f781e0 Mon Sep 17 00:00:00 2001 From: Shivam Sharma <192242476+ShivamSharma43@users.noreply.github.com> Date: Sat, 17 Oct 2026 22:58:17 +0530 Subject: [PATCH] Python: Recommend include_detailed_errors only when it is disabled The tool-failure warning always told callers to set include_detailed_errors=True, even when it was already enabled. Co-Authored-By: Claude Opus 5.5 --- .../packages/core/agent_framework/_tools.py | 12 ++-- .../core/test_function_invocation_logic.py | 60 +++++++++++++++++++ 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/python/packages/core/agent_framework/_tools.py b/python/packages/core/agent_framework/_tools.py index eb40fec7ee7..a5038d754eb 100644 --- a/python/packages/core/agent_framework/_tools.py +++ b/python/packages/core/agent_framework/_tools.py @@ -1992,21 +1992,23 @@ def _function_execution_error_result( ) -> Content: from .observability import OBSERVABILITY_SETTINGS + include_detailed_errors = config.get("include_detailed_errors", False) + recommendation = "" if include_detailed_errors else " Set include_detailed_errors=True for the full detail." if OBSERVABILITY_SETTINGS.SENSITIVE_DATA_ENABLED: logger.warning( - "Function '%s' raised an exception; returning an error result to the model. " - "Set include_detailed_errors=True for the full detail. Exception: %r", + "Function '%s' raised an exception; returning an error result to the model.%s Exception: %r", tool_name, + recommendation, exception, ) else: logger.warning( - "Function '%s' raised an exception; returning an error result to the model. " - "Set include_detailed_errors=True for the full detail.", + "Function '%s' raised an exception; returning an error result to the model.%s", tool_name, + recommendation, ) message = "Error: Function failed." - if config.get("include_detailed_errors", False): + if include_detailed_errors: message = f"{message} Exception: {exception}" return _finalize_function_result( call_id=function_call.call_id, # type: ignore[arg-type] diff --git a/python/packages/core/tests/core/test_function_invocation_logic.py b/python/packages/core/tests/core/test_function_invocation_logic.py index f37f6a8848f..7fcdfcd12fe 100644 --- a/python/packages/core/tests/core/test_function_invocation_logic.py +++ b/python/packages/core/tests/core/test_function_invocation_logic.py @@ -6023,6 +6023,66 @@ def make_result() -> dict[str, str]: ] assert len(execution_warnings) == 1 assert (_PRIVATE_ERROR_DETAIL in execution_warnings[0]) is enable_sensitive_data + assert ("Set include_detailed_errors=True" in execution_warnings[0]) is not include_detailed_errors + + +@pytest.mark.parametrize( + ("enable_instrumentation", "enable_sensitive_data"), + [(False, False), (True, False), (True, True)], + indirect=True, +) +@pytest.mark.usefixtures("span_exporter") +@pytest.mark.parametrize("include_detailed_errors", [False, True]) +async def test_function_execution_error_warning_recommends_detailed_errors_only_when_disabled( + chat_client_base: SupportsChatGetResponse, + monkeypatch: pytest.MonkeyPatch, + caplog: pytest.LogCaptureFixture, + include_detailed_errors: bool, + enable_sensitive_data: bool, +) -> None: + @tool(name="error_function", approval_mode="never_require") + def error_func() -> str: + raise RuntimeError(f"Tool failure: {_PRIVATE_ERROR_DETAIL}") + + monkeypatch.setattr( + chat_client_base, + "run_responses", + [ + ChatResponse( + messages=Message( + role="assistant", + contents=[Content.from_function_call(call_id="1", name="error_function", arguments="{}")], + ) + ), + ChatResponse(messages=Message(role="assistant", contents=["done"])), + ], + ) + monkeypatch.setitem( + chat_client_base.function_invocation_configuration, # type: ignore[attr-defined] # ty: ignore[unresolved-attribute] + "include_detailed_errors", + include_detailed_errors, + ) + + with caplog.at_level(logging.WARNING, logger="agent_framework"): + response = await chat_client_base.get_response( + [Message(role="user", contents=["hello"])], options={"tools": [error_func]} + ) + + result = next(content for msg in response.messages for content in msg.contents if content.type == "function_result") + assert (_PRIVATE_ERROR_DETAIL in (result.result or "")) is include_detailed_errors + execution_warnings = [ + record.getMessage() + for record in caplog.records + if record.name == "agent_framework" + and record.levelno == logging.WARNING + and "raised an exception; returning an error result" in record.getMessage() + ] + assert len(execution_warnings) == 1 + assert execution_warnings[0].startswith( + "Function 'error_function' raised an exception; returning an error result to the model." + ) + assert ("Set include_detailed_errors=True" in execution_warnings[0]) is not include_detailed_errors + assert (_PRIVATE_ERROR_DETAIL in execution_warnings[0]) is enable_sensitive_data async def test_function_invocation_config_include_detailed_errors_false(chat_client_base: SupportsChatGetResponse):