Webhook notifier
Generic HTTP POST. Retries, exponential backoff, custom headers.
Slot:
notifier · Name: webhookmacOSSupported
LinuxSupported
WindowsSupported
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.
Use
notifier:
- type: webhook
url: https://example.com/ao-events
headers:
Authorization: "Bearer ${MY_TOKEN}"
X-Source: "agent-orchestrator"
retries: 5 # default 3
retryDelayMs: 2000 # default 1000Config
| 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:
{
"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):
{
"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:
{
"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
Authorizationheader (set viaheaders.Authorizationin 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.).