You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
By default, `tool_pre_invoke` and `tool_post_invoke` hooks are **skipped for framework-internal tools** such as the ReAct loop's `final_answer` tool. This prevents allowlist plugins from accidentally blocking internal control flow. See [Internal tool exemption](#internal-tool-exemption) for details and how to opt out.
678
+
The payload includes an `is_control_flow` field that is `True`for framework control-flow tools (e.g. the ReAct loop's `final_answer`). Allowlist plugins should check this field to avoid blocking internal tools. See [Control-flow tools](#control-flow-tools) for the recommended pattern.
return block(f"Tool '{tool_name}' is not permitted", code="TOOL_NOT_ALLOWED")
@@ -882,49 +884,43 @@ with start_session(plugins=[tool_security]) as m:
882
884
883
885
See the [full tool hooks example](https://github.com/generative-computing/mellea/blob/main/docs/examples/plugins/tool_hooks.py).
884
886
885
-
### Internal tool exemption
887
+
### Control-flow tools
886
888
887
-
Mellea's frameworks use internal tools that are invisible to application developers. For example, the [ReAct loop](../reference/glossary#react) uses a `final_answer` tool to signal that the agent has finished reasoning. These tools flow through the same invocation path as user-defined tools, which means a `tool_pre_invoke` allowlist plugin would block them — breaking the framework.
889
+
Mellea's frameworks use internal tools for control flow. For example, the [ReAct loop](../reference/glossary#react) uses a `final_answer` tool to signal that the agent has finished reasoning. These tools flow through the same invocation path as user-defined tools — hooks always fire for them — but the payload carries an `is_control_flow` flag so each plugin can decide its own policy.
888
890
889
-
To prevent this, **tool hooks are skipped for framework-internal tools by default**. Both `tool_pre_invoke` and `tool_post_invoke` are bypassed; the tool itself still executes normally.
890
-
891
-
This means you can write a tool allowlist plugin that lists only your own tools, without worrying about framework internals:
891
+
The recommended pattern for allowlist plugins is to skip control-flow tools explicitly:
If your plugin genuinely needs to intercept internal tools (e.g., for deep audit logging of every tool invocation including framework tools), disable the exemption:
915
+
Use `is_internal_tool()`to check whether a tool name is a known control-flow tool:
917
916
918
917
```python
919
-
from mellea.plugins importset_skip_hooks_for_internal_tools
918
+
from mellea.plugins importis_internal_tool
920
919
921
-
set_skip_hooks_for_internal_tools(False) # all tools now fire hooks
920
+
is_internal_tool("final_answer") # True
921
+
is_internal_tool("get_weather") # False
922
922
```
923
923
924
-
<Warning>
925
-
Disabling the exemption means your allowlist plugin must explicitly permit internal tools like `final_answer`, or the ReAct loop will fail with a `PluginViolationError`.
926
-
</Warning>
927
-
928
924
---
929
925
930
926
## Patterns and best practices
@@ -1026,12 +1022,10 @@ from mellea.plugins import (
1026
1022
PluginViolationError, # Exception raised when a hook blocks execution
1027
1023
block, # Helper to create a blocking PluginResult
1028
1024
hook, # Decorator to register an async function as a hook handler
1029
-
is_internal_tool, # Check if a tool name is framework-internal
1025
+
is_internal_tool, # Check if a tool is a framework control-flow tool
1030
1026
modify, # Helper to create a modifying PluginResult
1031
1027
plugin_scope, # Context manager for with-block scoped activation
1032
1028
register, # Register hooks/plugins globally or per-session
1033
-
set_skip_hooks_for_internal_tools, # Enable/disable tool hook exemption for internal tools
1034
-
skip_hooks_for_internal_tools, # Query current exemption state
0 commit comments