GitHub PR Review Assistant with OpenClaw: From Webhook to Telegram
Too many PRs, too little time on a phone screen. This lab note walks through the loop I use: GitHub opens a PR → a tiny webhook receiver → OpenClaw summarizes the diff → Telegram gets a short, actionable digest.
XXXX.
1. Why I built this
On multi-repo weeks I miss PR noise until CI is red. I wanted:
- A push when a PR opens or updates (not every comment storm).
- A 8–15 line summary: intent, risky files, tests to run—not a novel.
- Everything self-hosted so repo tokens never sit in a random SaaS bot.
This is a triage assistant, not a replacement for human review.
2. Architecture
GitHub (pull_request event)
→ HTTPS webhook (small Node/Express or Python receiver on VPS)
→ verify signature
→ extract title, author, URL, changed files, patch summary
→ call OpenClaw agent (CLI or HTTP)
→ Telegram channel message
Components:
- GitHub fine-grained PAT or GitHub App installation with read access to PRs/contents.
- Webhook receiver (only this port is public; Gateway stays on localhost).
- OpenClaw agent
PrReviewBriefwith a strict system prompt. - Telegram bot for delivery (setup).
3. Prerequisites
- OpenClaw running on a VPS or always-on box — VPS / hub
- Telegram bot connected
- GitHub repo admin rights to add a webhook
- TLS for the webhook URL (Caddy/Nginx) — do not send webhook traffic to the Gateway directly
export GITHUB_TOKEN="XXXX"
export GITHUB_WEBHOOK_SECRET="XXXX"
export TELEGRAM_BOT_TOKEN="XXXX"
export TELEGRAM_CHAT_ID="XXXX"
4. Define the PR review agent
{
"agents": [
{
"name": "PrReviewBrief",
"description": "Summarise GitHub pull requests for Telegram triage.",
"model": "gpt-4.1-mini",
"skills": ["github_pr_read"],
"system_prompt": "You summarise pull requests for a busy developer.\nOutput:\n1) One-line intent\n2) Risk files (max 5)\n3) Missing tests / concerns (max 3)\n4) Suggested next action (approve / request changes / needs human)\nMax 180 words. No code dumps. No secrets."
}
]
}
Use a mid/cheap model for routine PRs; escalate to a stronger model only for large or security-sensitive diffs (LLM guide, cost playbook).
5. Minimal webhook receiver (Node sketch)
This is intentionally small and replaceable. Verify signatures; never trust raw JSON.
// webhook-server.js (sketch)
import express from "express";
import crypto from "crypto";
import { execFile } from "child_process";
const app = express();
app.post("/github/webhook", express.raw({ type: "*/*" }), (req, res) => {
const sig = req.headers["x-hub-signature-256"];
const digest = "sha256=" + crypto
.createHmac("sha256", process.env.GITHUB_WEBHOOK_SECRET)
.update(req.body)
.digest("hex");
if (sig !== digest) return res.status(401).end();
const event = JSON.parse(req.body.toString("utf8"));
if (event.action !== "opened" && event.action !== "synchronize") {
return res.status(204).end();
}
const pr = event.pull_request;
const payload = JSON.stringify({
title: pr.title,
number: pr.number,
url: pr.html_url,
author: pr.user.login,
body: (pr.body || "").slice(0, 2000)
});
// Official CLI: https://docs.openclaw.ai/cli/agent
execFile("openclaw", [
"agent",
"--agent", "PrReviewBrief",
"--message", `Summarise PR #${pr.number}: ${pr.title}\n${pr.html_url}\n${(pr.body || "").slice(0, 1500)}`,
"--json"
], (err, stdout) => {
if (err) console.error(err);
// parse stdout JSON and send summary text to Telegram via your helper
});
res.status(202).end();
});
app.listen(8787, "127.0.0.1");
Put Caddy/Nginx in front with HTTPS; keep Node on localhost. Firewall: only 443 public. Optionally add --deliver when the agent is already wired to Telegram.
6. GitHub webhook settings
- Repo → Settings → Webhooks → Add webhook
- Payload URL:
https://hooks.example.com/github/webhook - Content type:
application/json - Secret: same as
GITHUB_WEBHOOK_SECRET - Events: at least Pull requests
7. Example Telegram digest
PR #128 opened by alice — “Fix session expiry on mobile”
Intent: tighten token refresh when app resumes from background
Risk files: src/auth/session.ts, src/api/client.ts
Concerns: no test for resume-from-background; check logout race
Next: needs human on auth path; CI green first
https://github.com/org/repo/pull/128
8. Debugging notes from first runs
- 401 from signature checks — raw body must be used for HMAC; parsing JSON before verify breaks the digest.
- Timeouts on large diffs — truncate patch text; summarize file list first, fetch patch only for top risk files.
- Noise — ignore
labeled/editeduntil you want them; start withopened+synchronize. - Secret hygiene — webhook secret ≠ GitHub PAT; rotate if the receiver was briefly public.
Channel issues: channels troubleshooting. Gateway: gateway. Useful commands: openclaw gateway status, openclaw doctor, openclaw logs --follow.
9. Performance and cost
- Classifier gate: skip AI if the PR is docs-only (path heuristics).
- Batch: optional cron digest of open PRs instead of every push (cron).
- Token budget: mini model for triage; escalate on
security/authpaths.
10. Extensions
- Reply in Telegram with
ackto mute that PR for 24h. - Attach CI status from CI/CD integration.
- Pair with bug triage or server monitoring.
- Productize later via pricing / starter package.
Last updated: 2026-07-14 · About this site