## Why It Matters

[Code-Aware AI Triage](/docs/code-aware-ai-triage) runs an AI security agent in *your* CI on every incoming report. This page walks you through connecting your fork of the example repo to Kit. The setup is a guided, Vanta-style stepper in your CSiRT settings — it doesn't mark a step done until it's verified, and the final step only turns green when a **real triage round-trip** completes.

You'll need a self-managed GitLab Runner (gitlab.com SaaS shared runners can't be host-network-isolated, which the airgap requires — see [How the airgap works](/docs/triage-agent-airgap)).

## What You Need

- A Kit account with the **VDP Add-on** enabled and an **active CSiRT program**
- A GitLab account that can fork a repo and create a **self-managed runner**
- A model endpoint your runner can reach through the egress proxy — DeepSeek by default (`https://api.deepseek.com/anthropic`), or any Anthropic-compatible endpoint
- Your GitLab project's **pipeline trigger token** (you'll create this in step 2)

## The Stepper

Navigate to **VDP > Settings > Code-Aware Triage**. The page walks five steps; each verified step locks in before the next opens.

### Step 1 — Fork the Example Repo

Fork the reference implementation:

```
git@gitlab.com:startupkit/vdp-ai-triage-example.git
```

The stepper gives you a deep link and a copy button. Fork it into a GitLab project you own and control. Before going further, run the pipeline once in `--dry-run` mode against the bundled `examples/sample-report` fixture — it should go green and produce a canned triage **with no Kit connection and no model key**. That confirms the contract works before you wire anything live.

### Step 2 — Wire the Pipeline Trigger

Kit needs to fire your pipeline when a report arrives. In your GitLab project:

1. Go to **Settings > CI/CD > Pipeline trigger tokens** and **Add new token**.
2. Copy the generated **trigger token** and your project's **trigger URL**.

Paste both into the stepper. Kit calls the GitLab pipeline trigger API on report submit:

```
POST https://gitlab.com/api/v4/projects/<project_id>/trigger/pipeline
  --form token=<trigger_token>
  --form ref=main
  --form "variables[KIT_REPORT_ID]=rpt_..."
  --form "variables[KIT_MCP_URL]=https://..."
  --form "variables[KIT_TRIAGE_TOKEN]=<scoped, short-lived>"
```

The trigger token is masked in the stepper with a reveal toggle, and stored encrypted.

> [!NOTE]
> Kit passes the report ID, your scoped MCP URL, and a short-lived triage token as **CI variables** on the trigger call. These have the highest precedence in GitLab and arrive per-run — the scoped token is never stored in your repo or your project's variable settings.

### Step 3 — Share Kit's MCP Callback

Your agent reads the report and posts the triage back through a **scoped, single-report MCP endpoint**. The stepper shows you:

- The **MCP callback URL** your agent's `mcp.json` points at.
- A **signing secret** (if you enable signed callbacks).

Copy these into your fork's `agent/mcp.json`. Each row has a copy button. The MCP token that authorizes a given run is **not** here — it arrives per-report as the `KIT_TRIAGE_TOKEN` CI variable in step 2, scoped to exactly one report and expiring in one hour.

> [!IMPORTANT]
> The scoped token grants access to **one report, for one hour.** It is not an account-wide API key. A new token is minted for every report and is single-use on the write side. This is what keeps a compromised CI job from reaching any report but the one it's triaging.

### Step 4 — Test It Now

The stepper fires a **real round-trip** using the `examples/sample-report` fixture: Kit triggers your pipeline, your agent reads the fixture report through the scoped MCP token, runs, and posts a triage back.

This step turns green **only when a real triage actually arrives back in Kit** — not when the trigger merely fires. If your pipeline errors, times out, or posts an invalid blob, the stepper anchors a failure banner on this step with links to the GitLab pipeline and a re-trigger button.

> [!TIP]
> If the test hangs in "running," check that your **self-managed runner is online** and picking up jobs, and that your egress proxy actually allows the two permitted destinations (your model endpoint and Kit's MCP host). A deny-all that's *too* aggressive blocks the MCP callback too — see [How the airgap works](/docs/triage-agent-airgap).

### Step 5 — Complete

The success state confirms the connection and links you to a recent report so you can see the panel live. From here, every new report fires your pipeline automatically.

## Where the Card Lives

Once connected, a **Code-Aware Triage** card appears on your [Integrations dashboard](/docs/connecting-ai-assistants) under Incident Response, next to Vanta and PagerDuty. It shows connected / disconnected status and the time of your last triage, and links back to this stepper.

## Quick Checklist

- [ ] VDP Add-on enabled and CSiRT program active
- [ ] Fork `vdp-ai-triage-example` and run it in `--dry-run` against the sample report (green, no Kit, no key)
- [ ] Set up a **self-managed GitLab Runner** — SaaS shared runners can't be airgapped
- [ ] Create a pipeline trigger token and paste the trigger URL + token into the stepper
- [ ] Copy Kit's MCP callback URL into your fork's `agent/mcp.json`
- [ ] Run **Test it now** and confirm it greens on a real arriving triage
- [ ] Open a recent report and confirm the Code-Aware Triage panel renders

## Next Steps

- [How the airgap works](/docs/triage-agent-airgap) — set up the egress boundary correctly before going live
- [Customizing the triage prompt and model](/docs/customizing-triage-agent) — point the agent at your model and tune the prompt
- [Code-Aware AI Triage](/docs/code-aware-ai-triage) — what the panel shows and how the loop works