---
title: Reactions
description: Configure what AO does when CI fails, reviews arrive, agents get stuck, or PRs become ready.
---

Reactions are AO's automatic responses to session events. They decide whether AO should message an agent, notify a human, or mark a PR as ready for a merge action.

You do not need to configure reactions to start. AO ships with defaults for CI failures, review comments, merge conflicts, stuck agents, input prompts, and completed sessions.

## Common Recipes

### Watch Without Auto-Recovery

Use this while onboarding AO to a sensitive repo. You still see notifications, but AO stops sending recovery prompts to agents automatically.

```yaml title="agent-orchestrator.yaml"
reactions:
  ci-failed:
    auto: false
  changes-requested:
    auto: false
  bugbot-comments:
    auto: false
  merge-conflicts:
    auto: false
```

### Give CI Recovery More Attempts

```yaml title="agent-orchestrator.yaml"
reactions:
  ci-failed:
    retries: 3
    message: |
      CI is failing. Read the failing check logs, reproduce locally when possible,
      fix the smallest cause, and push the correction.
```

### Escalate Stuck Agents Faster

```yaml title="agent-orchestrator.yaml"
reactions:
  agent-stuck:
    priority: urgent
    threshold: "7m"
```

### Notify On Merge-Ready PRs

`approved-and-green` does not merge by default. It notifies you that the PR is ready.

```yaml title="agent-orchestrator.yaml"
reactions:
  approved-and-green:
    auto: false
    action: notify
    priority: action
```

<Callout type="warning">
	`auto-merge` is currently an intent flag, not a bypass. AO does not ignore branch protection, reviews, or failing
	checks.
</Callout>

## Default Reactions

| Key                  | When it fires                               | Default action  | Notes                                               |
| -------------------- | ------------------------------------------- | --------------- | --------------------------------------------------- |
| `ci-failed`          | CI check fails                              | `send-to-agent` | Sends the agent a recovery prompt                   |
| `changes-requested`  | Human requests changes                      | `send-to-agent` | Sends review feedback to the agent                  |
| `bugbot-comments`    | Known automation leaves actionable feedback | `send-to-agent` | Keeps bot feedback separate from human reviews      |
| `merge-conflicts`    | PR has conflicts                            | `send-to-agent` | Asks the agent to resolve conflicts                 |
| `approved-and-green` | PR is approved and checks pass              | `notify`        | Does not merge unless future SCM support enables it |
| `agent-stuck`        | Agent has been inactive past threshold      | `notify`        | Urgent by default                                   |
| `agent-needs-input`  | Agent is waiting for human input            | `notify`        | Urgent by default                                   |
| `agent-exited`       | Session exits unexpectedly or is killed     | `notify`        | Urgent by default                                   |
| `all-complete`       | Session finishes cleanly                    | `notify`        | Includes summary by default                         |
| `agent-idle`         | Reserved                                    | `send-to-agent` | Defined for future idle handling                    |

## Action Types

| Action          | Meaning                                                     |
| --------------- | ----------------------------------------------------------- |
| `send-to-agent` | Sends `message` into the running agent session              |
| `notify`        | Routes an event to configured notifiers                     |
| `auto-merge`    | Reserved merge intent; currently routes like a notification |

`send-to-agent` is the autonomous recovery path. `notify` is the human awareness path.

## Config Fields

Each reaction accepts:

| Field            | Type                                        | Purpose                                                    |
| ---------------- | ------------------------------------------- | ---------------------------------------------------------- |
| `auto`           | `boolean`                                   | Whether AO should perform the automated action             |
| `action`         | `send-to-agent` \| `notify` \| `auto-merge` | What AO does when the reaction fires                       |
| `message`        | `string`                                    | Message sent to the agent or included in notification text |
| `priority`       | `urgent` \| `action` \| `warning` \| `info` | Notification routing priority                              |
| `retries`        | `number`                                    | Max repeated agent messages before escalation              |
| `escalateAfter`  | `number` or duration string                 | Escalate after attempts or time, whichever applies         |
| `threshold`      | duration string                             | Used by stuck/idle style reactions                         |
| `includeSummary` | `boolean`                                   | Include session summary in the notification                |

Example:

```yaml
reactions:
  changes-requested:
    action: send-to-agent
    retries: 2
    escalateAfter: "30m"
    message: |
      Reviewers requested changes. Read the unresolved comments,
      make the requested fixes, and push an update.
```

## Notification Routing

Reaction `priority` maps to `notificationRouting` in the global config:

```yaml title="~/.agent-orchestrator/config.yaml"
notificationRouting:
  urgent: [desktop, composio]
  action: [desktop]
  warning: [composio]
  info: [composio]
```

Named notifier instances are configured separately:

```yaml title="~/.agent-orchestrator/config.yaml"
notifiers:
  desktop:
    plugin: desktop
  slack:
    plugin: slack
    webhookUrl: ${SLACK_WEBHOOK_URL}
```

## Per-Project Overrides

Put reaction overrides in a local project config to affect only that project:

```yaml title="agent-orchestrator.yaml"
reactions:
  ci-failed:
    retries: 4
  approved-and-green:
    priority: info
```

Project values override global values for the same reaction key.

## CI Failure Flow

CI failure handling happens in two passes:

1. AO sends the configured `ci-failed.message` when the session first enters a failed-CI state.
2. On the next poll, AO sends a structured follow-up with the failing check names, statuses, and URLs.

The second message does not consume the `ci-failed` retry budget. It exists so the agent gets both the instruction and the specific failing checks.

## Review Backlog Throttle

AO throttles review-comment lookups to avoid hammering GitHub or GitLab. Pending human comments and known automation comments are fetched at most once every two minutes per session.

Force a check when you need one immediately:

```bash
ao review-check <session-id>
```

## Event Reference

| Event                      | Reaction             |
| -------------------------- | -------------------- |
| `ci.failing`               | `ci-failed`          |
| `review.changes_requested` | `changes-requested`  |
| `automated_review.found`   | `bugbot-comments`    |
| `merge.conflicts`          | `merge-conflicts`    |
| `merge.ready`              | `approved-and-green` |
| `session.stuck`            | `agent-stuck`        |
| `session.needs_input`      | `agent-needs-input`  |
| `session.killed`           | `agent-exited`       |
| `summary.all_complete`     | `all-complete`       |

## Next Steps

<Cards>
	<Card title="Projects" href="/docs/configuration/projects" description="Apply reaction overrides to one project." />
	<Card
		title="Webhook notifier"
		href="/docs/plugins/notifiers/webhook"
		description="Send AO events to any HTTPS endpoint."
	/>
	<Card
		title="Configuration"
		href="/docs/configuration"
		description="Understand global registry vs local project config."
	/>
</Cards>
