Summary
The before_tool_call hook is defined in plugins/hooks.js and exported via createHookRunner(), but it's never called in the actual tool execution flow. This prevents plugins from intercepting tool calls before execution.
Use Case
Security and guardrail plugins need to intercept tool calls to:
- Block operations that exceed trust/budget thresholds
- Enforce risk-based autonomy limits
- Log all tool invocations for audit trails
- Implement zero-trust patterns for AI agents
Current Behavior
- Plugin registers hook via
api.registerHook(["before_tool_call"], handler)
- Hook appears in
hookNames array when listing plugins
- Hook is never invoked — tools execute without calling
runBeforeToolCall
Expected Behavior
Before tool.execute() is called, the hook should fire and allow plugins to:
- Block execution (
{ block: true, blockReason: "..." })
- Modify parameters (
{ params: {...} })
- Log/observe (return
{})
Proposed Fix
In steerable-agent-loop.js (or .ts), inside executeToolCalls(), before the tool.execute() call (~line 254):
// Before tool.execute(), check plugin hooks
if (hookRunner?.hasHooks?.("before_tool_call")) {
const hookResult = await hookRunner.runBeforeToolCall({
toolName: toolCall.name,
toolCallId: toolCall.id,
params: validatedArgs,
}, ctx);
if (hookResult?.block) {
throw new Error(hookResult.blockReason ?? `Tool ${toolCall.name} blocked by plugin`);
}
if (hookResult?.params) {
Object.assign(validatedArgs, hookResult.params);
}
}
result = await tool.execute(toolCall.id, validatedArgs, signal, ...);
Context
Working on [Equilibrium Guard](https://github.com/rizqcon/equilibrium-guard), a zero-trust security layer for AI agents. The plugin infrastructure is excellent — just needs this hook wired up to enable enforcement.
Summary
The
before_tool_callhook is defined inplugins/hooks.jsand exported viacreateHookRunner(), but it's never called in the actual tool execution flow. This prevents plugins from intercepting tool calls before execution.Use Case
Security and guardrail plugins need to intercept tool calls to:
Current Behavior
api.registerHook(["before_tool_call"], handler)hookNamesarray when listing pluginsrunBeforeToolCallExpected Behavior
Before
tool.execute()is called, the hook should fire and allow plugins to:{ block: true, blockReason: "..." }){ params: {...} }){})Proposed Fix
In
steerable-agent-loop.js(or.ts), insideexecuteToolCalls(), before thetool.execute()call (~line 254):