Configure Hooks
Hooks let you subscribe to Snippbot’s internal event stream and react to them — either by running sandboxed Python scripts, forwarding events to external URLs, or triggering built-in actions.
What are hooks?
Section titled “What are hooks?”A hook is a rule that says: when event X happens, do Y. Hooks connect Snippbot’s event bus to the outside world and to your own automation logic.
Examples:
- When a task completes, post a summary to a Slack webhook
- When an agent fails, create a GitHub issue
- When a scheduler job runs, log the result to a custom database
- When a new project is created, send an email notification
Hook types
Section titled “Hook types”| Type | What it does |
|---|---|
python | Run sandboxed Python code with access to the event |
http | HTTP POST to an external URL (outbound webhook) |
builtin | Built-in action provided by a Snippbot module |
Events you can hook
Section titled “Events you can hook”Snippbot emits events on all major state transitions. Events follow a category.action naming convention and are grouped by category in the UI. Common hookable events include:
| Category | Example events |
|---|---|
| task | task.started, task.completed, task.failed, task.queued |
| project | project.created, project.updated, project.completed |
| execution | execution.started, execution.paused, execution.completed |
| job_run | job_run.completed, job_run.failed |
| channel | channel.message.received, channel.message.sent |
| memory | memory.stored, memory.consolidated, memory.recalled |
| workflow | workflow.run.started, workflow.run.completed, workflow.step.failed |
| approval | approval.requested, approval.granted, approval.denied |
When creating a hook, the Event Type dropdown in the form groups all available events by category so you can browse and select the one you need. You can also enter a glob pattern in the Event Pattern field (e.g., task.*) to match multiple events.
Creating a hook
Section titled “Creating a hook”-
Open Hooks from the sidebar navigation
-
Click ”+ Create Hook” in the top-right corner
-
Fill in the hook form:
- Name — a descriptive label (e.g., “Notify Slack on task complete”)
- Description — what the hook does
- Event Type — select from the grouped dropdown (e.g.,
task.completed) - Event Pattern — optional glob to match multiple events (e.g.,
task.*) - Hook Type — choose
Python,HTTP, orBuiltin - Scope —
Global,Project, orAgent
-
Configure type-specific settings (see sections below)
-
Set advanced options:
- Priority — execution order (lower runs first, default 100)
- Timeout — max execution time in milliseconds (default 5000)
- Max Retries — how many times to retry on failure (0-5)
- Permission Tier — controls what the hook can access (0 = read-only, 4 = admin)
- Enabled — toggle the hook on or off
- Can Mutate — if checked, the hook runs sequentially instead of concurrently
-
Add tags and a filter expression (optional), then click Save
HTTP hooks
Section titled “HTTP hooks”HTTP hooks send a JSON POST to an external URL whenever the subscribed event fires.
When you select HTTP as the hook type, the form shows these additional fields:
- Webhook URL — the external endpoint to POST to
- Payload Format — choose “Raw Event JSON” (default), “Slack” (formats for Slack incoming webhooks), or “Google Chat”
- HTTP Headers — custom headers as JSON (e.g.,
{"Authorization": "Bearer ..."}) - HMAC Secret — optional secret for signing outbound requests (click “Generate” for a cryptographically secure value)
- Use reliable queue-backed delivery — enables retry with exponential backoff and dead letter queue
Webhook payloads
Section titled “Webhook payloads”Every HTTP hook delivery sends a JSON POST with this structure:
The payload is a JSON object with these top-level fields:
| Field | Description |
|---|---|
| event | The event name (e.g., task.completed) |
| timestamp | ISO 8601 timestamp of when the event fired |
| hook_id | The unique identifier of the hook that triggered delivery |
| data | An object containing event-specific fields such as task_id, project_id, status, result, and duration_seconds |
Outbound HMAC signing
Section titled “Outbound HMAC signing”If you set an HMAC Secret, Snippbot adds an HMAC-SHA256 signature header to every outbound delivery:
The signature is sent in the X-Snippbot-Signature header in the format sha256=<hex_digest>.
Verify it in your receiver:
import hmac, hashlib
def verify_signature(payload: bytes, signature: str, secret: str) -> bool: expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest() return hmac.compare_digest(f"sha256={expected}", signature)Queue-backed delivery
Section titled “Queue-backed delivery”For critical integrations, check “Use reliable queue-backed delivery” when creating or editing an HTTP hook. This reveals additional settings:
- Retry Delay — initial delay before first retry (default: 10 seconds)
- Multiplier — exponential backoff multiplier (default: 2.0x)
- Max Delay — maximum delay cap (default: 3600 seconds)
Queue-backed hooks use 4 concurrent async workers and persist deliveries to the database for reliability. Non-queued hooks execute inline with fast retry (100ms backoff) — use these when low latency matters more than guaranteed delivery.
Python hooks
Section titled “Python hooks”Python hooks run sandboxed code with access to the event data. When you select Python as the hook type, a code editor appears in the form.
Available in the sandbox:
ctx.event— the triggering event as a dictctx.log(msg)— structured loggingctx.emit(type, data)— emit a new event
if ctx.event["data"]["status"] == "failed": ctx.emit("custom.alert", { "message": f"Task failed: {ctx.event['data']['error']}" })
result = {"processed": True}After creating a Python hook, you can edit the code from the hook’s detail page. Navigate to Hooks in the sidebar, click the hook to open it, then switch to the Code tab for a full editor with line numbers.
Builtin hooks
Section titled “Builtin hooks”Builtin hooks reference a Python module path that Snippbot loads and executes. When you select Builtin as the hook type, enter the module path (e.g., snippbot_core.hooks.bundled.audit_logger).
Snippbot ships with several bundled hooks that appear in the Bundled tab on the Hooks page. These are system-provided and loaded on startup.
Conditional filters
Section titled “Conditional filters”Hooks support a Filter Expression that prevents the hook from firing unless the event matches. The filter builder in the form lets you construct conditions visually, or you can type an expression directly:
For example, you might filter with event.data.task_type == "code_review" and event.data.agent_id == "agent_123" to only fire when a specific agent completes a code review.
The expression is evaluated using safe AST evaluation — no arbitrary code execution.
Managing hooks
Section titled “Managing hooks”All hooks are managed from the Hooks page in the sidebar. The page has four tabs:
- Hooks — your custom hooks with filters for event type, scope, enabled status, and tags
- Webhooks — inbound webhook endpoints that external services can call into Snippbot (see below)
- Bundled — system-provided hooks that ship with Snippbot
- Deliveries — real-time view of the outbound HTTP delivery queue
Editing a hook
Section titled “Editing a hook”Click any hook in the list to open its detail page with these tabs:
- Config — edit all hook settings
- Code — edit Python source code (Python hooks only)
- Executions — view execution history with status, timing, and output
- Analytics — delivery metrics (total, success/failure rate, average latency)
- Test — fire the hook with a synthetic event to verify it works
Enabling and disabling
Section titled “Enabling and disabling”Toggle a hook on or off directly from the hook list using the enable/disable toggle. Disabled hooks remain configured but do not fire.
Deleting a hook
Section titled “Deleting a hook”Click the delete button on any hook in the list. You will be asked to confirm before the hook is permanently removed.
Inbound webhooks
Section titled “Inbound webhooks”Separate from outbound HTTP hooks, inbound webhooks let external services (GitHub, CI/CD, Slack, etc.) push events into Snippbot. These are managed in the Webhooks tab.
Each webhook endpoint provides:
- A unique receive URL that external services can POST to
- HMAC signature verification
- IP allowlisting
- Rate limiting (requests per minute)
- Replay protection
- Optional payload transforms (JSONPath expressions)
- Delivery logging with accept/reject/error status
To create an inbound webhook, switch to the Webhooks tab and click ”+ Create Webhook”.
Delivery monitoring
Section titled “Delivery monitoring”The Deliveries tab on the Hooks page provides real-time visibility into the outbound HTTP delivery queue:
- Queue stats — pending, processing, success, failed, and dead letter counts
- Delivery log — per-delivery details including request headers, response body, duration, and attempt count
- Manual retry — retry any failed or dead-lettered delivery to re-enqueue it
You can also view delivery history for individual hooks from the hook detail page under the Executions tab.
Hook chains
Section titled “Hook chains”One hook can emit events that trigger another hook:
For example, Hook A listens for task.failed and runs a Python script that emits a custom.alert event. Hook B listens for custom.alert and sends an HTTP POST to PagerDuty. The result is an automated chain: a failed task triggers a PagerDuty alert without any manual intervention.
Chains have cycle detection — circular chains are rejected with a validation error. Maximum chain depth: 10.