Skip to main content

Hooks

A hook is an address you give a CI service or other webhook sender. When an event arrives, Saggar's relay holds the result until your Mac is listening, and Saggar either opens an agent terminal to investigate the failure, triages a labeled issue, or waits for you to look first. The point is that the investigation is already underway by the time you sit back down.

Setting one up

  1. Open a project, choose the Automations tab, select Hooks, and click New hook.
  2. Saggar asks the relay for an address and shows it with a signing secret, once.
  3. Click Set up GitHub with agent and your own agent registers the webhook on the repository with the GitHub CLI.

If you would rather do it by hand, copy the address and the secret into the repository's webhook settings with the content type set to JSON and the workflow_run, issues, and pull_request_review events selected.

GitHub sends a ping when the webhook is created. The hook shows Connected in the Automations tab once it arrives.

Using another webhook sender

Any sender can use the hook if it can send JSON and sign the raw request body with HMAC-SHA256.

  • Put the hex digest in the X-Hub-Signature-256 header, prefixed with sha256=.
  • The JSON object must include a non-empty title.
  • It can also include key, repo, branch, sha, url, conclusion, and detail.
  • Events with the same key replace one another while queued.

A service with fixed payloads or a different signing scheme needs a small adapter to reshape and sign the request. The first accepted event marks the hook as connected.

GitHub issue triage

LabelWhat the agent does
saggarReads the issue with the GitHub CLI, checks it against the repository, and posts one concise triage comment. It then stops.
saggar:actAuthorizes implementation. The agent works on a new branch in a sibling worktree, opens a pull request that closes the issue, and comments back with the result. It never pushes directly to the target branch.

Both labels send the issue through the same review or automatic-investigation flow.

The label is the authorization boundary. The relay carries only the issue number, title, URL, repository, author, and intent; it drops the body and comments. The agent fetches those separately and treats them as untrusted problem reports, never as instructions.

Requested pull request changes

When a reviewer submits a formal Request changes review, Saggar fetches the review and its inline comments with the GitHub CLI. The agent groups concrete fixes, disagreements, resolved points, and questions, then comments on the pull request and stops.

Review prose does not cross the relay and cannot authorize changes. Add saggar:act to the pull request before the review is submitted to let the agent address clear feedback on the existing pull request branch. Forked pull requests, unsafe branch names, and product decisions stop at triage.

Review first, investigate, or fix

Each hook has one of three modes.

ModeWhat happens when a run fails
Review firstThe default. The run lands in the Activity tab as Needs you, with Investigate and Dismiss beside it, and the Automations tab wears a count in the project landing.
Investigate automaticallyAn agent terminal opens the moment the failure arrives, without stealing the screen. The agent reads the failure and reports back; it changes nothing unless you ask it to in that terminal.
Fix automaticallyOne step further: the agent may commit and push a fix.

Either way the terminal is titled after the workflow and branch so it is easy to find in the Project menu.

Settings that apply to every hook

Two choices apply to every hook at once and live in Settings under Agents, in the Automation pane. Each hook keeps its own mode either way.

  • Investigate with picks the agent a hook opens, defaulting to the last agent you launched.
  • Pause automatic launches holds every failure an automatic hook would have acted on in the Activity tab, with a note saying why, until you turn it off.

What the agent is told

The prompt the agent receives is Saggar's own. It quotes the repository, workflow, branch, commit, and run URL as data and asks the agent to read the failed steps with the GitHub CLI.

The terminal opens in your checkout, which may be mid-edit, so the prompt declares that directory read-only: no edits, no stash, no branch switch. A fix is made in a sibling worktree cut at the failing commit, and pushed to the branch only when your checkout isn't on it; otherwise the agent pushes a hook/fix- branch named for the commit and opens a pull request, so your local branch never falls behind its remote without warning.

A passing run on the same branch retires an earlier failure that was still waiting, and a repeat failure while an agent is already on it is held rather than doubled up.

A Claude Code terminal opened by a hook, reading the failed steps of a Swift CI run and checking the repository's secrets

This is what the handoff looks like. A Swift CI run failed on main, the hook opened a terminal titled after it, and the agent had pulled the failed log and traced the cause to a missing repository secret before anyone read the notification. The last step of the prompt matters as much as the first: a flaky, infrastructural, or judgment-shaped failure ends in a summary, not a push.

When the Mac is away

The relay keeps undelivered events for up to a week and hands them over the next time the Mac connects. Runs of the same workflow on the same branch replace one another while the Mac is away, so you come back to the latest result, not the history.

Sleep still wins: a hook cannot wake a Mac, so a closed lid means the investigation starts when you open it.

Transparency

Every delivery leaves a record in the project's Activity tab with its verdict: investigating, needs you, skipped, superseded, connected, or dismissed. Every delivery is also written to the remote-control audit log, so nothing arrives silently.

What the relay knows

Hooks ride the same relay and the same subscription as remote control, and the Mac still never listens on your network. Unlike a remote-control request, a webhook reaches the relay in the clear, because an external service sent it.

The relay keeps a small digest of it, a few named fields rather than the payload, and only a delivery signed with the hook's secret is accepted. Deleting a hook closes its address for good.

Ideas for hooks

A useful hook says that something deserves investigation or a decision, not merely that something happened. The generic endpoint can receive these signals today when the sender, or a small adapter, reshapes and signs them. Native support for more GitHub event types may follow the same model as CI runs, labeled issues, and requested pull request changes.

  • Pull request review requested: run targeted checks, inspect the diff, flag risks, and prepare a review.
  • Merge conflict introduced: explain the conflicting intent before anyone chooses whether an agent should resolve it.
  • Dependency update opened: read the release notes, look for breaking changes, run the affected checks, and recommend a verdict.
  • Deployment failed: separate code failures from infrastructure failures and connect the result to the responsible change.
  • Sentry regression: correlate a new error with recent deployments and commits, then update one issue rather than opening a flock.
  • Support escalation: turn a report into a reproduction recipe and likely owner without copying sensitive customer data into a prompt.
  • Scheduled hygiene: find stale pull requests, unanswered issues, broken documentation links, or abandoned branches once a week.

These patterns tend to deepen through the same four steps: record the event, triage it, propose a response, then act only when the hook's configuration or an explicit signal grants that authority. Receiving an event should never grant more permission by accident.