diff --git a/docs-website/reference/haystack-api/hooks_api.md b/docs-website/reference/haystack-api/hooks_api.md
index f281f7c969d..3d02aabaa45 100644
--- a/docs-website/reference/haystack-api/hooks_api.md
+++ b/docs-website/reference/haystack-api/hooks_api.md
@@ -1,7 +1,7 @@
---
title: "Hooks"
id: hooks-api
-description: "Hooks that run at points in the Agent's run loop and influence it by mutating State, including built-in tool result offloading."
+description: "Hooks that run at points in the Agent's run loop and influence it by mutating State, including built-in tool result offloading and Human-in-the-Loop tool confirmation."
slug: "/hooks-api"
---
@@ -131,6 +131,470 @@ agent = Agent(chat_generator=..., tools=[...], hooks={"on_exit": [require_save]}
- FunctionHook – A `FunctionHook` wrapping the function.
+## human_in_the_loop/dataclasses
+
+### ConfirmationUIResult
+
+Result of the confirmation UI interaction.
+
+**Parameters:**
+
+- **action** (str) – The action taken by the user such as "confirm", "reject", or "modify".
+ This action type is not enforced to allow for custom actions to be implemented.
+- **feedback** (str | None) – Optional feedback message from the user. For example, if the user rejects the tool execution,
+ they might provide a reason for the rejection.
+- **new_tool_params** (dict\[str, Any\] | None) – Optional set of new parameters for the tool. For example, if the user chooses to modify the tool parameters,
+ they can provide a new set of parameters here.
+
+### ToolExecutionDecision
+
+Decision made regarding tool execution.
+
+**Parameters:**
+
+- **tool_name** (str) – The name of the tool to be executed.
+- **execute** (bool) – A boolean indicating whether to execute the tool with the provided parameters.
+- **tool_call_id** (str | None) – Optional unique identifier for the tool call. This can be used to track and correlate the decision with a
+ specific tool invocation.
+- **feedback** (str | None) – Optional feedback message.
+ For example, if the tool execution is rejected, this can contain the reason. Or if the tool parameters were
+ modified, this can contain the modification details.
+- **final_tool_params** (dict\[str, Any\] | None) – Optional final parameters for the tool if execution is confirmed or modified.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Convert the ToolExecutionDecision to a dictionary representation.
+
+**Returns:**
+
+- dict\[str, Any\] – A dictionary containing the tool execution decision details.
+
+#### from_dict
+
+```python
+from_dict(data: dict[str, Any]) -> ToolExecutionDecision
+```
+
+Populate the ToolExecutionDecision from a dictionary representation.
+
+**Parameters:**
+
+- **data** (dict\[str, Any\]) – A dictionary containing the tool execution decision details.
+
+**Returns:**
+
+- ToolExecutionDecision – An instance of ToolExecutionDecision.
+
+## human_in_the_loop/hooks
+
+### ConfirmationHook
+
+A `before_tool` Agent hook that applies Human-in-the-Loop confirmation strategies to pending tool calls.
+
+Register it on an `Agent` to confirm, modify, or reject tool calls before they run:
+
+```python
+from haystack.components.agents import Agent
+from haystack.hooks.human_in_the_loop import (
+ AlwaysAskPolicy,
+ BlockingConfirmationStrategy,
+ ConfirmationHook,
+ NeverAskPolicy,
+ RichConsoleUI,
+ SimpleConsoleUI,
+)
+
+hook = ConfirmationHook(
+ confirmation_strategies={
+ "my_tool": BlockingConfirmationStrategy(
+ confirmation_policy=NeverAskPolicy(), confirmation_ui=SimpleConsoleUI()
+ )
+ }
+)
+agent = Agent(chat_generator=..., tools=[...], hooks={"before_tool": [hook]})
+```
+
+A key may be a single tool name, a tuple of tool names sharing one strategy, or the wildcard `"*"` which applies
+to any tool without a more specific entry. More specific keys win, so you can set a default for all tools and
+override individual ones:
+
+```python
+hook = ConfirmationHook(
+ confirmation_strategies={
+ "delete_file": BlockingConfirmationStrategy(
+ confirmation_policy=AlwaysAskPolicy(), confirmation_ui=RichConsoleUI()
+ ),
+ "*": BlockingConfirmationStrategy(
+ confirmation_policy=NeverAskPolicy(), confirmation_ui=SimpleConsoleUI()
+ ),
+ }
+)
+```
+
+Request-scoped resources for the strategies (e.g. a WebSocket or queue) are passed per run via the Agent's
+`hook_context` argument (`agent.run(messages=[...], hook_context={...})`) and read by the hook with
+`state.data.get("hook_context")`.
+
+This hook only makes sense at the `before_tool` hook point, where the pending tool calls exist (between the model
+requesting tools and those tools running); the Agent enforces this and raises if it is registered elsewhere. Use a
+single ConfirmationHook with one entry per tool (or per tuple of tools) in `confirmation_strategies` rather than
+registering several hooks.
+
+#### __init__
+
+```python
+__init__(
+ confirmation_strategies: dict[str | tuple[str, ...], ConfirmationStrategy],
+) -> None
+```
+
+Initialize the hook with its per-tool confirmation strategies.
+
+**Parameters:**
+
+- **confirmation_strategies** (dict\[str | tuple\[str, ...\], ConfirmationStrategy\]) – Mapping of tool name (or a tuple of tool names) to its `ConfirmationStrategy`.
+ The wildcard key `"*"` applies to any tool without a more specific entry.
+
+#### run
+
+```python
+run(state: State) -> None
+```
+
+Confirm the pending tool calls, rewriting the `messages` in `state` to reflect modifications and rejections.
+
+**Parameters:**
+
+- **state** (State) – The Agent's live `State`. Reads the available tools (`state.data.get("tools")`) and the per-run
+ context (`state.data.get("hook_context")`), and the pending tool calls from the last message; writes the
+ updated conversation back to `messages`. Reads go through `state.data` rather than `state.get`, which
+ deep-copies and would break non-copyable resources (e.g. a WebSocket or client) in `hook_context`.
+
+#### run_async
+
+```python
+run_async(state: State) -> None
+```
+
+Async version of `run`.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serialize the hook, including its confirmation strategies (tuple keys become JSON-array strings).
+
+#### from_dict
+
+```python
+from_dict(data: dict[str, Any]) -> ConfirmationHook
+```
+
+Deserialize the hook, reconstructing its confirmation strategies.
+
+## human_in_the_loop/policies
+
+### AlwaysAskPolicy
+
+Bases: ConfirmationPolicy
+
+Always ask for confirmation.
+
+#### should_ask
+
+```python
+should_ask(
+ tool_name: str, tool_description: str, tool_params: dict[str, Any]
+) -> bool
+```
+
+Always ask for confirmation before executing the tool.
+
+**Parameters:**
+
+- **tool_name** (str) – The name of the tool to be executed.
+- **tool_description** (str) – The description of the tool.
+- **tool_params** (dict\[str, Any\]) – The parameters to be passed to the tool.
+
+**Returns:**
+
+- bool – Always returns True, indicating confirmation is needed.
+
+### NeverAskPolicy
+
+Bases: ConfirmationPolicy
+
+Never ask for confirmation.
+
+#### should_ask
+
+```python
+should_ask(
+ tool_name: str, tool_description: str, tool_params: dict[str, Any]
+) -> bool
+```
+
+Never ask for confirmation, always proceed with tool execution.
+
+**Parameters:**
+
+- **tool_name** (str) – The name of the tool to be executed.
+- **tool_description** (str) – The description of the tool.
+- **tool_params** (dict\[str, Any\]) – The parameters to be passed to the tool.
+
+**Returns:**
+
+- bool – Always returns False, indicating no confirmation is needed.
+
+### AskOncePolicy
+
+Bases: ConfirmationPolicy
+
+Ask only once per tool with specific parameters.
+
+#### __init__
+
+```python
+__init__() -> None
+```
+
+Creates an instance of AskOncePolicy.
+
+#### should_ask
+
+```python
+should_ask(
+ tool_name: str, tool_description: str, tool_params: dict[str, Any]
+) -> bool
+```
+
+Ask for confirmation only once per tool with specific parameters.
+
+**Parameters:**
+
+- **tool_name** (str) – The name of the tool to be executed.
+- **tool_description** (str) – The description of the tool.
+- **tool_params** (dict\[str, Any\]) – The parameters to be passed to the tool.
+
+**Returns:**
+
+- bool – True if confirmation is needed, False if already asked with the same parameters.
+
+#### update_after_confirmation
+
+```python
+update_after_confirmation(
+ tool_name: str,
+ tool_description: str,
+ tool_params: dict[str, Any],
+ confirmation_result: ConfirmationUIResult,
+) -> None
+```
+
+Store the tool and parameters if the action was "confirm" to avoid asking again.
+
+This method updates the internal state to remember that the user has already confirmed the execution of the
+tool with the given parameters.
+
+**Parameters:**
+
+- **tool_name** (str) – The name of the tool that was executed.
+- **tool_description** (str) – The description of the tool.
+- **tool_params** (dict\[str, Any\]) – The parameters that were passed to the tool.
+- **confirmation_result** (ConfirmationUIResult) – The result from the confirmation UI.
+
+## human_in_the_loop/strategies
+
+### BlockingConfirmationStrategy
+
+Confirmation strategy that blocks execution to gather user feedback.
+
+#### __init__
+
+```python
+__init__(
+ *,
+ confirmation_policy: ConfirmationPolicy,
+ confirmation_ui: ConfirmationUI,
+ reject_template: str = REJECTION_FEEDBACK_TEMPLATE,
+ modify_template: str = MODIFICATION_FEEDBACK_TEMPLATE,
+ user_feedback_template: str = USER_FEEDBACK_TEMPLATE
+) -> None
+```
+
+Initialize the BlockingConfirmationStrategy with a confirmation policy and UI.
+
+**Parameters:**
+
+- **confirmation_policy** (ConfirmationPolicy) – The confirmation policy to determine when to ask for user confirmation.
+- **confirmation_ui** (ConfirmationUI) – The user interface to interact with the user for confirmation.
+- **reject_template** (str) – Template for rejection feedback messages. It should include a `{tool_name}` placeholder.
+- **modify_template** (str) – Template for modification feedback messages. It should include `{tool_name}` and `{final_tool_params}`
+ placeholders.
+- **user_feedback_template** (str) – Template for user feedback messages. It should include a `{feedback}` placeholder.
+
+#### run
+
+```python
+run(
+ *,
+ tool_name: str,
+ tool_description: str,
+ tool_params: dict[str, Any],
+ tool_call_id: str | None = None,
+ confirmation_strategy_context: dict[str, Any] | None = None
+) -> ToolExecutionDecision
+```
+
+Run the human-in-the-loop strategy for a given tool and its parameters.
+
+**Parameters:**
+
+- **tool_name** (str) – The name of the tool to be executed.
+- **tool_description** (str) – The description of the tool.
+- **tool_params** (dict\[str, Any\]) – The parameters to be passed to the tool.
+- **tool_call_id** (str | None) – Optional unique identifier for the tool call. This can be used to track and correlate the decision with a
+ specific tool invocation.
+- **confirmation_strategy_context** (dict\[str, Any\] | None) – Optional dictionary for passing request-scoped resources. Useful in web/server environments
+ to provide per-request objects (e.g., WebSocket connections, async queues, Redis pub/sub clients)
+ that strategies can use for non-blocking user interaction.
+
+**Returns:**
+
+- ToolExecutionDecision – A ToolExecutionDecision indicating whether to execute the tool with the given parameters, or a
+ feedback message if rejected.
+
+#### run_async
+
+```python
+run_async(
+ *,
+ tool_name: str,
+ tool_description: str,
+ tool_params: dict[str, Any],
+ tool_call_id: str | None = None,
+ confirmation_strategy_context: dict[str, Any] | None = None
+) -> ToolExecutionDecision
+```
+
+Async version of run. Calls the sync run() method by default.
+
+**Parameters:**
+
+- **tool_name** (str) – The name of the tool to be executed.
+- **tool_description** (str) – The description of the tool.
+- **tool_params** (dict\[str, Any\]) – The parameters to be passed to the tool.
+- **tool_call_id** (str | None) – Optional unique identifier for the tool call.
+- **confirmation_strategy_context** (dict\[str, Any\] | None) – Optional dictionary for passing request-scoped resources.
+
+**Returns:**
+
+- ToolExecutionDecision – A ToolExecutionDecision indicating whether to execute the tool with the given parameters.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serializes the BlockingConfirmationStrategy to a dictionary.
+
+**Returns:**
+
+- dict\[str, Any\] – Dictionary with serialized data.
+
+#### from_dict
+
+```python
+from_dict(data: dict[str, Any]) -> BlockingConfirmationStrategy
+```
+
+Deserializes the BlockingConfirmationStrategy from a dictionary.
+
+**Parameters:**
+
+- **data** (dict\[str, Any\]) – Dictionary to deserialize from.
+
+**Returns:**
+
+- BlockingConfirmationStrategy – Deserialized BlockingConfirmationStrategy.
+
+## human_in_the_loop/user_interfaces
+
+### RichConsoleUI
+
+Bases: ConfirmationUI
+
+Rich console interface for user interaction.
+
+#### __init__
+
+```python
+__init__(console: Console | None = None) -> None
+```
+
+Creates an instance of RichConsoleUI.
+
+#### get_user_confirmation
+
+```python
+get_user_confirmation(
+ tool_name: str, tool_description: str, tool_params: dict[str, Any]
+) -> ConfirmationUIResult
+```
+
+Get user confirmation for tool execution via rich console prompts.
+
+**Parameters:**
+
+- **tool_name** (str) – The name of the tool to be executed.
+- **tool_description** (str) – The description of the tool.
+- **tool_params** (dict\[str, Any\]) – The parameters to be passed to the tool.
+
+**Returns:**
+
+- ConfirmationUIResult – ConfirmationUIResult based on user input.
+
+#### to_dict
+
+```python
+to_dict() -> dict[str, Any]
+```
+
+Serializes the RichConsoleConfirmationUI to a dictionary.
+
+**Returns:**
+
+- dict\[str, Any\] – Dictionary with serialized data.
+
+### SimpleConsoleUI
+
+Bases: ConfirmationUI
+
+Simple console interface using standard input/output.
+
+#### get_user_confirmation
+
+```python
+get_user_confirmation(
+ tool_name: str, tool_description: str, tool_params: dict[str, Any]
+) -> ConfirmationUIResult
+```
+
+Get user confirmation for tool execution via simple console prompts.
+
+**Parameters:**
+
+- **tool_name** (str) – The name of the tool to be executed.
+- **tool_description** (str) – The description of the tool.
+- **tool_params** (dict\[str, Any\]) – The parameters to be passed to the tool.
+
## protocol
### Hook