agent-orchestrator/website/content/docs/plugins/notifiers/webhook.mdx

148 lines
6.7 KiB
Plaintext

---
title: Webhook notifier
description: Generic HTTP POST. Retries, exponential backoff, custom headers.
---
<div style={{ display: "flex", alignItems: "center", gap: "0.75rem", margin: "0.5rem 0 1.25rem" }}>
<Logo name="webhook" size={28} />
<span style={{ fontSize: "0.8125rem", color: "var(--color-fd-muted-foreground)" }}>
Slot: <code>notifier</code> · Name: <code>webhook</code>
</span>
</div>
<PlatformSupport macos="full" linux="full" windows="full" />
Point it at any HTTPS endpoint. AO POSTs a JSON event. Use this for PagerDuty-style integrations, custom dashboards, or anything we don't have a dedicated notifier for.
## Setup
Run the setup command:
```bash
ao setup webhook
```
If a webhook notifier is already configured, the command asks whether to use the
existing webhook URL, add a new webhook URL, or cancel. The add-new path lets you
paste a different endpoint, go back, or cancel before AO sends the setup test.
Before saving, AO also asks which notification priorities the webhook should
receive: `urgent-only`, `urgent-action`, or `all`. For scriptable setup, pass
`--routing-preset <preset>`.
## Use
```yaml title="agent-orchestrator.yaml"
notifiers:
webhook:
plugin: webhook
url: https://example.com/ao-events
headers:
Authorization: "Bearer ${MY_TOKEN}"
X-Source: "agent-orchestrator"
retries: 5 # default 3
retryDelayMs: 2000 # default 1000
notificationRouting:
urgent: [webhook]
action: [webhook]
```
## Config
| Key | Required | Default | What it does |
| -------------- | -------- | ------- | ------------------------------------------------------------ |
| `url` | ✓ | — | HTTPS endpoint that accepts POST |
| `headers` | optional | `{}` | Custom request headers (supports `${ENV_VAR}` interpolation) |
| `retries` | optional | `3` | Retry count on 429/5xx/network errors |
| `retryDelayMs` | optional | `1000` | Base retry delay (exponential backoff) |
## Payload
### Envelope
Every POST has a `type` discriminant. Most events use `notification`:
```json
{
"type": "notification",
"event": {
"id": "3f6a1b2c-...",
"type": "pr.created",
"priority": "info",
"sessionId": "sess_01HXY...",
"projectId": "myproject",
"timestamp": "2026-04-17T15:00:00.000Z",
"message": "PR opened: fix(auth): handle token expiry",
"data": {}
}
}
```
When actions are attached (e.g. approve/retry buttons in supported notifiers):
```json
{
"type": "notification_with_actions",
"event": { "...": "same fields as above" },
"actions": [{ "label": "View PR", "url": "https://github.com/owner/repo/pull/123" }]
}
```
Free-form messages sent via `ao send` arrive as:
```json
{
"type": "message",
"message": "Hello from AO",
"context": {}
}
```
### Event types
| `event.type` | Default priority | When emitted |
| ---------------------------- | ---------------- | ------------------------------------------------- |
| `session.spawned` | `info` | Session created |
| `session.working` | `info` | Agent begins working on the issue |
| `session.exited` | `info` | Agent process exited cleanly |
| `session.killed` | `info` | Session was manually killed |
| `session.idle` | `info` | Agent has been idle for a while |
| `session.stuck` | `urgent` | Agent appears stuck (no activity) |
| `session.needs_input` | `urgent` | Agent is blocked waiting for user input |
| `session.errored` | `urgent` | Agent hit an unrecoverable error |
| `pr.created` | `info` | PR opened by the agent |
| `pr.updated` | `info` | PR updated (new commits pushed) |
| `pr.merged` | `action` | PR was merged |
| `pr.closed` | `info` | PR was closed without merging |
| `ci.passing` | `info` | CI checks passed |
| `ci.failing` | `warning` | CI checks failed |
| `ci.fix_sent` | `info` | Agent sent a CI fix to itself |
| `ci.fix_failed` | `warning` | Agent's CI fix attempt failed |
| `review.pending` | `info` | PR review requested |
| `review.approved` | `action` | PR approved by reviewer |
| `review.changes_requested` | `warning` | Reviewer requested changes |
| `review.comments_sent` | `info` | Review comments sent to agent |
| `review.comments_unresolved` | `info` | Agent left unresolved review comments |
| `automated_review.found` | `warning` | Automated review tool (e.g. BugBot) left comments |
| `automated_review.fix_sent` | `info` | Agent sent fixes for automated review comments |
| `merge.ready` | `action` | PR is approved + CI green — ready to merge |
| `merge.conflicts` | `warning` | Merge conflicts detected |
| `merge.completed` | `action` | PR was successfully merged |
| `reaction.triggered` | `info` | A configured reaction was triggered |
| `reaction.escalated` | `urgent` | A reaction was escalated to a human notifier |
| `summary.all_complete` | `info` | All sessions in the project completed |
### Signature verification
The webhook notifier does **not** sign outgoing requests. There is no `X-Signature` or HMAC header added to POSTs. To secure your endpoint:
- Use a secret `Authorization` header (set via `headers.Authorization` in config, passed as `${MY_TOKEN}`).
- Restrict inbound traffic to your AO host via IP allowlist or VPN.
- Use a reverse proxy with mutual TLS if needed.
## Why use this over a specific notifier
- You want a single endpoint regardless of Slack/Discord/email routing (handled downstream).
- You're building an internal AO dashboard of your own.
- You want structured events for observability tooling (Datadog, Honeycomb, etc.).