From 5acc18f071ebde734642d3d9d1c6a3aa2e46361d Mon Sep 17 00:00:00 2001 From: Charles Duffy Date: Mon, 26 Jan 2026 17:43:25 -0600 Subject: [PATCH] docs(hooks): document exception property on AfterToolCallEvent Related SDK PR: strands-agents/sdk-python#1565 --- docs/user-guide/concepts/agents/hooks.md | 36 ++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/docs/user-guide/concepts/agents/hooks.md b/docs/user-guide/concepts/agents/hooks.md index c0f5cd03..d3ce9445 100644 --- a/docs/user-guide/concepts/agents/hooks.md +++ b/docs/user-guide/concepts/agents/hooks.md @@ -196,6 +196,7 @@ Most event properties are read-only to prevent unintended modifications. However - [`AfterToolCallEvent`](../../../api-reference/python/hooks/events.md#strands.hooks.events.AfterToolCallEvent) - `result` - Modify the tool result. See [Result Modification](#result-modification). + - `exception` *(read-only)* - The original exception if the tool raised one, otherwise `None`. See [Exception Handling](#exception-handling). === "TypeScript" @@ -310,6 +311,41 @@ Modify tool results after execution: {{ ts_not_supported_code("Changing of tool results is not yet available in TypeScript SDK") }} +### Exception Handling + +When a tool raises an exception, the agent converts it to an error result and returns it to the model, allowing the model to adjust its approach and retry. This works well for expected errors like validation failures, but for unexpected errors—assertion failures, configuration errors, or bugs—you may want to fail immediately rather than let the model retry futilely. The `exception` property on `AfterToolCallEvent` provides access to the original exception, enabling hooks to inspect error types and selectively propagate those that shouldn't be retried: + +=== "Python" + + ```python + class PropagateUnexpectedExceptions(HookProvider): + """Re-raise unexpected exceptions instead of returning them to the model.""" + + def __init__(self, allowed_exceptions: tuple[type[Exception], ...] = (ValueError,)): + self.allowed_exceptions = allowed_exceptions + + def register_hooks(self, registry: HookRegistry) -> None: + registry.add_callback(AfterToolCallEvent, self._check_exception) + + def _check_exception(self, event: AfterToolCallEvent) -> None: + if event.exception is None: + return # Tool succeeded + if isinstance(event.exception, self.allowed_exceptions): + return # Let model retry these + raise event.exception # Propagate unexpected errors + ``` + + ```python + # Usage + agent = Agent( + model=model, + tools=[my_tool], + hooks=[PropagateUnexpectedExceptions(allowed_exceptions=(ValueError, ValidationError))], + ) + ``` + +{{ ts_not_supported_code("Exception inspection is not yet available in TypeScript SDK") }} + ### Conditional Node Execution Implement custom logic to modify orchestration behavior in multi-agent systems: