Field reference:
hooks — every field, type, default, and tier for this page.Creating a hook
- Open your agent and go to Hooks in the sidebar (under Advanced).
- Click Add hook.
- Fill in a Name, pick an Event, set the target URL, and choose Mode (
Non-blockingorBlocking). - Optionally set a Timeout (ms) (for blocking hooks), add Custom headers, and a Signing secret.
- Save.
Events
Blocking hooks wait for your endpoint before the agent continues. They can halt, rewrite, or replace any part of the request — see the response protocol below.
Non-blocking hooks fire in the background and the agent never waits for a response.
Reacting to inbound email/IM. The most-requested hook is On inbound message — it fires the moment an email or IM message reaches the agent, before any reply is generated. As a blocking hook it can drop the message or suppress the reply entirely; as non-blocking it gives you a real-time feed of everything arriving on your channels.
Hooks are one stage of the event pipeline. Two sibling features handle inbound events (email, webhooks, feeds, IM, MCP) earlier and locally, without an external endpoint:
- Event pre-processor — your own code in a sandbox (Python 3.11 / Node 20) that runs before any hook, the LLM classifier, and the agent, returning a verdict (
pass_to_agent/drop/store/run_tool/respond). It’s the cheapest place to filter bulk mail or health-check pings, because adrophere skips the classifier entirely — and it fails open, so an event is never silently lost. - Interpreters — named match rules (JSON field presence or regex) that prepend a plain-language hint telling the agent what an event is before it reads the body, when one ingress receives several different payload types.
Examples — from simple to advanced
Hello world — log every conversation. Add a Conversation start hook, mode Non-blocking, pointing at your logging endpoint. Every new session POSTs to your URL with the session metadata. The agent never waits; you get a real-time feed of conversations into your own systems. No response protocol needed — fire and forget. Simple — Slack notification on errors. Add an On error hook (non-blocking) pointing at a Slack incoming-webhook relay. Whenever the engine fails, you get a Slack message. Pair with an On rate limit hook to know when quota is biting. Medium — moderate incoming messages. Add an On user message hook, mode Blocking. Your endpoint inspects the message and returns the response protocol: allow it through, or halt with a polite refusal if it violates your policy. This is a content gate that runs before the agent ever sees the message. See Response protocol. Complex — inject live context before the LLM call. Add a Before query hook (blocking) that looks up the user in your CRM and returns extra system context (their account tier, open tickets) for the agent to use — so every reply is personalised with data the agent didn’t have to ask for. See Full prompt control (pre_query). Complex — gate and rewrite tool calls. Add a Before tool call hook (blocking) that intercepts asend_email call, checks the recipient against an allow-list, and either lets it proceed, rewrites the arguments, or blocks it. This is policy enforcement at the tool boundary — the agent proposes, your hook disposes. See Tool interception (pre_tool_call).
Scope a tool-call hook to one tool. On a Before tool call hook, set Tool name pattern to ^send_email$ (or click Select tools and pick it from the list) so the hook fires only for that tool instead of every tool call. See Advanced options → Tool filter.
Page only on critical alerts. On an On alert hook, set Minimum severity to critical so you are notified only for the most severe monitoring alerts, not for every info or warning. See Advanced options → Alert filter.
System-pushing — a full control plane. Combine blocking hooks across the lifecycle: On user message to moderate, Before query to inject context, Before tool call to enforce tool policy, After tool call to redact sensitive fields from results, and After query to run a final compliance check that can replace the response before it reaches the user — all signed with HMAC so your endpoints can verify the requests came from Agentheya. At this point your hooks form an external governance layer that sees and can rewrite every step of every conversation. The detailed reference for each of these follows below.
Payload
Every payload includes:messages_context contains the last five turns (truncated to 500 chars each) so your endpoint always has conversational context without needing to maintain its own session state.
Event-specific fields are included on top:
on_user_message:query,user_name,caller_user_id,caller_ip,accessed_viapre_query:query,system_prompt,sections_used,retrieval_hits_count,tool_names,modelpre_tool_call/post_tool_call:tool,args, and (on post)resultpost_query:user_message,agent_response,tool_calls, token usage
Response protocol
Your endpoint returns JSON. Returning2xx with no body continues normally.
Decision field
User-visible blocking
When you block a request and want the user to see a friendly message instead of an error:block_message is returned to the user as an assistant response in the chat. reason is logged server-side only.
UI notifications
Surface a markdown notification to the user before the LLM responds (non-blocking path):Full prompt control (pre_query)
pre_query blocking hooks have full control over what the LLM sees.
Replace the system prompt
Append context
<hook_context>. Lighter-weight than full replacement when you only need to inject runtime data.
Replace the messages array
MessageParam[] array (role + content blocks).
Inject messages
Tool interception (pre_tool_call)
Rewrite arguments
Skip execution and return a synthetic result
result_override as the tool result. Use for caching, mocking, or replacing external calls at runtime.
Block a tool call
block_message as the error the LLM sees. The LLM can then relay this to the user naturally in its response.
Post-tool result rewriting (post_tool_call)
Post-query response replacement (post_query, blocking)
Configure the hook as blocking. Return:Request signing (HMAC-SHA256)
Set a Signing secret on a hook to enable Standard Webhooks compatible request signing. Every request will carry three headers:
The signed content is:
"<webhook-id>.<webhook-timestamp>.<request-body>".
Verification example (Python):
Advanced options
Custom headers — addAuthorization: Bearer <token> or X-Api-Key: <key> for endpoint authentication.
Timeout — maximum wait time in milliseconds (default: 5000, range 500–60000). Only applies to blocking hooks. Blocking hooks that time out treat the request as blocked (fail-closed). Increase this for hooks that do heavy work.
Method — every hook is delivered as POST with a JSON body.
Tool filter (pre_tool_call / post_tool_call only) — restrict a hook to specific tools by name pattern (regex), by selecting from the tool list (Select tools button), or both.
Alert filter (on_alert only) — restrict by minimum severity (info, warning, critical).
Hook order — drag the hook card by its header to reorder. Order matters for blocking hooks in the same event (see “Multiple hooks” above).
Multiple hooks, chain behaviour
You can have multiple blocking hooks for the same event. They run sequentially. The firstblock decision halts the chain immediately — later hooks do not run. continue hooks run to completion and their rewrites accumulate (last writer wins for system_prompt_override, messages_override, args_override; appended for messages_append, additional_context).
Example — CRM context injection
Configure a Before query hook pointing at an endpoint that fetches the user’s CRM record and returns it asadditional_context. Zero latency impact if you keep the lookup under your timeout budget.
Example — compliance guardrail
Configure an On user message hook that sends the message to your moderation API. Block and show a user-friendly message if it violates policy.Manage via the Management MCP
This page can be configured programmatically through the Management MCP — useful for AI agents and CI pipelines.
Example:
config.get to read the current values and schema.get (or the HTTP schema URL above) to see the full field list.