Hooks
Hook system in AgenticX.
Hook System
Hooks intercept LLM and tool calls without forking the runtime. Use them for guardrails, logging, and policy. They are not skills and not MCP servers.
Two layers:
Worked example: confirm a risky shell
Scene. The model wants bash_exec on a destructive command.
- Permissions are Ask Every Time or an allowlist that does not include this command.
- Runtime emits
tool:before_call. Bundledpre_tool_guardcan block mergedrm -rfflags. A quoted commit message must not match. - Near should show an in-app confirm (themed dialog), not a bare
window.confirm. Choose Allow / Deny.Run Everythingmust stick — no second popup for the same class of call.
What you should see. A dialog over a folded bash_exec card, countdown if the gate has one. After deny, the tool result explains the block; the chat continues.

| Layer | Package path | Purpose |
|---|---|---|
| Core hooks | agenticx/core/hooks/ | Synchronous interception around LLM and tool calls |
| Runtime hooks | agenticx/runtime/hooks/ | Async lifecycle hooks on AgentRuntime |
Core Hooks (agenticx/core/hooks/)
Core hooks are plain callables registered globally or on an Agent instance.
LLM hooks
Context type: LLMCallHookContext.
Before call fields:
| Field | Description |
|---|---|
agent_id | Agent identifier |
task_id | Optional task id |
messages | Message list (may be mutated) |
model | Optional model name |
temperature | Optional sampling temperature |
max_tokens | Optional cap |
iteration | Loop iteration index |
Registration:
python
1from agenticx.core.hooks import (2 LLMCallHookContext,3 register_before_llm_call_hook,4 register_after_llm_call_hook,5)67def log_before_llm(ctx: LLMCallHookContext) -> bool:8 # Mutate ctx.messages in place if needed9 return True # False blocks the LLM call1011register_before_llm_call_hook(log_before_llm)
Tool hooks
Context type: ToolCallHookContext.
Before call fields:
| Field | Description |
|---|---|
agent_id | Agent identifier |
tool_name | Tool being invoked |
tool_args | Argument dict (may be mutated) |
iteration | Loop iteration |
Runtime Hooks (agenticx/runtime/hooks/)
Runtime hooks are async methods on subclasses of AgentHook, coordinated by HookRegistry.
AgentHook base class
| Method | Role |
|---|---|
before_model(messages, session) | Transform message sequence before LLM call |
after_model(response, session) | Observe or side-effect after model returns |
before_tool_call(tool_name, arguments, session) | Return HookOutcome(blocked=True) to veto |
after_tool_call(tool_name, result, session) | Replace tool result string |
on_compaction(compacted_count, summary, session) | After context compaction |
on_agent_end(final_text, session) | End of agent turn |
HookOutcome
python
1@dataclass2class HookOutcome:3 blocked: bool = False4 reason: str = ""
Example: block a tool
python
1from agenticx.runtime.hooks import AgentHook, HookOutcome23class DenyShellHook(AgentHook):4 async def before_tool_call(self, tool_name, arguments, session):5 if tool_name in {"run_terminal_cmd", "bash"}:6 return HookOutcome(blocked=True, reason="Shell tools disabled")7 return None89runtime.hooks.register(DenyShellHook(), priority=100)
Core vs Runtime hooks
| Aspect | Core | Runtime |
|---|---|---|
| Execution model | Synchronous callables | async methods on AgentHook |
| Block LLM | before hook returns False | Transform in before_model |
| Block tool | before hook returns False | HookOutcome(blocked=True) |
| Registry | Module-level lists + Agent.llm_hooks | HookRegistry with numeric priority |
| Typical uses | Logging, policy, rewriting | Streaming lifecycle, memory hooks |