Quick Start
1
Allowlist — drop messages from unknown senders
2
PII redaction — rewrite content before the LLM sees it
How It Works
Decision Table
Supported Adapters
Every built-in messaging adapter honours the gate decision:Custom adapters must call
fire_message_received and check the returned drop / content fields to participate in the gate.Slack @mentions
The Slackapp_mention handler fires MESSAGE_RECEIVED before allow-list checks, so @mentions now flow through the same gate as DMs (previously DM-only).
Mentions also now count toward channel
last_activity and increment messages_inbound_total, so an @mention registers as inbound activity for /health.
Quoted content in the hook
On Telegram, when a user replies to or quotes an earlier message,event_input.content for MESSAGE_RECEIVED is the rendered turn — the quoted block above the new text — so a redaction/deny hook can inspect and veto quoted text too. If the hook rewrites content, the separately-resolved quoted reference is cleared so unredacted quoted text can’t be re-appended after the hook runs.
See Quoted Reply Context.
Common Patterns
Allowlist
Rate Limiter
Keyword Ban
Combined Gate + Redaction
- Blocked user’s messages: agent stays silent, no reply sent.
- Messages containing an SSN pattern: LLM sees
[SSN]instead of the digits. - All other messages: unchanged.
User Interaction Flow
A Telegram user sends a message. The gate runs before the agent responds:Symmetry with Outbound
MESSAGE_RECEIVED (inbound) and MESSAGE_SENDING (outbound) share the same deny / modified_input contract. Use the same pattern for both directions:
For secrets specifically, you don’t have to hand-roll a hook. The built-in Outbound Secret Scrub runs after every
MESSAGE_SENDING hook and masks registered secrets and credential-shaped tokens by default. Keep hooks for policies the core scrub doesn’t cover (PII, company-specific patterns).Best Practices
Keep the gate cheap
Keep the gate cheap
The hook runs on every inbound message. Avoid blocking I/O or heavy computation — use in-memory lookups and pre-compiled regex patterns.
Fail-open, not fail-closed
Fail-open, not fail-closed
Raising an exception lets the message through. Explicitly call
HookResult.deny(...) if you mean to block.Mutate content only for redaction
Mutate content only for redaction
The LLM will see the
modified_input content and may quote it back in replies. Only rewrite when necessary (e.g. PII scrubbing).Use deny for hard blocks, not redaction
Use deny for hard blocks, not redaction
deny prevents agent dispatch entirely. modified_input still dispatches — use it only when you want the agent to respond to the sanitised content.Related
Hook Events
Complete reference for all hook events and input types
Bot Lifecycle Hooks
Gateway, session, and schedule lifecycle hooks
Quoted Reply Context
The hook sees the rendered turn, including any quoted block

