> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ankra.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# AI Code Review

> How Ankra's AI reviews pull requests - connecting GitHub, GitLab, or Bitbucket, what every switch in Source control & AI review does, and what the review posts.

Connect a source-control provider and Ankra's AI reviews your pull requests: it reads the diff, posts a verdict with its findings, pins each finding to the line it is about, and answers when somebody mentions it in a comment.

Everything is configured in one place: **AI** → **Settings** → **Connections** → **Source control & AI review**.

> [!NOTE]
>
> **Nothing runs until you switch it on.** Every capability on a new connection is off. Installing the GitHub App, connecting a GitLab token, or authorising a Bitbucket workspace gives Ankra access, and nothing more: no review is posted, no mention is answered, and no preview is deployed until an organisation admin turns the switch on for that connection or for a single repository.

***

## Connect a provider

Each provider appears as its own card. Connecting one is an organisation **admin** action.

**GitHub**

Press **Install GitHub App** and pick the organisation or user account, then the repositories Ankra may see. You land back on this page with the installation listed.

One account can carry several installations, and each is configured separately. See the [GitHub integration](https://docs.ankra.ai/integrations/github.md) for the permissions the App requests and how to change which repositories it covers.

GitHub is the only provider that also offers [PR preview environments](https://docs.ankra.ai/guides/pr-preview-environments.md).

**GitLab**

Paste an access token, optionally naming a self-managed instance URL. Ankra validates it, then shows the webhook URL and secret to register in GitLab by hand.

The form asks for `read_api` and `read_repository`, which is what Ankra validates against and enough to *read* your merge requests. Posting the review is a write, so use a token with the `api` scope unless you deliberately want a read-only connection.

Webhook registration is manual for GitLab and the secret is shown once. The [GitLab integration](https://docs.ankra.ai/integrations/gitlab.md) walks through both.

**Bitbucket Cloud**

Press **Connect workspace** and authorise the Ankra OAuth consumer against your Bitbucket Cloud workspace. Webhooks are registered for you: switching AI review or mention replies on registers one on every repository it covers - every repository the credential can see, for the **All repositories** row - and a repository found later gets its own within minutes. Switching a lane off leaves the webhook in place.

The webhooks carry pull request events only when the credential grants Bitbucket's `pullrequest` scope. A credential connected before Ankra asked for it has to be reconnected; until then GitOps sync works and reviews and mentions receive nothing. See the [Bitbucket Cloud integration](https://docs.ankra.ai/integrations/bitbucket-cloud.md#granting-the-pull-request-permission) for the OAuth scopes, their purpose, and reconnecting.

A connected card shows one row per installation, credential, or workspace. Its one-line summary says which lanes the default row runs and how many repositories deviate from it, so a connection reading **Nothing enabled** is doing exactly that. Rows that do nothing open collapsed; press the row to expand it.

***

## AI mode: Ask or Agent

Every connection carries an **AI mode** that bounds what the AI may do when it is talked to from that repository. It is separate from the capability switches: the switches decide *whether* the AI answers, the mode decides *how far* the answer may go.

| Mode | What the AI may do |
| - | - |
| **Ask** (default) | Read-only. It investigates, explains, and can spin up throwaway workspaces or PR demos, but never changes existing infrastructure and never opens a pull request. |
| **Agent** | It may act. It opens fix pull requests on its own, and the pull request is the review gate. Other destructive changes still ask for confirmation. |

A connection in Agent mode is marked **Can act**. Automatic review events themselves stay read-only whatever the mode: a review comments, and a proposed fix arrives as a separate pull request you review like any other.

On GitLab and Bitbucket Cloud, Ankra cannot open a pull request, so an Agent-mode reply proposes the fix with a branch name and a commit message instead of offering one.

***

## The repository table

Each connection expands into one table of every capability, with two kinds of row.

* **All repositories** is the default row. It carries the connection-wide values, and every repository with no rule of its own follows it.
* **A repository rule** is one row per repository that should differ. Pick the repository (or type `<owner>/<repository>`) and press **Add rule**; the new row starts as a copy of the default row. Removing the rule reverts that repository to the default row.

Every control saves the moment you change it. There is no separate save button on this table.

To manage rules from the terminal or a script instead, an organisation admin can use the CLI:

```bash theme={null}
ankra org ai-review repos list
ankra org ai-review repos set my-org/my-repo --review --mentions --max-reviews-per-pr 3
ankra org ai-review repos unset my-org/my-repo
```

`set` changes only the switches you pass (`--review`, `--mentions`, `--previews`, `--model`, `--review-drafts`, `--max-reviews-per-pr`; turn one off with `=false`) and keeps the rest of the repository's rule, or the default row's values when the repository has no rule yet. The connection is found from the repository; when that is ambiguous, pass `--binding <provider>/<id>` as `list` shows it. `list --reachable` also lists the repositories each GitHub App installation can see, and `unset` removes the rule so the repository follows the default row again. Listing needs organisation membership; `set` and `unset` need an organisation admin.

Over the API, an organisation admin's [API token](https://docs.ankra.ai/reference/tokens.md) can send `PUT /api/v1/org/ai-gateway/scm-bindings/{provider}/{binding_external_id}/repo-overrides` with `repo_full_name`, `ai_review`, `mention_replies` and `pr_previews` to add or change a rule, and `DELETE` on the same path with `?repo_full_name=<owner>/<repository>` to remove it. `GET /api/v1/org/ai-gateway/scm-bindings` lists each connection's `binding_external_id` and its current rules; the [API Reference](https://docs.ankra.ai/api-reference/introduction.md) has the full request shape.

> [!NOTE]
>
> Rules are keyed by the repository path, lowercased. For GitLab, use the full project path including subgroups, up to 20 levels deep - for example `my-group/my-subgroup/my-project`.

### What each column means

| Column | What it does | Default |
| - | - | - |
| **AI review** | Reviews every pull or merge request when it is opened and on every push to it, and posts the findings. | Off |
| **Review drafts** | Also reviews draft pull requests automatically. When off, a draft is skipped until it is marked ready. | Off |
| **Auto reviews / PR** | Caps how many reviews one pull request receives over its whole life, requested ones included. Blank or `0` means no cap. See [The two budgets](#the-two-budgets). | 5 |
| **Mention replies** | Lets the AI answer when somebody writes `@ankraai` in a pull request comment. | Off |
| **PR previews** | Deploys every pull request to a throwaway [preview environment](https://docs.ankra.ai/guides/pr-preview-environments.md) with its own URL. GitHub only. | Off |
| **Review model** | Which model the review runs on: an entry from your organisation's [model catalogue](https://docs.ankra.ai/platform/ai-provider.md), or any exact OpenRouter model from the searchable list. A repository row set to **Inherit** follows the default row. | Your organisation's **AI code review** model |

When nothing picks a review model - not the repository's [Application AI settings](https://docs.ankra.ai/platform/application-ai.md), not a repository rule, not the default row - the review runs on your organisation's **AI code review** function under [Models per function](https://docs.ankra.ai/platform/ai-provider.md#models-per-function). Unless an admin changes it, that follows the **Think** tier: GLM 5.3 on the Ankra provider, or your own Think model when the organisation runs on its own key. Every pull request gets that model, whatever the size of its diff.

> [!TIP]
>
> The cap and the draft switch gate *automatic* reviews only. Asking for a review in a comment always runs one, though it still counts toward the cap - see [Talking to the review](#talking-to-the-review) below.

***

## Review instructions

**Customise review instructions**, at the top of the section, opens your organisation's own review prompt, with one field per connected installation. It is what the reviewer should keep in mind on this installation: which areas to weigh heavily, which conventions to enforce, what language to write in.

```text theme={null}
Write review comments in Swedish.
Pay extra attention to Terraform and RBAC changes.
Our Helm values must never hardcode an image tag.
```

* Up to 4,000 characters per installation. The counter turns red past the cap and **Save** stays disabled until you shorten it.
* The instructions steer what the review focuses on and how it is phrased. They cannot override the platform guardrails or the review format.
* Every repository on the installation inherits them. An application that overrode its own **Pull request** settings under [Application AI settings](https://docs.ankra.ai/platform/application-ai.md) keeps the instructions set there instead, because overriding a lane pins the whole lane.
* Only organisation admins can change them.

***

## What a review posts

One comment per pull request, updated in place on every re-review, never a stream of new ones. Where a pipeline, a preview, or a promotion is also running, they share that comment as separate sections.

The review section is laid out like this:

```markdown theme={null}
## Ankra AI review

**Verdict: comments.**

<two to four sentences on the change as a whole>

### Findings

- **[high] <short title>** (`path/to/file.go:42`)
  <what is wrong, why it matters, and what to do instead>

---
_Reviewed commit abc1234. This review is read-only and advisory._
```

| Verdict | What it means |
| - | - |
| **looks good** | The change looks safe. |
| **no findings** | The review ran and surfaced nothing. |
| **comments** | Worth reading, but nothing the reviewer calls a probable defect. |
| **changes requested** | A probable bug or a security issue. |
| **unavailable** | The model's answer could not be read. Push again or mention Ankra to re-run it. |

Findings carry a severity of **high**, **medium**, or **low**, and a review keeps to the issues that matter - at most eight. A finding that names a line is also posted as a comment pinned to that line, so it is read where the decision is made. Each inline comment carries an invisible fingerprint of its file and title, so re-reviewing a pull request never restates a finding it has already pinned, even if the line has drifted or the wording changed.

### How the review reads a change

* **Machine-written files are dropped before the diff is measured.** Lockfiles, minified bundles, source maps, and generated protobuf never reach the model. Beyond keeping the cost down, this is what stops a large lockfile from crowding the real change out of the review. Set **Ignore paths** per repository under [Application AI settings](https://docs.ankra.ai/platform/application-ai.md) to drop more.
* **Uncertain findings are settled, not guessed.** When a finding rests on something the diff does not show, Ankra reads the file and either restates the finding as a definite defect or drops it. Where that check cannot run, the finding is posted with its uncertainty visible.
* **A truncated answer says so.** If the model runs out of output budget mid-answer, what arrived is posted under an explicit incomplete-review notice rather than as a finished review that found nothing.
* **The diff is treated as text, never as instructions.** An instruction planted in a diff or a pull request description asking the reviewer to act, change role, or reveal data is refused.

***

## What the review reads beyond the diff

Before it answers, the review also reads the code a change can break outside its diff: other callers of what changed in the same repository, files in related repositories that still use a name the change removes, and the companion pull request that carries the other half of a cross-repository change. A `Depends-on:` line in the description declares which pull request has to merge first.

How each of those works, how to relate two repositories, and what an empty result does and does not mean are covered in [Cross-repository review](https://docs.ankra.ai/platform/ai-code-review-cross-repo.md).

***

## Talking to the review

Mention `@ankraai` in a pull request or merge request comment and the AI answers in the thread, with the change as context. This needs **Mention replies** on for that repository.

* **Ask a question.** "@ankraai does this handle the empty case?" gets an answer grounded in the diff, and a plain statement when the diff does not contain the answer.
* **Ask under an inline comment** and the question is read as being about that line.
* **Ask for a review.** A mention is a direct request from a human, so it is never filtered by draft state, branch scope, or either review budget. It runs even on a draft and even past the **Auto reviews / PR** cap, and it is counted against both budgets.

On GitHub and GitLab, Ankra reacts to your comment with 👀 as soon as it picks the mention up, so you can tell a slow review from one that never started. Bitbucket Cloud has no comment reactions, so there the reply itself is the first sign; it is posted as a reply to your comment.

> [!NOTE]
>
> Only `@ankraai` summons the review. It is matched as a whole word, so `@ankraai-bot` and an address like `someone@ankraai.example.com` are ignored.

***

## When a review does not run

A skipped review is normal and costs nothing. Ankra decides before any model call, in the order below, and stops at the first reason that applies. On GitHub the reason is written to the **Ankra AI review** check run on that commit: its title reads **Review skipped** followed by the reason, and its summary says what lifts it. The check run is the one place the decision is recorded.

| Check-run title | Why | What to change |
| - | - | - |
| **Review skipped - AI review is switched off for this repository** | **AI review** is off on the default row and on any rule covering the repository. | Turn the switch on, on the default row or on that repository's rule. |
| **Review skipped - draft pull request** | The pull request is a draft and **Review drafts** is off. | Turn **Review drafts** on, mark the pull request ready, or mention `@ankraai`. |
| **Review skipped - target branch out of scope** | The pull-request lane's branch patterns exclude the target branch. | Widen **Target branches** under [Application AI settings](https://docs.ankra.ai/platform/application-ai.md), or mention `@ankraai`. |
| **Review skipped - head already reviewed** | A review of exactly this commit is already on the pull request. | Push a new commit. Nothing was lost. |
| **Review skipped - superseded by a newer push** | A later push replaced this commit before its review started. | Nothing. The newest head gets the review. |
| **Review skipped - daily review budget reached** | The repository has used its **Max runs per day** since midnight UTC, across every pull request. | Raise or clear **Max runs per day** under [Application AI settings](https://docs.ankra.ai/platform/application-ai.md), or mention `@ankraai`. |
| **Review skipped - per-pull-request review budget reached** | This pull request has used its **Auto reviews / PR** allowance over its lifetime. | Raise or clear **Auto reviews / PR** on the repository rules, or mention `@ankraai`. |

A skipped head is not retried. Nothing on Ankra's side re-queues a commit it declined; the next push is a new head, judged afresh against the same switches and counts. So once a pull request is over its budget, every later push to it is skipped until the budget changes.

### The two budgets

Two counters can decline a review, and they are set in different places.

| | **Auto reviews / PR** | **Max runs per day** |
| - | - | - |
| Counts | Reviews of one pull request over its whole life, keyed by the pull request number. A re-cut pull request starts at zero. | Reviews of the whole repository since midnight UTC, across every pull request. A brand-new pull request can be declined on its first push. |
| Default | 5 | No cap |
| No cap | Blank or `0` | Blank or `0` |
| Where | The repository rules on this page, per repository or on the default row. Organisation admins only. | The **Pull request review** card under [Application AI settings](https://docs.ankra.ai/platform/application-ai.md). |
| Applies | From the next push. | From the next push. |

The daily budget is checked first, so a repository over both reads **daily review budget reached** on its check run. Both counters include reviews somebody asked for with `@ankraai`: a requested review runs past either budget, and it is still counted against both.

A completed review of a commit replaces any earlier **Review skipped** on that commit's check run, so a review requested with `@ankraai` clears a check that a budget had concluded.

***

## Per-application overrides

The table on this page sets your organisation's defaults. An [application](https://docs.ankra.ai/concepts/applications.md) connected to a repository can override them on its own **Ankra AI** panel, which also exposes branch patterns, ignore paths, daily budgets, input-character budgets, and the deeper lanes. Both surfaces read the same stored settings, so they never disagree. See [Application AI settings](https://docs.ankra.ai/platform/application-ai.md).

***

## Cost

A review is a model completion, billed to your organisation like any other AI usage. Four things keep it bounded, and all four are yours to set:

1. **Every lane is off until you turn it on**, per connection or per repository.
2. **Auto reviews / PR** caps the reviews one pull request can accumulate.
3. **Review model** picks what a review costs. The picker shows each model's context window and price. With nothing picked, the organisation's **AI code review** model applies.
4. **Ignore paths** and the input-character budget bound how much of a diff one review reads.

Reviews already spent appear in your AI usage - see [Models and Cost](https://docs.ankra.ai/platform/ai-provider.md#usage-and-the-free-allowance).

***

## Permissions

Connecting a provider, disconnecting one, changing any switch, and editing the review instructions all require organisation **admin**. Members see the connections and their current settings, and the controls are disabled with the reason.

***

## Troubleshooting

| Symptom | What to check |
| - | - |
| No review appears on a new pull request | Is **AI review** on for that repository - the default row *and* any rule covering it? A rule wins over the default row. Then read the **Ankra AI review** check run on the commit: its title names the [skip reason](#when-a-review-does-not-run). |
| The connection card says **Nothing enabled** | Every lane is off on the default row and on every rule. Nothing will run for this installation until one is switched on. |
| A repository is missing from the add-rule picker | The picker lists what the installation can actually see. For GitHub, add the repository to the App installation; for other providers, type the path by hand. |
| Reviews run but mentions go unanswered | **Mention replies** is a separate switch from **AI review**, and mentions must spell `@ankraai`. |
| The review says **Verdict: unavailable** | The model's answer could not be read. Push a new commit or mention `@ankraai` to re-run it. A recurring one usually means the selected review model's output budget is too small; pick a larger model. |
| The review says it is incomplete | Same cause, caught mid-answer: the model stopped at its output ceiling. Re-run it, and consider a model with a larger output budget. |
| Findings repeat on every push | They should not: inline findings are fingerprinted and deduped. The summary comment does restate every finding in full by design, so a reader who only opens the conversation tab still sees the whole review. |
| GitLab reviews stop after a secret rotation | Regenerating the webhook secret invalidates the old one immediately. Update the hook in GitLab with the new secret. |
| Bitbucket pushes sync, but no review or mention reply ever runs | The credential does not grant Bitbucket's `pullrequest` scope, so its webhooks carry pushes only. Reconnect it - see [Granting the pull request permission](https://docs.ankra.ai/integrations/bitbucket-cloud.md#granting-the-pull-request-permission). |

***

## Related

* [AI Connections](https://docs.ankra.ai/platform/ai-connections.md) - every integration the AI communicates through
* [Cross-repository review](https://docs.ankra.ai/platform/ai-code-review-cross-repo.md) - what the review reads outside the diff, related repositories, and merge order
* [Application AI settings](https://docs.ankra.ai/platform/application-ai.md) - per-repository lanes, branch scope, ignore paths, and budgets
* [PR preview environments](https://docs.ankra.ai/guides/pr-preview-environments.md) - what the **PR previews** switch deploys
* [GitHub](https://docs.ankra.ai/integrations/github.md), [GitLab](https://docs.ankra.ai/integrations/gitlab.md), [Bitbucket Cloud](https://docs.ankra.ai/integrations/bitbucket-cloud.md) - connecting each provider
* [AI Skills](https://docs.ankra.ai/platform/ai-skills.md) - the conventions the org skills review checks a change against
* [`ankra application pull-request-reviews`](https://docs.ankra.ai/reference/cli/application) - read posted reviews from the CLI


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.