Controlling an agent from a GitHub pull-request review
Type @agentis in a PR comment — or on a single line of the diff — and an agent run starts with the whole pull request as context. A look under the hood of the Agentis GitHub bridge: webhooks, signature checks, inline code locations and the guards that keep a noisy repo from launching a fleet.
Ondřej Novák
Founder
Code review is where the most precise instructions in your whole workflow get written — and where they usually die. A reviewer points at a line and says exactly what is wrong and exactly how to fix it, and then a human has to read that, switch branches, make the change, and push. The GitHub bridge removes that last hop. You mention the bot in a pull-request comment, an agent run starts with the entire PR as context, and when the comment sits on a specific line of the diff, the agent knows precisely which line you meant. This is how that round trip is built.
A mention becomes a task
The bridge is a small FastAPI server that listens for two GitHub webhook events. An issue_comment is a comment in the PR conversation tab; a pull_request_review_comment is an inline comment pinned to a line in the diff. Both can mention the bot, and the only trigger is the handle in the text — @agentis by default — matched as a case-insensitive substring. There is no slash command and no special syntax to learn.
@agentis this loop is O(n²) — rewrite it to use the lookup map we built aboveWhen a matching comment arrives, the bridge strips the mention out of the text to get the instruction, then assembles the context an agent actually needs: the PR title and body, the full unified diff, and the history of prior comments on the thread. It folds all of that into the task description, starts a run against the configured project and agent, and records the GitHub coordinates — repo, PR number, comment id, author, base and head refs, head SHA — in the task headers. The run is created with a fresh worktree, so the agent works on an isolated checkout rather than your branch in place.
Inline comments carry their location
The interesting case is the inline review comment, because it has something a chat message never does: a position in the code. When the comment is pinned to the diff, the bridge captures the file path, the line (or line range) it covers, the side of the diff, the commit SHA, and the id of any comment it is replying to. It then puts that location and the surrounding diff hunk at the very top of the task description, so the first thing the agent reads is exactly where in the code you were pointing.
There is a small robustness detail here that matters in real repos: on an outdated comment — one left on code that has since changed — GitHub returns a null line. The bridge falls back to the original_line and original_start_line fields so the location survives even when the diff has moved on under it.
“A chat bot knows what you said. A review bot also knows which line you were looking at when you said it.”
Three guards before anything runs
A bridge that turns comments into agent runs has to be conservative, because repositories are noisy and GitHub redelivers webhooks. Several cheap checks sit in front of every run. It ignores anything that is not a freshly created comment, anything from a bot account (including itself, so it can never answer its own output), and any comment that does not mention the handle. An event deduper keyed on the X-GitHub-Delivery id drops retried deliveries for ten minutes, so GitHub redelivering the same event never spawns a second task. And a global rate limiter caps how many events become runs in a window — thirty per minute by default — so a review storm on a big PR cannot accidentally launch a fleet of agents.
The acknowledgement you see is deliberately quiet. When the task is created, a 👀 reaction lands on your comment; if something fails on the way, a 😕 reaction appears instead. No chatty “on it” reply cluttering the thread — a reaction is enough, and crucially, a failure to talk to GitHub never takes the agent run down with it. Every reaction is best-effort.
Signed webhooks, answered fast
Every webhook is verified before it is trusted. The server recomputes the X-Hub-Signature-256 HMAC over the raw request body and compares it in constant time; an unsigned or mismatched request is rejected with a 401 and never reaches the handler. A valid request gets the opposite treatment — it is acknowledged immediately with a 202 and the heavy work (fetching the diff, building the task, starting the run) runs in the background. GitHub sees a fast endpoint, and the agent work happens off the request path.
App or token, your choice
Authentication comes in two flavours. The recommended one is a GitHub App: the bridge signs a short-lived RS256 JWT with the app’s private key and exchanges it for an installation token, which it caches for its roughly one-hour lifetime. The installation id rides along in every webhook payload, so the bridge always knows which installation to act as. The quick-start alternative is a personal access token from a bot account — it overrides App auth and gets you running in minutes; the only cost is that the bot’s comments won’t carry the polished [bot] badge.
- Trigger: @agentis in a PR conversation comment or an inline review comment on the diff
- Context: PR title and body, the full diff (capped, 30k characters by default), and prior comment history
- Inline extras: file path, line range, diff hunk, side and commit SHA pinned to the top of the task
- Guards: created-only, no bots, mention required, delivery-id dedupe, global rate limit
- Feedback: 👀 on success, 😕 on failure — best-effort, never blocks the run
The same engine as Slack
None of the agent machinery is GitHub-specific. The task client, the guards and the text handling are the same core that powers the Agentis Slack bridge — only the edges differ. Slack’s edge is Socket Mode in and reactions out; GitHub’s is a signed webhook in and PR reactions out. Everything between a mention and a running agent is shared. That is why a new surface is a thin input adapter rather than a second product, and why a fix requested in a Slack thread and a fix requested on a line of a diff arrive at the agent looking almost identical.
Today the agent reads the review and does the work; its questions and approvals are still answered in the Agentis web app. Answering them inline — replying to the agent in the same PR thread it started from — is the next step. The plumbing already carries the reply id and the comment thread, so the conversation has somewhere to go.
See Agentis in action on your own task
Sign in, describe a task and watch an agent deliver reviewed, ready-to-ship work in minutes.
Try Agentis now