Skip to main content
Agent Orchestrator uses a push notification model—agents notify humans only when judgment is required. Configure notifiers and routing to control where notifications go based on priority.

Notifier System Overview

The notification system has two parts:
1

Notifier Plugins

Define notification channels (Slack, Discord, webhooks, etc.)
2

Notification Routing

Route notifications to channels based on priority level
When an event occurs, the orchestrator:
  1. Determines event priority (urgent, action, warning, info)
  2. Looks up which notifiers should receive that priority
  3. Sends the notification to all configured channels
Source: packages/core/src/lifecycle-manager.ts:422-431

Built-in Notifiers

Agent Orchestrator includes 4 built-in notifiers:
NotifierDescriptionUse Case
desktopNative OS notificationsLocal development, immediate alerts
composioComposio integrationTeam visibility, workflow automation
slackSlack webhooksTeam channels, async updates
webhookCustom HTTP webhooksCustom integrations, logging
Source: packages/core/src/plugin-registry.ts:43-46

Desktop Notifier

Native OS notifications for local development.
defaults:
  notifiers: [desktop]
Desktop notifier is enabled by default. No additional configuration needed.
Supports:
  • macOS (Notification Center)
  • Linux (libnotify)
  • Windows (Toast notifications)

Composio Notifier

Integration with Composio platform for team visibility.
defaults:
  notifiers: [composio, desktop]
Composio notifier is included in default notifiers. Remove it if you don’t use Composio:
defaults:
  notifiers: [desktop]  # Desktop only

Slack Notifier

Send notifications to Slack channels via incoming webhooks.

Setup

1

Create Incoming Webhook

  1. Go to https://api.slack.com/messaging/webhooks
  2. Create a new webhook for your workspace
  3. Choose a default channel
  4. Copy the webhook URL
2

Set Environment Variable

export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
Add to your shell profile (~/.zshrc, ~/.bashrc):
echo 'export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..."' >> ~/.zshrc
source ~/.zshrc
3

Configure Notifier

notifiers:
  slack:
    plugin: slack
    webhook: ${SLACK_WEBHOOK_URL}
    channel: "#agent-updates"
4

Add to Routing

notificationRouting:
  urgent: [desktop, slack]
  action: [desktop, slack]
  warning: [slack]
  info: [slack]

Configuration

notifiers.slack
object
Slack notifier configuration
notifiers.slack.plugin
string
required
Must be slack
notifiers.slack.webhook
string
required
Slack incoming webhook URL. Use ${SLACK_WEBHOOK_URL} to reference environment variable.
notifiers.slack.channel
string
Default channel for notifications (e.g., #agent-updates). Can be overridden per-notification.
notifiers.slack.username
string
default:"Agent Orchestrator"
Bot username displayed in Slack

Example

notifiers:
  slack:
    plugin: slack
    webhook: ${SLACK_WEBHOOK_URL}
    channel: "#agent-updates"
    username: "Agent Orchestrator"

notificationRouting:
  urgent: [desktop, slack]  # Critical alerts to both
  action: [desktop, slack]  # Action items to both
  warning: [slack]          # Warnings to Slack only
  info: [slack]             # Info to Slack only
Source: packages/plugins/notifier-slack/src/index.ts, examples/multi-project.yaml:45-57

Webhook Notifier

Send notifications to custom HTTP endpoints.

Configuration

notifiers.webhook
object
Webhook notifier configuration
notifiers.webhook.plugin
string
required
Must be webhook
notifiers.webhook.url
string
required
HTTP endpoint URL. Use ${WEBHOOK_URL} to reference environment variable.
notifiers.webhook.method
string
default:"POST"
HTTP method: POST, PUT, PATCH
notifiers.webhook.headers
object
Custom HTTP headers (e.g., authentication)

Example

notifiers:
  webhook:
    plugin: webhook
    url: https://your-service.com/agent-events
    method: POST
    headers:
      Authorization: "Bearer ${WEBHOOK_TOKEN}"
      Content-Type: "application/json"

notificationRouting:
  urgent: [desktop, webhook]
  action: [webhook]
  warning: [webhook]
  info: [webhook]

Webhook Payload

The webhook receives a JSON payload with event details:
{
  "id": "evt_abc123",
  "type": "ci.failing",
  "priority": "warning",
  "sessionId": "my-app-5",
  "projectId": "my-app",
  "timestamp": "2026-03-04T12:34:56.789Z",
  "message": "CI checks are failing",
  "data": {
    "prUrl": "https://github.com/org/repo/pull/123",
    "ciStatus": "failing",
    "branch": "feature/new-thing"
  }
}
Source: packages/core/src/types.ts:747-757

Notification Routing

Route notifications to different channels based on priority level.
notificationRouting:
  urgent: [desktop, slack]   # Critical issues
  action: [desktop, slack]   # Action required
  warning: [slack]           # Something to be aware of
  info: [slack]              # Informational only

Priority Levels

notificationRouting.urgent
array
Urgent priority — Critical issues requiring immediate attention:
  • Agent stuck
  • Agent needs input (permission prompt, question)
  • Agent crashed/exited
  • Multiple failed escalations
Recommended routing: Desktop + Slack (immediate attention)
notificationRouting.action
array
Action priority — Action required but not urgent:
  • PR ready to merge (approved + CI green)
  • Manual intervention needed
Recommended routing: Desktop + Slack (check when convenient)
notificationRouting.warning
array
Warning priority — Something to be aware of:
  • Auto-fix failed (escalated after retries)
  • CI failing (after automatic retries exhausted)
  • Review comments (after automatic handling failed)
Recommended routing: Slack only (async, no immediate action)
notificationRouting.info
array
Info priority — Informational only:
  • All agents complete
  • PR merged successfully
  • Session summary
Recommended routing: Slack only (FYI, no action needed)
Source: packages/core/src/types.ts:705-706

Default Routing

If you don’t specify notificationRouting, these defaults apply:
notificationRouting:
  urgent: [desktop, composio]
  action: [desktop, composio]
  warning: [composio]
  info: [composio]
Source: packages/core/src/config.ts:99-104

Routing Examples

Desktop-only (local development):
defaults:
  notifiers: [desktop]

notificationRouting:
  urgent: [desktop]
  action: [desktop]
  warning: [desktop]
  info: [desktop]
Slack-only (team environment):
defaults:
  notifiers: [slack]

notifiers:
  slack:
    plugin: slack
    webhook: ${SLACK_WEBHOOK_URL}
    channel: "#agent-updates"

notificationRouting:
  urgent: [slack]
  action: [slack]
  warning: [slack]
  info: [slack]
Hybrid (local + team):
defaults:
  notifiers: [desktop, slack]

notifiers:
  slack:
    plugin: slack
    webhook: ${SLACK_WEBHOOK_URL}
    channel: "#agent-updates"

notificationRouting:
  urgent: [desktop, slack]   # Critical: both
  action: [desktop, slack]   # Action: both
  warning: [slack]           # Warning: team only
  info: [slack]              # Info: team only
Multiple channels:
notifiers:
  slack-team:
    plugin: slack
    webhook: ${SLACK_WEBHOOK_TEAM}
    channel: "#agent-updates"
  
  slack-oncall:
    plugin: slack
    webhook: ${SLACK_WEBHOOK_ONCALL}
    channel: "#oncall-alerts"
  
  pagerduty:
    plugin: webhook
    url: ${PAGERDUTY_WEBHOOK}

notificationRouting:
  urgent: [desktop, slack-oncall, pagerduty]  # Critical: all channels
  action: [desktop, slack-team]               # Action: desktop + team
  warning: [slack-team]                       # Warning: team only
  info: [slack-team]                          # Info: team only

Custom Notification Rules

Adjust notification behavior per reaction:
reactions:
  ci-failed:
    auto: true
    action: send-to-agent
    retries: 3
    escalateAfter: 3
    priority: warning  # Override: warning instead of urgent on escalation
  
  agent-stuck:
    auto: true
    action: notify
    priority: urgent  # Send as urgent
    threshold: 10m
  
  approved-and-green:
    auto: false
    action: notify
    priority: action  # Send as action priority
When reactions escalate or trigger notifications, they use the configured priority to determine routing. Source: packages/core/src/types.ts:774-775

Channel Configuration

Some notifiers support per-notification channel overrides.

Slack Channels

Override the default channel:
notifiers:
  slack:
    plugin: slack
    webhook: ${SLACK_WEBHOOK_URL}
    channel: "#agent-updates"  # Default channel
When posting via the API, you can override:
await notifier.post("Custom message", {
  channel: "#different-channel"
});
Source: packages/plugins/notifier-slack/src/index.ts:171-184

Complete Example

A production-ready notification configuration:
# Default notifiers
defaults:
  runtime: tmux
  agent: claude-code
  workspace: worktree
  notifiers: [desktop, slack, webhook]

# Configure notification channels
notifiers:
  slack:
    plugin: slack
    webhook: ${SLACK_WEBHOOK_URL}
    channel: "#agent-updates"
    username: "Agent Orchestrator"
  
  webhook:
    plugin: webhook
    url: https://your-service.com/agent-events
    method: POST
    headers:
      Authorization: "Bearer ${WEBHOOK_TOKEN}"

# Route by priority
notificationRouting:
  urgent: [desktop, slack]   # Agent stuck, needs input, crashed
  action: [desktop, slack]   # PR ready to merge
  warning: [slack, webhook]  # Auto-fix failed, escalated
  info: [slack, webhook]     # Summary, all done

# Configure reactions with priorities
reactions:
  ci-failed:
    auto: true
    action: send-to-agent
    retries: 3
    escalateAfter: 3
    priority: warning  # Routed to: slack, webhook
  
  changes-requested:
    auto: true
    action: send-to-agent
    escalateAfter: 30m
    priority: warning  # Routed to: slack, webhook
  
  approved-and-green:
    auto: false
    action: notify
    priority: action   # Routed to: desktop, slack
  
  agent-stuck:
    auto: true
    action: notify
    priority: urgent   # Routed to: desktop, slack
    threshold: 10m
  
  agent-needs-input:
    auto: true
    action: notify
    priority: urgent   # Routed to: desktop, slack
  
  all-complete:
    auto: true
    action: notify
    priority: info     # Routed to: slack, webhook
    includeSummary: true

Testing Notifications

Test your notification setup:
# Spawn a test agent
ao spawn my-app TEST-123

# Trigger events to test notifications:
# 1. Push a failing commit → triggers ci-failed → warning priority
# 2. Request changes → triggers changes-requested → warning priority
# 3. Approve PR → triggers approved-and-green → action priority
# 4. Let agent sit idle → triggers agent-stuck → urgent priority
Verify:
  • Desktop notifications appear (for urgent/action)
  • Slack messages arrive in correct channel
  • Webhooks receive POST requests with correct payload

Troubleshooting

No Desktop Notifications

macOS: Grant notification permissions:
  1. System Settings → Notifications
  2. Find Terminal or your terminal app
  3. Enable “Allow Notifications”
Linux: Install libnotify-bin:
sudo apt install libnotify-bin

Slack Webhook Fails

Check webhook URL:
echo $SLACK_WEBHOOK_URL
# Should print: https://hooks.slack.com/services/...
Test webhook manually:
curl -X POST -H 'Content-type: application/json' \
  --data '{"text":"Test from Agent Orchestrator"}' \
  $SLACK_WEBHOOK_URL
Common issues:
  • Webhook URL expired (recreate in Slack)
  • Channel doesn’t exist (check spelling)
  • Workspace permissions (ensure app is installed)

Webhook Timeout

Increase timeout (future feature):
notifiers:
  webhook:
    plugin: webhook
    url: https://slow-service.com/webhook
    timeout: 10000  # 10 seconds
Use async webhooks: Configure your endpoint to return 200 immediately and process async.

Missing Notifications

Check routing:
# This won't send notifications if desktop notifier isn't configured!
notificationRouting:
  urgent: [desktop]  # But desktop isn't in defaults.notifiers!
Solution: Ensure notifiers are in defaults.notifiers or explicitly configured:
defaults:
  notifiers: [desktop, slack]  # Include all notifiers used in routing

Next Steps

Reactions

Configure what events trigger notifications

Projects

Set up projects with custom notification rules

Build docs developers (and LLMs) love