The bot needs two things: a token with the api scope (to read the diff and write comments and statuses) and a webhook in the project that calls the bot on merge request and comment events.
1. The bot token
It is best to create a separate bot user and issue a project access token (or a personal access token) with the api scope. The value goes into GITLAB_TOKEN.
token permissionsDeveloper role or above, so that the bot can leave discussion comments. A commit status is only needed if you turned the severity gate on (it is off by default); if the token cannot set a status, the review is still published — the bot does not fall over. You create the webhook below by hand, so Developer is enough; creating it through the API requires Maintainer, and Developer gets a 403.
2. The project webhook
In the project: Settings → Webhooks → Add new webhook.
URL — the bot address with the webhook path:
webhook URL
https://адрес-бота/api/webhooks/gitlab
Secret token — the same value as GITLAB_WEBHOOK_SECRET. The bot compares it in constant time.
Trigger — tick Merge request events and Comments (note events are needed for reply mode; until it is enabled in the config the bot simply ignores comment events). If the webhook already existed, turn Comments on in Settings → Webhooks → Edit; diagnose.sh --project checks this for you.
Press Test → Merge request events. The expected answer is 202: the bot has queued the job.
self-hosted networkingIf the bot sits on an internal network, let GitLab reach it: Admin → Settings → Network → Outbound requests → «Allow requests to the local network from webhooks».
Which events are reviewed
event
behaviour
open / reopen
a review starts
update (new commits)
a review starts on the new head
update (label or description only)
ignored — no wasted runs
a comment in the merge request (note)
with reply mode on, the bot answers in the thread; otherwise ignored
deduplicationA queued job is keyed as project:mr:headSha (a reply is keyed by the comment id), so repeated webhook deliveries from GitLab never produce duplicates.
What the team sees
inline discussion comments anchored to diff positions;
a summary comment grouped by severity;
with reply mode on, the bot's answers to replies in the threads of its own comments (the summary tells the team they may reply);
a commit status (success/failed) — only if the severity gate is on (off by default); it then blocks the merge when «pipeline must succeed» is required.