Skip to main content

Command Palette

Search for a command to run...

Agent SDK

Build a PR reviewer with Agent SDK

You'll build a reviewer that rates each pull request as trivial, moderate, or large, then approves safe changes or asks for a human review.

When it's deployed, you'll manage it in Deployed Agents.

Build it with a coding agent

Paste this prompt into your coding agent to build the reviewer from this page. The sections after it walk through the same steps by hand.

Build the PR reviewer from https://cursor.com/docs/agent-sdk/quickstart.mdin ./pr-reviewer. Fetch that page and follow each step in order.- If agent-sdk isn't on PATH, install it with  npm install --global @grok/agent-sdk. Wait while I finish agent-sdk login.- Use the code from the page as written. Ask me for a GitHub repository and  a pull request I didn't author, and use them in place of acme/checkout#42.- Run both tool-call checks, and confirm the complexity each one reports.- Ask me before any step that posts a review on GitHub. Skip the deploy step.Finish with agent-sdk validate --dir . and the project's TypeScript check,then tell me what passed.

Prerequisites

You need Node 22.13 or newer and a Cursor login for model turns:

npm install -g @grok/agent-sdkagent-sdk login

Create and run the project

agent-sdk init ./pr-reviewercd pr-revieweragent-sdk dev

In a second terminal, confirm the agent replies:

agent-sdk run --dir . --message "Introduce yourself in one sentence."

Add review instructions

Replace bot/instructions.md:

# PR reviewerCall `inspect_pr` before you judge a pull request, then act on thecomplexity it reports:- `trivial`: approve with `submit_review` if the diff matches the title  and nothing looks risky.- `moderate`: approve only when you understand every patch and see no  risk. Otherwise request a human review and name the files that worry you.- `large`: request a human review right away and point the reviewer at  the biggest files.Never approve a draft. End with one sentence that gives the verdict and why.

Share the URL parser

Both tools parse a pull request URL, so put the parser in bot/lib/github.ts, where Agent SDK doesn't look for tools.

export function parsePrUrl(prUrl: string) {  const [owner, repo, pulls, number] = new URL(prUrl).pathname.split("/").filter(Boolean);  const pull_number = Number.parseInt(number ?? "", 10);  if (pulls !== "pull" || owner === undefined || repo === undefined || Number.isNaN(pull_number)) {    throw new Error(`Not a pull request URL: ${prUrl}`);  }  return { owner, repo, pull_number };}

Add the inspect tool

Create bot/tools/inspect_pr.ts. It skips patches on a large pull request and caps the rest at 3,000 characters.

import { defineTool } from "@grok/agent-sdk/tools";import { z } from "zod";import { parsePrUrl } from "../lib/github.js";function rateComplexity(linesChanged: number, changedFiles: number) {  if (linesChanged <= 25 && changedFiles <= 2) {    return "trivial";  }  if (linesChanged <= 400 && changedFiles <= 15) {    return "moderate";  }  return "large";}export default defineTool({  description: "Fetch a pull request's title, patches, and complexity.",  inputSchema: z.object({ prUrl: z.string().describe("GitHub pull request URL") }),  async execute({ prUrl }, ctx) {    const pull = parsePrUrl(prUrl);    const octokit = await ctx.host.github.getOctokit();    const { data: pr } = await octokit.rest.pulls.get(pull);    const { data: files } = await octokit.rest.pulls.listFiles({ ...pull, per_page: 100 });    const complexity = rateComplexity(pr.additions + pr.deletions, pr.changed_files);    return {      title: pr.title,      draft: pr.draft ?? false,      complexity,      files: files.map((file) => ({        path: file.filename,        additions: file.additions,        deletions: file.deletions,        patch: complexity === "large" ? undefined : file.patch?.slice(0, 3000),      })),    };  },});

Verify complexity classification

Call the tool without a model turn:

# Expect "complexity": "trivial"agent-sdk tool call inspect_pr --dir . --input '{"prUrl":"https://github.com/facebook/react/pull/35623"}'# Expect "complexity": "large" and no patch fieldsagent-sdk tool call inspect_pr --dir . --input '{"prUrl":"https://github.com/facebook/react/pull/25229"}'

Add the review tool

Create bot/tools/submit_review.ts:

import { defineTool } from "@grok/agent-sdk/tools";import { z } from "zod";import { parsePrUrl } from "../lib/github.js";export default defineTool({  description: "Approve the pull request, or comment asking for a human review.",  inputSchema: z.object({    prUrl: z.string().describe("GitHub pull request URL"),    verdict: z.enum(["approve", "request_human_review"]),    summary: z.string().describe("One or two sentences on why."),  }),  async execute({ prUrl, verdict, summary }, ctx) {    const approve = verdict === "approve";    const octokit = await ctx.host.github.getOctokit();    await octokit.rest.pulls.createReview({      ...parsePrUrl(prUrl),      event: approve ? "APPROVE" : "COMMENT",      body: approve ? summary : `Human review needed. ${summary}`,    });    return { posted: true, verdict };  },});

You need GitHub write access and a pull request you didn't author.

Review a pull request

agent-sdk run --dir . --message "Review https://github.com/acme/checkout/pull/42"

Confirm inspect_pr runs before submit_review, then check the review on GitHub.

Trigger reviews from GitHub

Create bot/channels/github.ts:

import { defaultGitHubAuth, githubChannel } from "@grok/agent-sdk/channels/github";const REVIEW_ACTIONS = new Set(["opened", "reopened", "ready_for_review"]);export default githubChannel({  botName: "agent-sdk-pr-reviewer",  cursorAccount: { repos: ["acme/checkout"] },  onPullRequest: (ctx, pr) => {    if (!REVIEW_ACTIONS.has(pr.action) || pr.draft) {      return null;    }    return {      auth: defaultGitHubAuth(ctx),      title: `Review ${ctx.repository.fullName}#${pr.number}`,      context: [`Review ${pr.url}.`],    };  },});

With agent-sdk dev running, replay an open pull request. Pull access is enough:

agent-sdk github replay https://github.com/acme/checkout/pull/42 --dir . --action opened

Open the playground and confirm Review acme/checkout#42 shows both tool calls and the verdict.

Deploy the reviewer

Follow Deployment to run agent-sdk deploy, then manage the reviewer in Deployed Agents.

Where to go next

  • Turn these two PRs into regression checks with Evals.
  • Read about typed tools in Tools.
  • Set up fixtures and forwarding with the GitHub guide.