gh CLI, and the response is posted back to the PR thread.
Reference docsFor the full webhook platform reference (all config options, delivery types, dynamic subscriptions, security model) see Webhooks.
Prerequisites
- Mibyan installed and running (
mibyan gateway) ghCLI installed and authenticated on the gateway host (gh auth login)- A publicly reachable URL for your Mibyan instance (see Local testing with ngrok if running locally)
- Admin access to the GitHub repository (required to manage webhooks)
Step 1 — Enable the webhook platform
Add the following to your~/.mibyan/config.yaml:
The payload does not contain codeThe GitHub webhook payload includes PR metadata (title, description, branch names, URLs) but not the diff. The prompt above instructs the agent to run
gh pr diff to fetch the actual changes. The default mibyan-webhook toolset is deliberately constrained (web search/extract, vision, clarify — no terminal) because webhook payloads can carry untrusted content. To let this route run gh, add a per-route toolset grant: toolsets: ["terminal", "web"] on the route config — see Per-route toolsets.Step 2 — Start the gateway
Step 3 — Register the webhook on GitHub
- Go to your repository → Settings → Webhooks → Add webhook
- Fill in:
- Payload URL:
https://your-public-url.example.com/webhooks/github-pr-review - Content type:
application/json - Secret: the same value you set for
secretin the route config - Which events? → Select individual events → check Pull requests
- Payload URL:
- Click Add webhook
ping event to confirm the connection. It is safely ignored — ping is not in your events list — and returns {"status": "ignored", "event": "ping"}. It is only logged at DEBUG level, so it won’t appear in the console at the default log level.
Step 4 — Open a test PR
Create a branch, push a change, and open a PR. Within 30–90 seconds (depending on PR size and model), Mibyan should post a review comment. To follow the agent’s progress in real time:Local testing with ngrok
If Mibyan is running on your laptop, use ngrok to expose it:https://...ngrok-free.app URL and use it as your GitHub Payload URL. On the free ngrok tier the URL changes each time ngrok restarts — update your GitHub webhook each session. Paid ngrok accounts get a static domain.
You can smoke-test a static route directly with curl — no GitHub account or real PR needed.
mibyan webhook test <name> only works for dynamic subscriptions created with mibyan webhook subscribe. It does not read routes from config.yaml.Filtering to specific actions
GitHub sendspull_request events for many actions: opened, synchronize, reopened, closed, labeled, etc. The events list filters by the X-GitHub-Event header value, and route-level filters can narrow by payload fields such as action.
The prompt in Step 1 already handles this by instructing the agent to stop early for closed and labeled events.
There is no Jinja2 or conditional template syntax.{field}and{nested.field}are the only substitutions supported. Anything else is passed verbatim to the agent.
Using a skill for consistent review style
Load a Mibyan skill to give the agent a consistent review persona. Addskills to your route inside platforms.webhook.extra.routes in config.yaml:
Note: Only the first skill in the list that is found is loaded. Mibyan does not stack multiple skills — subsequent entries are ignored.
Sending responses to Slack or Discord instead
Replace thedeliver and deliver_extra fields inside your route with your target platform:
chat_id is omitted, the response is sent to that platform’s configured home channel.
Valid deliver values: log · github_comment · telegram · discord · slack · signal · sms
GitLab support
The same adapter works with GitLab. GitLab usesX-Gitlab-Token for authentication (plain string match, not HMAC) — Mibyan handles both automatically.
For event filtering, GitLab sets X-GitLab-Event to values like Merge Request Hook, Push Hook, Pipeline Hook. Use the exact header value in events:
{object_attributes.title} for the MR title and {object_attributes.iid} for the MR number. The easiest way to discover the full payload structure is GitLab’s Test button in your webhook settings, combined with the Recent Deliveries log. Alternatively, omit prompt from your route config — Mibyan will then pass the full payload as formatted JSON directly to the agent, and the agent’s response (visible in the gateway log with deliver: log) will describe its structure.
Security notes
- Never use
INSECURE_NO_AUTHin production — it disables signature validation entirely. It is only for local development. - Rotate your webhook secret periodically and update it in both GitHub (webhook settings) and your
config.yaml. - Rate limiting is 30 req/min per route by default (configurable via
extra.rate_limit). Exceeding it returns429. - Duplicate deliveries (webhook retries) are deduplicated via a 1-hour idempotency cache. The cache key is
X-GitHub-Deliveryif present, thenX-Request-ID, then a random per-request ID. When neither delivery ID header is set, retries are not deduplicated. - Prompt injection: PR titles, descriptions, and commit messages are attacker-controlled. Malicious PRs could attempt to manipulate the agent’s actions. Run the gateway in a sandboxed environment (Docker, VM) when exposed to the public internet.
Troubleshooting
GitHub’s Recent Deliveries tab (repo → Settings → Webhooks → your webhook) shows the exact request headers, payload, HTTP status, and response body for every delivery. It is the fastest way to diagnose failures without touching your server logs.
Full config reference
What’s Next?
- Cron-Based PR Reviews — poll for PRs on a schedule, no public endpoint needed
- Webhook Reference — full config reference for the webhook platform
- Build a Plugin — package review logic into a shareable plugin
- Profiles — run a dedicated reviewer profile with its own memory and config

