Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,11 @@ dist

# End of https://www.toptal.com/developers/gitignore/api/yarn,node

.claude
.sourcebot
/bin
/config.json
.DS_Store
oss-licenses.json
oss-license-summary.json
license-audit-result.json
license-audit-result.json
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added
- Added `thinkingLevel` and `thinkingBudget` configuration options for Google Generative AI and Google Vertex providers. [#1110](https://github.com/sourcebot-dev/sourcebot/pull/1110)
- Support Gitlab MRs in the AI Code Review Agent [#1104](https://github.com/sourcebot-dev/sourcebot/pull/1104)

### Changed
- Deprecated `GOOGLE_VERTEX_THINKING_BUDGET_TOKENS` environment variable in favor of per-model `thinkingBudget` config. [#1110](https://github.com/sourcebot-dev/sourcebot/pull/1110)
Expand Down
151 changes: 101 additions & 50 deletions docs/docs/features/agents/review-agent.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,64 +3,55 @@ title: AI Code Review Agent
sidebarTitle: AI code review agent
---

<Note>
This agent sends data to OpenAI (through an API key you supply) to perform code reviews. This data includes code from the PR being reviewed, as well as additional relevant context from your
codebase that the agent may fetch to perform the review.
</Note>
This agent provides codebase-aware reviews for your GitHub PRs and GitLab MRs. For each diff, the agent fetches relevant context from your indexed codebase and feeds it into a configured language model for a detailed review.

This agent provides codebase-aware reviews for your PRs. For each diff, this agent fetches relevant context from Sourcebot and feeds it into an LLM for a detailed review of your changes.

The AI Code Review Agent is [fair source](https://github.com/sourcebot-dev/sourcebot/tree/main/packages/web/src/features/agents/review-agent) and packaged in [Sourcebot](https://github.com/sourcebot-dev/sourcebot). To get started using this agent, [deploy Sourcebot](/docs/deployment/docker-compose)
and then follow the configuration instructions below.
The AI Code Review Agent is [fair source](https://github.com/sourcebot-dev/sourcebot/tree/main/packages/web/src/features/agents/review-agent) and packaged in [Sourcebot](https://github.com/sourcebot-dev/sourcebot). To get started, [deploy Sourcebot](/docs/deployment/docker-compose) and follow the configuration instructions below.

![AI Code Review Agent Example](/images/review_agent_example.png)

# Configure
# Language model

The review agent uses whichever language model you have configured in your `config.json`. All providers supported by Sourcebot (OpenAI, Anthropic, AWS Bedrock, Azure OpenAI, and others) work out of the box.

This agent currently only supports reviewing GitHub PRs. You configure the agent by creating a GitHub app, installing it into your GitHub organization, and then giving your app info to Sourcebot.
If you have multiple models configured, set `REVIEW_AGENT_MODEL` to the `displayName` of the model you want the agent to use. If this variable is unset, the agent uses the first configured model.

Before you get started, make sure you have an OpenAPI account that you can create an OpenAPI key with.
# GitHub

<Steps>
<Step title="Register a GitHub app">
Follow the official GitHub guide for [registering a GitHub app](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app)

- GitHub App name: You can make this whatever you want (ex. Sourcebot Review Agent)
- Homepage URL: You can make this whatever you want (ex. https://www.sourcebot.dev/)
- Webhook URL (**IMPORTANT**): You must set this to point to your Sourcebot deployment at /api/webhook (ex. https://sourcebot.aperture.com/api/webhook). Your Sourcebot deployment must be able to accept requests from GitHub
(either github.com or your self-hosted enterprise server) for this to work. If you're running Sourcebot locally, you can [use smee](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#step-2-get-a-webhook-proxy-url) to [forward webhooks](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#step-6-start-your-server) to your local deployment.
- Webook Secret: This can be any string (ex. generate a random string `python -c "import secrets; print(secrets.token_hex(10))"`). You'll provide this to Sourcebot to be able to read webhook events from your app.
- Permissions
Follow the official GitHub guide for [registering a GitHub app](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app).

- **GitHub App name**: Any name you choose (e.g. Sourcebot Review Agent)
- **Homepage URL**: Any URL you choose (e.g. `https://www.sourcebot.dev/`)
- **Webhook URL** (required): Your Sourcebot deployment URL at `/api/webhook` (e.g. `https://sourcebot.example.com/api/webhook`). Your deployment must be reachable from GitHub. If you are running Sourcebot locally, use [smee](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#step-2-get-a-webhook-proxy-url) to [forward webhooks](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#step-6-start-your-server) to your local deployment.
- **Webhook Secret**: Any string (e.g. generate one with `python -c "import secrets; print(secrets.token_hex(10))"`)
- **Permissions**
- Pull requests: Read & Write
- Issues: Read & Write
- Contents: Read
- Events:
- **Events**
- Pull request
- Issue comment
</Step>
<Step title="Install the GitHub app in your organization">
Navigate to your new [GitHub app's page](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#navigate-to-your-app-settings) and press `Install`
Navigate to your new [GitHub app's page](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#navigate-to-your-app-settings) and press **Install**.
</Step>
<Step title="Configure the environment variables in Sourcebot">
Sourcebot requires the following environment variables to begin reviewing PRs through your new GitHub app:

- `GITHUB_REVIEW_AGENT_APP_ID`: The client ID of your GitHub app. Can be found in your [app settings](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#navigate-to-your-app-settings)
- `GITHUB_REVIEW_AGENT_APP_WEBHOOK_SECRET`: The webhook secret you defined in your GitHub app. Can be found in your [app settings](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#navigate-to-your-app-settings)
- `GITHUB_REVIEW_AGENT_APP_PRIVATE_KEY_PATH`: The path to your app's private key. If you're running Sourcebot from a container, this is the path to this file from within your container
(ex `/data/review-agent-key.pem`). You must copy the private key file into the directory you mount to Sourcebot (similar to the config file).

You can generate a private key file for your app in the [app settings](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#navigate-to-your-app-settings). You must copy this private key file into the
directory that you mount to Sourcebot
![GitHub App Private Key](/images/github_app_private_key.png)
- `OPENAI_API_KEY`: Your OpenAI API key
- `REVIEW_AGENT_API_KEY`: The Sourcebot API key that the review agent uses to hit the Sourcebot API to fetch code context
- `REVIEW_AGENT_AUTO_REVIEW_ENABLED` (default: `false`): If enabled, the review agent will automatically review any new or updated PR. If disabled, you must invoke it using the command defined by `REVIEW_AGENT_REVIEW_COMMAND`
- `REVIEW_AGENT_REVIEW_COMMAND` (default: `review`): The command that invokes the review agent (ex. `/review`) when a user comments on the PR. Don't include the slash character in this value.

You can find an example docker compose file below.
- This docker compose file is placed in `~/sourcebot_review_agent_workspace`, and I'm mounting that directory to Sourcebot
- The config and the app private key files are placed in this directory
- The paths to these files are given to Sourcebot relative to `/data` since that's the directory in Sourcebot that I'm mounting to
<Step title="Configure environment variables">
Set the following environment variables in your Sourcebot deployment:

| Variable | Description |
|---|---|
| `GITHUB_REVIEW_AGENT_APP_ID` | The client ID of your GitHub app, found in your [app settings](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#navigate-to-your-app-settings) |
| `GITHUB_REVIEW_AGENT_APP_WEBHOOK_SECRET` | The webhook secret you set when registering the app |
| `GITHUB_REVIEW_AGENT_APP_PRIVATE_KEY_PATH` | Path to your app's private key file inside the container (e.g. `/data/review-agent-key.pem`). Copy the key file into the directory you mount to Sourcebot. |

You can generate a private key in your [app settings](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#navigate-to-your-app-settings).

<Frame>
<img src="/images/github_app_private_key.png" alt="GitHub App Private Key" />
</Frame>

Example `docker-compose.yml`:

```yaml
services:
Expand All @@ -71,26 +62,86 @@ Before you get started, make sure you have an OpenAPI account that you can creat
ports:
- "3000:3000"
volumes:
- "/Users/michael/sourcebot_review_agent_workspace:/data"
- "/home/user/sourcebot_workspace:/data"
environment:
CONFIG_PATH: "/data/config.json"
GITHUB_REVIEW_AGENT_APP_ID: "my-github-app-id"
GITHUB_REVIEW_AGENT_APP_WEBHOOK_SECRET: "my-github-app-webhook-secret"
GITHUB_REVIEW_AGENT_APP_WEBHOOK_SECRET: "my-webhook-secret"
GITHUB_REVIEW_AGENT_APP_PRIVATE_KEY_PATH: "/data/review-agent-key.pem"
REVIEW_AGENT_API_KEY: "sourcebot-my-key"
OPENAI_API_KEY: "sk-proj-my-open-api-key"
```
</Step>
<Step title="Verify configuration">
Navigate to the agents page by pressing `Agents` in the Sourcebot nav menu. If you've configured your environment variables correctly you'll see the following:
Navigate to **Agents** in the Sourcebot nav menu. If your environment variables are set correctly, the GitHub Review Agent card shows a confirmation that the agent is configured and accepting requests.

![Review Agent Configured](/images/review_agent_configured.png)
<Frame>
<img src="/images/review_agent_configured.png" alt="Review Agent Configured" />
</Frame>
</Step>
</Steps>

# GitLab

<Steps>
<Step title="Create a GitLab access token">
Create a [personal access token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html) or [project access token](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html) with the following scope:

- `api`

Keep a note of the token value — you will need it in the next step.
</Step>
<Step title="Configure a webhook in GitLab">
In your GitLab project, go to **Settings → Webhooks** and add a new webhook:

- **URL**: Your Sourcebot deployment URL at `/api/webhook` (e.g. `https://sourcebot.example.com/api/webhook`)
- **Secret token**: Any string (e.g. generate one with `python -c "import secrets; print(secrets.token_hex(10))"`)
- **Trigger events**: Merge request events, Comments

Save the webhook.
</Step>
<Step title="Configure environment variables">
Set the following environment variables in your Sourcebot deployment:

| Variable | Description |
|---|---|
| `GITLAB_REVIEW_AGENT_WEBHOOK_SECRET` | The secret token you set on the GitLab webhook |
| `GITLAB_REVIEW_AGENT_TOKEN` | The GitLab personal or project access token |
| `GITLAB_REVIEW_AGENT_HOST` | Your GitLab hostname. Defaults to `gitlab.com`. Set this for self-hosted GitLab instances (e.g. `gitlab.example.com`). |

Example `docker-compose.yml`:

```yaml
services:
sourcebot:
image: ghcr.io/sourcebot-dev/sourcebot:latest
pull_policy: always
container_name: sourcebot
ports:
- "3000:3000"
volumes:
- "/home/user/sourcebot_workspace:/data"
environment:
CONFIG_PATH: "/data/config.json"
GITLAB_REVIEW_AGENT_WEBHOOK_SECRET: "my-webhook-secret"
GITLAB_REVIEW_AGENT_TOKEN: "glpat-my-token"
GITLAB_REVIEW_AGENT_HOST: "gitlab.example.com"
```
</Step>
<Step title="Verify configuration">
Navigate to **Agents** in the Sourcebot nav menu. If your environment variables are set correctly, the GitLab Review Agent card shows a confirmation that the agent is configured and accepting requests.
</Step>
</Steps>

# Using the agent

The review agent will not automatically review your PRs by default. To enable this feature, set the `REVIEW_AGENT_AUTO_REVIEW_ENABLED` environment variable to true.
By default, the agent does not review PRs and MRs automatically. To enable automatic reviews on every new or updated PR/MR, set `REVIEW_AGENT_AUTO_REVIEW_ENABLED` to `true`.

You can also trigger a review manually by commenting `/review` on any PR or MR. To use a different command, set `REVIEW_AGENT_REVIEW_COMMAND` to your preferred value (without the leading slash).

# Environment variable reference

You can invoke the review agent manually by commenting `/review` on the PR you'd like it to review. You can configure the command that triggers the agent by changing
the `REVIEW_AGENT_REVIEW_COMMAND` environment variable.
| Variable | Default | Description |
|---|---|---|
| `REVIEW_AGENT_AUTO_REVIEW_ENABLED` | `false` | Automatically review new and updated PRs/MRs |
| `REVIEW_AGENT_REVIEW_COMMAND` | `review` | Comment command that triggers a manual review (without the `/`) |
| `REVIEW_AGENT_MODEL` | first configured model | `displayName` of the language model to use for reviews |
| `REVIEW_AGENT_LOGGING_ENABLED` | unset | Write prompt and response logs to disk for debugging |
5 changes: 5 additions & 0 deletions packages/shared/src/env.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ const options = {
GITHUB_REVIEW_AGENT_APP_ID: z.string().optional(),
GITHUB_REVIEW_AGENT_APP_WEBHOOK_SECRET: z.string().optional(),
GITHUB_REVIEW_AGENT_APP_PRIVATE_KEY_PATH: z.string().optional(),
// GitLab for review agent
GITLAB_REVIEW_AGENT_WEBHOOK_SECRET: z.string().optional(),
GITLAB_REVIEW_AGENT_TOKEN: z.string().optional(),
GITLAB_REVIEW_AGENT_HOST: z.string().default('gitlab.com'),
REVIEW_AGENT_MODEL: z.string().optional(),
Comment on lines +198 to +202
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Validate/normalize GITLAB_REVIEW_AGENT_HOST as a hostname.

GITLAB_REVIEW_AGENT_HOST is currently any string. Since the GitLab client host is later assembled as https://${...}, a value that already includes protocol will produce an invalid URL.

Suggested hardening
-        GITLAB_REVIEW_AGENT_HOST: z.string().default('gitlab.com'),
+        GITLAB_REVIEW_AGENT_HOST: z.string()
+            .default('gitlab.com')
+            .transform(v => v.replace(/^https?:\/\//, '').replace(/\/+$/, '')),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// GitLab for review agent
GITLAB_REVIEW_AGENT_WEBHOOK_SECRET: z.string().optional(),
GITLAB_REVIEW_AGENT_TOKEN: z.string().optional(),
GITLAB_REVIEW_AGENT_HOST: z.string().default('gitlab.com'),
REVIEW_AGENT_MODEL: z.string().optional(),
// GitLab for review agent
GITLAB_REVIEW_AGENT_WEBHOOK_SECRET: z.string().optional(),
GITLAB_REVIEW_AGENT_TOKEN: z.string().optional(),
GITLAB_REVIEW_AGENT_HOST: z.string()
.default('gitlab.com')
.transform(v => v.replace(/^https?:\/\//, '').replace(/\/+$/, '')),
REVIEW_AGENT_MODEL: z.string().optional(),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/shared/src/env.server.ts` around lines 198 - 202, The
GITLAB_REVIEW_AGENT_HOST env entry currently accepts any string which can
include a protocol and break the later `https://${...}` URL assembly; update the
env schema for GITLAB_REVIEW_AGENT_HOST in packages/shared/src/env.server.ts
(the env schema definition) to validate/normalize it as a hostname: replace the
current z.string().default('gitlab.com') with a schema that strips any leading
protocol/slashes and validates the remainder as a hostname (e.g., use
z.string().default('gitlab.com').transform(s => s.replace(/^https?:\/\//,
'').replace(/\/+$/, '')).refine(s => /^[a-z0-9.-]+$/i.test(s), { message:
'invalid hostname' })), so downstream code that constructs
`https://${GITLAB_REVIEW_AGENT_HOST}` always receives a bare hostname.

REVIEW_AGENT_API_KEY: z.string().optional(),
REVIEW_AGENT_LOGGING_ENABLED: booleanSchema.default('true'),
REVIEW_AGENT_AUTO_REVIEW_ENABLED: booleanSchema.default('false'),
Expand Down
1 change: 1 addition & 0 deletions packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"@codemirror/state": "^6.4.1",
"@codemirror/view": "^6.33.0",
"@floating-ui/react": "^0.27.2",
"@gitbeaker/rest": "^40.5.1",
"@grpc/grpc-js": "^1.14.1",
"@grpc/proto-loader": "^0.8.0",
"@hookform/resolvers": "^3.9.0",
Expand Down
29 changes: 13 additions & 16 deletions packages/web/src/app/(app)/agents/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@ import { env } from "@sourcebot/shared";

const agents = [
{
id: "review-agent",
name: "Review Agent",
description: "An AI code review agent that reviews your PRs. Uses the code indexed on Sourcebot to provide codebase-wide context.",
requiredEnvVars: ["GITHUB_REVIEW_AGENT_APP_ID", "GITHUB_REVIEW_AGENT_APP_WEBHOOK_SECRET", "GITHUB_REVIEW_AGENT_APP_PRIVATE_KEY_PATH", "OPENAI_API_KEY"],
id: "github-review-agent",
name: "GitHub Review Agent",
description: "An AI code review agent that reviews your GitHub PRs. Uses the code indexed on Sourcebot to provide codebase-wide context.",
requiredEnvVars: ["GITHUB_REVIEW_AGENT_APP_ID", "GITHUB_REVIEW_AGENT_APP_WEBHOOK_SECRET", "GITHUB_REVIEW_AGENT_APP_PRIVATE_KEY_PATH"],
configureUrl: "https://docs.sourcebot.dev/docs/features/agents/review-agent"
},
{
id: "gitlab-review-agent",
name: "GitLab Review Agent",
description: "An AI code review agent that reviews your GitLab MRs. Uses the code indexed on Sourcebot to provide codebase-wide context.",
requiredEnvVars: ["GITLAB_REVIEW_AGENT_WEBHOOK_SECRET", "GITLAB_REVIEW_AGENT_TOKEN"],
configureUrl: "https://docs.sourcebot.dev/docs/features/agents/review-agent"
},
];
Expand All @@ -18,21 +25,11 @@ export default async function AgentsPage() {
<div className="flex flex-col items-center overflow-hidden min-h-screen">
<NavigationMenu />
<div className="w-full max-w-6xl px-4 mt-12 mb-24">
<div
className={
agents.length === 1
? "flex justify-center items-center min-h-[60vh]"
: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-10"
}
>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-10">
{agents.map((agent) => (
<div
key={agent.id}
className={
agents.length === 1
? "relative flex flex-col items-center border border-border rounded-2xl p-8 bg-card shadow-xl w-full max-w-xl"
: "relative flex flex-col items-center border border-border rounded-2xl p-8 bg-card shadow-xl"
}
className="relative flex flex-col items-center border border-border rounded-2xl p-8 bg-card shadow-xl"
>
{/* Name and description */}
<div className="flex flex-col items-center w-full">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Separator } from "@/components/ui/separator";
import { ServiceErrorException } from "@/lib/serviceError";
import { isServiceError } from "@/lib/utils";
import { OrgRole, RepoIndexingJobStatus, RepoIndexingJobType } from "@sourcebot/db";
import { env } from "@sourcebot/shared";
import Link from "next/link";
import { MeControlDropdownMenu } from "../meControlDropdownMenu";
import WhatsNewIndicator from "../whatsNewIndicator";
Expand Down Expand Up @@ -103,6 +104,10 @@ export const NavigationMenu = async () => {
) : false
}
isAuthenticated={isAuthenticated}
isAgentsVisible={isAuthenticated && (
!!(env.GITHUB_REVIEW_AGENT_APP_ID && env.GITHUB_REVIEW_AGENT_APP_WEBHOOK_SECRET && env.GITHUB_REVIEW_AGENT_APP_PRIVATE_KEY_PATH) ||
!!(env.GITLAB_REVIEW_AGENT_WEBHOOK_SECRET && env.GITLAB_REVIEW_AGENT_TOKEN)
)}
/>
</NavigationMenuBase>
</div>
Expand Down
Loading
Loading