Inbound Webhooks#
External systems push events directly to a managed agent instead of the agent polling for changes. Alertmanager, PagerDuty, GitHub, or anything that POSTs JSON can trigger agent runs or deliver formatted notifications — with no agent-side integration code.
How webhooks work#
Each webhook is a named subscription with its own endpoint. External systems POST JSON payloads to that endpoint. Depending on the subscription's mode, the agent either runs with the payload as context (agent mode) or delivers a rendered message directly to the configured channel (deliver-only mode).
Subscriptions are managed from the Webhooks page in the web UI. One agent can have multiple subscriptions — each with its own name, event filter, delivery target, and prompt template.
Enabling the webhook receiver#
A workspace-level Enable Webhooks toggle controls the receiver. Subscriptions do nothing until this toggle is on.
The toggle is hot — enabling or disabling takes effect immediately with no restart. When disabled, all inbound requests receive a 403 response and no runs are triggered.
Creating a subscription#
Each subscription is configured with the following fields:
| Field | Purpose |
|---|---|
| Name | Unique identifier for the subscription; determines the endpoint path |
| Description | Human-readable explanation of what this subscription handles |
| Events | Event-type filter — scope the endpoint to specific event kinds |
| Deliver To | Where results go: All channels, Chat, or Slack |
| Deliver Only | Toggle between agent mode (off) and deliver-only mode (on) |
| Prompt | Template for the message or agent instruction, with payload substitution |
Prompt templating#
The prompt field supports {dot.path} substitution from the inbound JSON payload. Nested fields use dot notation.
For a payload like:
{"alert": {"name": "HighCPU", "severity": "critical"}}
A prompt of Alert fired: {alert.name} at {alert.severity} severity resolves to Alert fired: HighCPU at critical severity.
{__raw__} inserts the entire raw JSON payload. Unresolved keys pass through as literal text. If no prompt is configured, the raw JSON is used as the agent instruction.
Event-type filtering#
A single endpoint can be scoped to specific event kinds. The filter matches against:
- The
X-GitHub-EventorX-GitLab-EventHTTP header - A top-level
event_typefield in the JSON body
When an event filter is configured, payloads that do not match are ignored (the request still receives a success response, but no run is triggered). Leave the filter empty to accept all events.
Agent mode vs. deliver-only mode#
| Agent mode (default) | Deliver-only mode | |
|---|---|---|
| What happens | The templated prompt is run as an agent instruction | The rendered template is posted directly as a message |
| LLM cost | Normal agent-run cost | Zero |
| Response | 202 with a run ID (fire-and-forget) |
200 synchronous |
| Best for | Events that need investigation or action | Notifications, status updates, pass-through alerts |
Agent mode is the default. Switch to deliver-only when you want zero-cost pass-through of formatted events.
Delivery targets#
Each subscription targets one of three delivery modes:
| Target | Behavior |
|---|---|
| All channels (default) | Broadcasts to web chat AND Slack — DM in personal mode, the main channel in team mode |
| Chat | Web chat only |
| Slack | Slack only; kept out of web Recents |
If no Slack workspace is linked, Slack-targeted deliveries fall back to a web chat thread with a warning. Webhook deliveries are never silently lost.
Response contract and reliability#
HTTP responses#
| Code | Meaning |
|---|---|
202 |
Agent-mode ingestion accepted (fire-and-forget) |
200 |
Deliver-only completed synchronously |
400 |
Malformed request body |
403 |
Receiver disabled or subscription disabled |
404 |
Unknown subscription name |
429 |
Queue full — flood backstop |
Serialization and queueing#
Runs are serialized per subscription. Concurrent deliveries queue and execute one at a time in arrival order. Rapid distinct events are never dropped — they run sequentially.
The queue is capped at 10 pending items per subscription. Beyond that, inbound requests receive 429. This cap acts as a flood backstop for misconfigured or runaway senders.
Error handling#
If an agent-mode run fails, a brief error notice is delivered to the subscription's target channel. The sender already received 202 and will not retry, so a crashed run is never silently swallowed.
Security#
Webhook endpoints follow the same authentication model as every other runtime route: auth is terminated by the platform routing layer in front of the container. The container itself does not perform inbound authentication.
No in-container auth by design
Like all runtime routes, webhook endpoints rely on platform-level authentication. The container trusts that requests reaching it have already passed the platform's auth boundary. Per-subscription HMAC secret verification is scoped during onboarding for customers with specific requirements.
Configuring external systems#
Each subscription's endpoint accepts POST requests with Content-Type: application/json. Point your external system at the subscription's URL (visible on the subscription detail in the web UI) with the following guidance:
Alertmanager#
Configure a webhook receiver in your Alertmanager config targeting the subscription endpoint. Set send_resolved: true if you want the agent to see resolution events.
receivers:
- name: 'lens-agent'
webhook_configs:
- url: '<subscription-endpoint>'
send_resolved: true
PagerDuty#
Add a Generic Webhook (v3) integration on the PagerDuty service. Set the endpoint URL to the subscription URL. PagerDuty sends incident.triggered, incident.resolved, and other lifecycle events as JSON.
GitHub#
Add a repository or organization webhook in GitHub Settings. Set the Payload URL to the subscription endpoint, Content type to application/json, and select the events you want delivered. Use the subscription's event-type filter to scope processing to specific GitHub event types (e.g., push, pull_request, issues).
Current scope#
The following capabilities are available to customers with specific requirements during evaluation:
- Per-subscription HMAC secret verification
- Idempotency-based deduplication
- Per-subscription test invocation from the UI
/webhooksslash command for in-chat management- Per-subscription target-channel selection in team mode
- Heartbeat-style DELIVER/SUPPRESS gate for high-volume resolved events
Related#
- Slack integration — delivery targets and channel modes
- Heartbeat monitoring — always-on polling (webhooks are the push complement)
- Scheduled operations — time-based triggers vs. event-based
- Creating a managed agent — setting up agents that receive webhooks