Skip to main content
This page catalogs every GitHub event key an agent trigger can listen on, the normalized payload each one carries, and the routing shape that fits it. Read Triggers first for the general trigger schema; this page assumes you know what event, where, message, and routing do.

How GitHub events reach your triggers

GitHub webhooks arrive through auto’s GitHub App and are normalized into provider-neutral event records before routing:
  1. GitHub delivers a webhook for a repository the App is installed on.
  2. auto verifies the delivery signature and resolves the installation to your organization’s GitHub connection.
  3. The connection resource must subscribe to the raw webhook event name (pull_request, issue_comment, …). Unsubscribed events are dropped at ingress and never reach a trigger.
  4. The payload is normalized into a stable shape and stored under an event key like github.pull_request.opened, then routed to every trigger whose event and where match.
A GitHub trigger names its connection so apply can resolve the grant:
The raw webhook names a connection may subscribe to are push, pull_request, check_run, issues, issue_comment, pull_request_review, pull_request_review_comment, pull_request_review_thread, workflow_run, and commit_comment. A connection’s default subscription is ["pull_request"] — if a trigger on another family never fires, check the connection’s events list first.
Trigger event keys are not validated against a closed catalog. A typo like github.pull_request.close (instead of closed) applies cleanly and silently never fires. Copy keys from the tables on this page.

Shared payload fields

Most GitHub events carry the same metadata alongside their event-specific fields. Trigger message templates render {{dot.path}} placeholders against this payload, and where filters address it with $.dot.path — always without a payload. prefix. Not every event carries the full set: push, workflow_run.completed, and check_run events have no github.auto metadata, and of those only check_run.rerequested carries github.author. Events about a specific pull request or issue also carry a top-level artifact identifying it. The artifact is what bind routing resolves: a session bound to the github.pull_request target receives every later event carrying that PR’s artifact.

Pull requests

github.pull_request.<action>

Fires on pull request lifecycle changes. Ingested actions: Payload: the shared fields plus github.pullRequest with id, nodeId, number, title, htmlUrl, headSha, headRef, baseSha, baseRef, state, merged, closedAt, mergeable, mergeableState, mergeCommitSha, and body. Useful placeholders: {{github.pullRequest.number}}, {{github.pullRequest.title}}, {{github.pullRequest.headSha}}, {{github.repository.fullName}}, {{github.action}}. Useful filters:
  • $.github.repository.fullName: acme/widgets — scope to one repository
  • $.github.pullRequest.merged: true — on closed, distinguish a merge from a plain close
  • $.github.author.bot: false — skip bot-opened PRs
Routing: these events carry the github.pull_request bind target, and the idiomatic shape folds a PR’s whole lifecycle into one session — routing: { kind: bind, target: github.pull_request, onUnmatched: spawn }. The first event for a PR finds no bound session and spawns one; the spawn claims the PR binding, and every later synchronize, comment, and review routes back into the same session instead of spawning parallel workers. checks: declarations (managed GitHub check runs the trigger drives) are legal only on github.pull_request.* events. A complete reviewer agent using this shape, adapted from the packaged @auto/agents@latest/pr-review.yaml role:
.auto/agents/pr-review.yaml
Mount ref templates are the one place the payload. prefix is correct (refs/pull/{{payload.github.pullRequest.number}}/head). Trigger message, initialPrompt, and displayTitle templates render against the bare payload and reject {{payload.…}} tokens at apply time.
To react to the merge itself — before, or independent of, any GitHub Sync apply the merge triggers:
closed events are lifecycle facts, not conversation: they never start GitHub Sync plans or mergeability checks at ingress, and the closed-PR conversation suppression described below does not apply to them.

github.pull_request.merge_conflict (synthetic)

auto runs a mergeability check whenever a PR head moves (opened, reopened, synchronize) or its base branch receives a push — one check per open PR whose base is the pushed branch. When the check resolves to a real conflict, auto emits this synthetic event — GitHub itself has no conflict webhook. The payload is the triggering PR event’s payload with type rewritten and github.pullRequest.mergeable, mergeableState, and mergeCommitSha refreshed to the conflict state. A conflict detected from a base-branch push instead carries github.action: "base_updated" and github.basePush { ref, branch, before, after } describing the push that moved the base. Deduplicated per head + base SHA pair, so one conflict fires once. Routing: carries the github.pull_request bind target — deliver it to the session that owns the PR:

Issues

github.issue.<action>

Payload: shared fields plus github.issue (id, nodeId, number, title, htmlUrl, body, state, labels as a string array) and, on label events, github.label { name }. Useful filters: $.github.action: labeled, $.github.label.name: agent-fix, $.github.issue.labels: { contains: "bug" }. Routing: carries the github.issue bind target. Label-driven kickoff is the common pattern — spawn a session when a human labels an issue for an agent, and bind it so follow-up comments route back:

Comments

GitHub sends one issue_comment webhook for comments on both issues and pull requests. auto splits it into two event families so PR conversation and issue conversation bind to the right target.

github.issue_comment.<action> — comments on pull requests

Actions: created, edited, deleted. Fires when the comment’s parent issue is a pull request. Payload: PR artifact, github.pullRequest reference, and github.issueComment with id, nodeId, htmlUrl, body, authorAssociation (GitHub’s OWNER / MEMBER / COLLABORATOR / CONTRIBUTOR / NONE permission signal), createdAt, updatedAt, author, and any attachments. Useful filters: $.github.auto.authored: false (never react to your own comments), $.github.auto.externalBot: false, $.github.issueComment.authorAssociation: MEMBER. Routing: bind on github.pull_request — see the pr-conversation trigger in the reviewer example above.

github.issue.comment.<action> — comments on plain issues

Actions: created, edited, deleted. The non-PR half of the split: payload carries an issue artifact, github.issue reference (number, title, htmlUrl), and the same github.issueComment shape (without authorAssociation). Routing: bind on github.issue.

Reviews

github.pull_request_review.<action>

Actions: submitted, edited, dismissed. Payload: PR artifact, github.pullRequest, and github.review with id, nodeId, htmlUrl, body, state, commitId, submittedAt, author, and attachments. Filter on the verdict: $.github.review.state: changes_requested or approved. Routing: bind on github.pull_request.

github.pull_request_review_comment.<action>

Actions: created, edited, deleted. Inline diff comments. Payload: PR artifact, github.pullRequest, and github.reviewComment with id, reviewId, htmlUrl, body, path, diffHunk, commitId, originalCommitId, line, originalLine, startLine, side, startSide, author, and attachments — enough to locate the exact code the reviewer is pointing at. Routing: bind on github.pull_request.

github.pull_request_review_thread.<action>

Actions: resolved, unresolved. Payload: PR artifact, github.pullRequest, and github.reviewThread { id, nodeId, path, line, side }. Routing: bind on github.pull_request — for example, waking the PR session when a human resolves the last open thread.

Checks and CI

github.check_run.completed

Fires when a check run finishes. Only action=completed is ingested, and the check run must be associated with a pull request — check runs without PR association are dropped at ingress. For CI results on non-PR branches (pushes to main), use github.workflow_run.completed instead. Payload: PR artifact, github.pullRequest (number, headSha, …), and github.checkRun with id, nodeId, name, headSha, status: "completed", conclusion, htmlUrl, externalId, headIsCurrent, and app { slug, owner }. headIsCurrent is true when the run’s head is still the PR’s head at delivery time — a false value means a newer push already superseded the run. Useful filters: $.github.checkRun.conclusion: failure, $.github.checkRun.name: build, $.github.checkRun.headIsCurrent: true. Routing: bind on github.pull_request. The canonical CI-fix loop:
Two delivery behaviors are specific to this event:
  • Defers until idle. A delivered check completion never interrupts the session’s running turn; it waits for the session to go idle. A session mid-push is not derailed by the CI result of its previous head.
  • Stale-head suppression. When the event routes through a github.pull_request bind, a check completion for a head auto has seen before that is no longer the PR’s current head is dropped — superseded runs never trigger redundant fix cycles. Completions for the current head, or for a head auto has never seen, always deliver.

github.check_run.rerequested

Fires when someone presses Re-run on a check in the GitHub UI. Payload: PR artifact, github.checkRun { id, name, headSha, htmlUrl }, github.pullRequest, and github.author (who pressed the button). Routing: bind on github.pull_request — deliver “the human asked for a re-run” to the session that owns the check.

github.check_run.requested_action.<identifier>

Fires when someone presses a custom action button on a check run. The button’s identifier is baked into the event key, so a check offering a fix button produces github.check_run.requested_action.fix. Payload: PR artifact, github.requestedAction { identifier }, github.checkRun, and github.pullRequest. Unlike check completions, requested actions interrupt the running turn immediately — a human pressed a button and expects a response.

github.workflow_run.completed

Fires when a GitHub Actions workflow run ends. Only action=completed is ingested. This is the general “CI finished” primitive for the cases check_run.completed cannot cover — it carries no PR artifact and works for pushes to any branch. Payload: github.workflowRun with id, nodeId, name, path, headBranch, headSha, status: "completed", conclusion, htmlUrl, runNumber, runAttempt, createdAt, updatedAt, runStartedAt, plus github.workflow (id, name, path, state) and the repository. Useful filters: $.github.workflowRun.path: .github/workflows/deploy.yml, $.github.workflowRun.headBranch: main, $.github.workflowRun.conclusion: success. Routing: no bind target — use deliver (typically routeBy: { kind: attributedSessions } to reach the sessions whose work produced the run) or spawn. Deliveries defer until the session is idle, like check completions.

Pushes

github.push

Fires on any push, including branch creation and deletion. Payload: github with installationId, repository, ref (refs/heads/main), branch, before, after, created, deleted, and sender. Useful filters: $.github.branch: main, $.github.created: true, $.github.deleted: false, $.github.repository.fullName. Routing: no bind target — a bind route can never resolve a push; use spawn or deliver. Pushes to a Sync-enabled production branch also start a GitHub Sync apply, and any push starts a mergeability check for each open PR targeting the pushed branch (surfacing as github.pull_request.merge_conflict when a conflict materializes) — platform side effects independent of your triggers.

Commit comments

github.commit_comment.created

Fires when a comment is attached to a commit. Only action=created is ingested. Payload: github.comment with id, nodeId, commitSha, body, htmlUrl, createdAt, updatedAt, and author, plus the repository and shared metadata. No bind target — route with deliver or spawn. Deliveries interrupt immediately. Deploy bots that comment a preview URL onto the deployed commit make this the natural “deploy landed” signal:

Delivery behavior

Rules the router applies to GitHub events after a trigger matches:
  • Echo suppression is yours to declare. The platform tags auto-authored content ($.github.auto.authored) and third-party bots ($.github.auto.externalBot) but does not filter them for you — add both filters to conversation triggers, as in the reviewer example.
  • Closed-PR conversation is suppressed. Comment, review, review-comment, and review-thread events routed through a github.pull_request bind are dropped when the PR is already closed or merged. Archived work does not reopen sessions.
  • Duplicate comment deliveries are deduplicated by body, so a redelivered webhook cannot make an agent process the same comment twice.
  • auto’s own head pushes do route. A pull_request.synchronize caused by an auto session’s push is delivered like any other (with github.auto.authored: true); per-head-SHA dedup collapses redeliveries of the same commit to one routed event.
  • Interrupt vs. defer. github.check_run.completed and github.workflow_run.completed defer until the session is idle; every other GitHub event interrupts the running turn immediately.

Quick reference

For chat events see Slack events, for issue-tracker events see Linear events, and for auto’s own internal events see Lifecycle events.