---
title: GitHub SCM
description: PRs, reviews, and CI status via the gh CLI. Optional webhook for real-time events.
---

<div style={{ display: "flex", alignItems: "center", gap: "0.75rem", margin: "0.5rem 0 1.25rem" }}>
	<Logo name="github" size={28} />
	<span style={{ fontSize: "0.8125rem", color: "var(--color-fd-muted-foreground)" }}>
		Slot: <code>scm</code> · Name: <code>github</code>
	</span>
</div>

<PlatformSupport macos="full" linux="full" windows="full" />

The default SCM. Uses `gh` for PR + review + CI polling. Optional webhook support for reduced poll latency.

## Setup

```bash
gh auth login
```

```yaml title="agent-orchestrator.yaml"
scm: github
projects:
  myproject:
    repo: owner/repo
```

## Webhook endpoint

AO's dashboard receives webhook events at:

```
POST /api/webhooks
```

The absolute URL is `https://<your-ao-host>/api/webhooks`. To expose your local dashboard publicly, see [Remote access](/docs/configuration/remote-access).

### GitHub repo settings

In your GitHub repo go to **Settings → Webhooks → Add webhook**:

- **Payload URL**: `https://<your-ao-host>/api/webhooks`
- **Content type**: `application/json`
- **Secret**: the value of your `secretEnvVar` environment variable
- **Events**: Pull requests, Push, Workflow runs, Pull request reviews, Check suites

### Config

```yaml
scm: github
projects:
  myproject:
    repo: owner/repo
    scm:
      webhook:
        secretEnvVar: GITHUB_WEBHOOK_SECRET # env var holding the HMAC secret
```

Full `webhook.*` sub-object:

| Field             | Default               | Description                                 |
| ----------------- | --------------------- | ------------------------------------------- |
| `enabled`         | `true`                | Enable or disable webhook processing        |
| `path`            | `/api/webhooks`       | Override the receive path                   |
| `secretEnvVar`    | —                     | Name of the env var holding the HMAC secret |
| `signatureHeader` | `x-hub-signature-256` | Header carrying the HMAC-SHA256 signature   |
| `eventHeader`     | `x-github-event`      | Header carrying the event type              |
| `deliveryHeader`  | `x-github-delivery`   | Header carrying the delivery UUID           |
| `maxBodyBytes`    | unlimited             | Reject payloads larger than this (bytes)    |

**Signature**: HMAC-SHA256 over the raw request body. AO compares the computed digest against the value in `x-hub-signature-256` using a constant-time comparison.

Polling is still active as a fallback — webhooks are a latency optimisation, not a hard dependency.

## Batch enrichment (performance)

On every poll cycle AO issues a **single batched GraphQL query** that fetches PR state, CI check results, review decisions, and merge readiness for all active sessions in a project at once. This replaces N × 3 REST calls with a single request.

For rate-limit debugging: even with dozens of concurrent sessions, AO stays well under GitHub's primary rate limit. If you do hit limits, the batch enricher backs off and queues — see [Troubleshooting](/docs/troubleshooting).

## Rate limits

AO paces `gh` calls per-project. If you hit limits anyway, batch-enrichment backs off and queues — see [Troubleshooting](/docs/troubleshooting) for the diagnostic steps.
