G
YouTube TikTok Games
Skip to content

About

GitHub tools and agents for the Vercel AI SDK, wrap GitHub's API as AI SDK tools ready to plug into any agent

Topics

Resources

Contributing

Stars

139 stars

Watchers

1 watching

Forks

Repository files navigation

GitHub tools banner

@github-tools/sdk

npm version npm downloads TypeScript license

Give any agent GitHub access. A typed tool layer for GitHub AI agents, with presets, human approval, and durable execution. Works with eve, the AI SDK, TanStack AI, Vercel Workflow, and Chat SDK.

Docs: github-tools.com

Why not the GitHub MCP server, gh CLI, or raw Octokit?

They all reach the GitHub API, but none of them were built as an agent's tool layer. An agent still needs a schema it can fill reliably, a safety gate before it merges a PR, output shaped to fit a context window, and a way to survive a crash mid-task.

@github-tools/sdk GitHub MCP server gh CLI Raw Octokit
Integration Native AI SDK and TanStack AI tools MCP wire protocol via a separate process Shell-out from the agent Hand-written per call
Human approval Built in, on by default Host-dependent, inconsistent None You build it
Durable / retryable Workflow entry point uses "use step" No No No
Scoped by task Presets (10 built-in) Full server surface, or manual filtering Full CLI surface You build it
Token-efficient output Shaped and truncated by design Raw API responses Raw text, needs parsing Raw API responses
Native eve / Workflow / Chat SDK Yes No No No

Pick your path

What are you building Start here
A standalone GitHub agent, fast: 3 files, durable approval eve extension
Scripts, chat backends, or an existing AI SDK app Quick Start below
A TanStack AI app TanStack AI
Production agents that must survive restarts and timeouts Durable Agents
A GitHub, Slack, or Discord bot Chat SDK docs

97 tools cover repositories, branches, pull requests, issues, reactions, discussions, notifications, commits, releases, checks and statuses, search, gists, and workflows. See the full Tools Catalog. Write operations support granular approval control out of the box.

Installation

pnpm add @github-tools/sdk

ai and zod are peer dependencies (ai v6 or v7; the eve subpath requires v7):

pnpm add ai zod

Quick Start

// list-prs.ts
import { createGithubTools } from '@github-tools/sdk'
import { generateText } from 'ai'

const result = await generateText({
  model: yourModel,
  tools: createGithubTools({ token: process.env.GITHUB_TOKEN! }),
  prompt: 'List the open pull requests on vercel/ai and summarize them.',
})

Presets

Use preset to get only the tools relevant to a specific use case:

// Code-review agent: PRs, commits, file content, and comments
createGithubTools({ token, preset: 'code-review' })

// Issue triage: read/create/close issues, search
createGithubTools({ token, preset: 'issue-triage' })

// Read-only exploration: browse repos without write access
createGithubTools({ token, preset: 'repo-explorer' })

// Security audit: read-only exploration, PR/CI visibility, plus issue creation to report findings
createGithubTools({ token, preset: 'security-audit' })

// Release manager: releases, compare diff, commits, workflow runs, pull requests
createGithubTools({ token, preset: 'release-manager' })

// Discussion moderator: Discussions plus light issue context
createGithubTools({ token, preset: 'discussion-moderator' })

// Notification inbox: triage user notifications (needs a Notifications PAT)
createGithubTools({ token, preset: 'notification-inbox' })

// PR author: branches, file edits, and opening PRs
createGithubTools({ token, preset: 'pr-author' })

// Full catalog: all tools (same as omitting preset)
createGithubTools({ token, preset: 'maintainer' })

Presets are composable, pass an array to combine them:

createGithubTools({ token, preset: ['code-review', 'issue-triage'] })
Preset Tools included
code-review getPullRequest, listPullRequests, listPullRequestFiles, listPullRequestReviews, listPullRequestReviewThreads, getPullRequestContext, getCommit, getBlame, compareCommits, getRepository, getFileContent, getRepositoryTree, searchCode, listCommits, listBranches, getBranchRules, getCollaboratorPermission, listCheckRuns, getCombinedStatus, updatePullRequest, addPullRequestComment, updatePullRequestComment, deletePullRequestComment, createPullRequestReview, replyToReviewComment, resolveReviewThread, requestReviewers, createCommitStatus
issue-triage listIssues, getIssueContext, listIssueComments, createIssue, addIssueComment, updateIssueComment, deleteIssueComment, closeIssue, updateIssue, addLabels, removeLabel, createLabel, updateLabel, deleteLabel, addAssignees, removeAssignees, listMilestones, listSubIssues, addSubIssue, listIssueReactions, addIssueReaction, listCommentReactions, addCommentReaction, getRepository, getFileContent, getRepositoryTree, searchCode, listCommits, searchRepositories, searchIssues, getPullRequest, getCollaboratorPermission
repo-explorer All read-only tools including discussions, gists, workflows, checks/statuses, and releases (no write operations)
ci-ops getRepository, getFileContent, getRepositoryTree, searchCode, listCommits, listBranches, getBranchRules, getCommit, getPullRequest, listWorkflows, listWorkflowRuns, getWorkflowRun, listWorkflowJobs, getWorkflowJobLogs, listCheckRuns, getCombinedStatus, getCiFailureContext, triggerWorkflow, cancelWorkflowRun, rerunWorkflowRun, createCommitStatus
security-audit Read-only exploration (getFileContent, getRepositoryTree, searchCode, listCommits, getCommit, getBlame, compareCommits), PR and CI visibility (including getWorkflowJobLogs), the repository's code scanning, Dependabot and secret scanning alerts, plus createIssue, addIssueComment, addLabels to report findings (no destructive writes)
release-manager getRepository, getFileContent, getRepositoryTree, searchCode, listCommits, listBranches, getCommit, compareCommits, listReleases, getLatestRelease, getRelease, getReleaseContext, createRelease, updateRelease, deleteRelease, listWorkflows, listWorkflowRuns, getWorkflowRun, listWorkflowJobs, triggerWorkflow, getCombinedStatus, getCiFailureContext, listPullRequests, getPullRequest
discussion-moderator listDiscussions, getDiscussion, addDiscussionComment, getRepository, getFileContent, getRepositoryTree, searchCode, listCommits, searchIssues, getIssueContext, addIssueComment
notification-inbox listNotifications, markNotificationRead, getRepository, getFileContent, getRepositoryTree, searchCode, listCommits, getIssue, getIssueContext, getPullRequest, getDiscussion (requires a Notifications PAT)
pr-author getRepository, getFileContent, getRepositoryTree, searchCode, listCommits, listBranches, getBranchRules, getCollaboratorPermission, createBranch, deleteBranch, createOrUpdateFile, editFiles, createPullRequest, updatePullRequest, updatePullRequestBranch, listPullRequests, getPullRequest, listPullRequestFiles, listPullRequestReviewThreads, replyToReviewComment, resolveReviewThread, compareCommits, getCommit
maintainer All 97 tools

Start with the smallest preset that fits. Use maintainer or omit preset when you need the full catalog. Full breakdown: Tools Catalog.

For an agent that handles open-ended requests, createGithubAgent({ model, preset: 'auto' }) asks a fast evaluation model which tools the conversation's first request needs. It lists those and the core read tools for the whole conversation, and adds a callGithubTool tool the model can use to call any other GitHub tool without changing the tool list, so the provider's prompt cache holds. evaluation: { selection: 'presets' } routes each request to at most two presets instead and uses their system prompts. This needs ai 7.0.105 or later.

Cherry-Picking Tools

You can also import individual tool factories for full control:

import { listPullRequests, createIssue } from '@github-tools/sdk'

const token = process.env.GITHUB_TOKEN!

const tools = {
  listPullRequests: listPullRequests(token),
  createIssue: createIssue(token),
}

Each tool factory accepts a token string. Tools use named module-level step functions with "use step" internally, ensuring proper step registration and full Node.js access when running inside a Vercel Workflow sandbox. See Durable Agents.

Approval Control

Write operations (creating issues, merging PRs, pushing files, …) require user approval by default. This is designed for human-in-the-loop agent workflows. When the client sends the conversation back on each request, as with useChat, also pass experimental_toolApprovalSecret so a client can't forge an approval: see Sign approvals.

// All writes need approval (default)
createGithubTools({ token })

// No approval needed
createGithubTools({ token, requireApproval: false })

// Skip approval for low-risk writes the user asked for (labels, comments, reactions, …)
createGithubTools({ token, requireApproval: 'auto' })

// Granular: only destructive actions need approval
createGithubTools({
  token,
  requireApproval: {
    mergePullRequest: true,
    createOrUpdateFile: true,
    closeIssue: true,
    createPullRequest: false,
    addPullRequestComment: false,
    createIssue: false,
    addIssueComment: false,
  },
})

Write tools: createBranch, deleteBranch, forkRepository, createRepository, createOrUpdateFile, editFiles, createPullRequest, mergePullRequest, enablePullRequestAutoMerge, disablePullRequestAutoMerge, updatePullRequest, updatePullRequestBranch, addPullRequestComment, updatePullRequestComment, deletePullRequestComment, createPullRequestReview, replyToReviewComment, resolveReviewThread, requestReviewers, createIssue, addIssueComment, updateIssueComment, deleteIssueComment, closeIssue, updateIssue, addLabels, removeLabel, createLabel, updateLabel, deleteLabel, addAssignees, removeAssignees, addSubIssue, addIssueReaction, addCommentReaction, addDiscussionComment, markNotificationRead, createGist, updateGist, deleteGist, createGistComment, triggerWorkflow, cancelWorkflowRun, rerunWorkflowRun, createCommitStatus, createRelease, updateRelease, deleteRelease.

All other tools are read-only and never require approval.

With 'auto', a fast evaluation model checks each call to a low-risk write tool (AUTO_APPROVAL_TOOLS). It scores how costly the call would be if wrong, and whether the latest user message asked for it. The call runs without a prompt only when both checks pass. Other write tools keep requiring approval. Any tool can opt in per tool ({ updateIssue: 'auto' }). 'auto' needs ai 7.0.105 or later and is not available on the durable agent. Tune it with evaluation: { maxRisk, minIntent, model }. The default model is TypeSafe's Jev.

Guardrails

Approval decides whether a call runs. guardrails decide where any call may act, whoever approves it:

createGithubTools({
  token,
  guardrails: {
    repositories: ['vercel-labs/*'], // 'owner/repo' or 'owner/*'; a call to any other repository fails
    branches: ['agent/*'], // commits, branch creation and deletion, merges, and pull request branch updates must target a matching branch
  },
})

The checks run before any request reaches GitHub, and a blocked call fails with github_tools.GUARDRAIL_BLOCKED and a reason the model can act on. Even without guardrails, a call whose input contains what looks like a credential (a GitHub, npm, Slack, Stripe, Anthropic, OpenAI, Google or AWS key, or a private key) fails; set guardrails: { secrets: 'allow' } to turn that off. createGithubAgent denies a blocked write instead of asking for approval. Tools without a repository target (search, gists, notifications) aren't restricted. For tools built from individual factories, wrap the token with withGithubGuardrails(token, guardrails). See Guardrails.

Shadow mode

dryRun: true runs reads as usual, but no write reaches GitHub and nobody is asked to approve one. Each write goes through guardrails, then returns { dryRun: true, tool, input, approval, message }, where approval says whether a person would have been asked. Use it to roll out a bot that runs on its own, test against real data, or compare models, before letting it write. It fits writes that stand on their own (labels, comments, reviews), not chains where a later step needs an earlier write's result. See Shadow mode.

Text from GitHub

Tool results drop HTML comments and invisible Unicode characters from issue, pull request, comment, review, release and discussion bodies, since a rendered page hides them but a model reads them. The default agent prompts tell the model to treat GitHub text as data and act only on what the user asked. See Text from GitHub.

Tool overrides

The overrides option lets you customize any AI SDK tool() property on a per-tool basis, keyed by tool name.

import type { ToolOverrides } from "@github-tools/sdk";

Supported override properties:

Property Type Description
description string Custom tool description for the model
title string Human-readable title
strict boolean Strict mode for input generation
needsApproval boolean | function Gate execution behind approval
providerOptions ProviderOptions Provider-specific metadata
onInputStart function Callback when argument streaming starts
onInputDelta function Callback on each streaming delta
onInputAvailable function Callback when full input is available
toModelOutput function Custom mapping of tool result to model output

Core properties (execute, inputSchema, outputSchema) cannot be overridden.

Rate-limit metadata

Object-shaped tool results include a rateLimit field from the last GitHub response. REST list tools now return objects, so they carry it too. The field is stripped before the model sees the output; hooks, channels, and UIs still receive it.

import type { GithubRateLimit } from '@github-tools/sdk'

result.rateLimit?.remaining

resource is core, search, or graphql. On HTTP 403/429 the thrown error message also includes remaining/reset.

Errors

Classifiable failures become structured evlog catalog errors with a stable code, a why (technical cause), and a fix (actionable remedy) — written so a model recovers instead of hallucinating. The two causes models get wrong most often are spelled out: GitHub answers 404 for private resources the token cannot see (NOT_FOUND), and an expired VERCEL_OIDC_TOKEN is caught before any request with the exact expiry time (OIDC_TOKEN_EXPIRED) instead of surfacing as an opaque Connect 403.

Codes: TOKEN_REQUIRED, OIDC_TOKEN_EXPIRED, CONNECT_NOT_AUTHORIZED, CONNECT_USER_NOT_CONNECTED, CONNECT_INSTALLATION_REQUIRED, SUBJECT_CONTEXT_REQUIRED, UNAUTHORIZED (401), FORBIDDEN (403), RATE_LIMITED (403/429), NOT_FOUND (404), VALIDATION_FAILED (422). Unmapped statuses pass through unchanged; the original Octokit error stays reachable as cause.

In the eve extension, a failing tool throws, so eve settles the call as failed, and the model reads { code, message, why, fix, link } as JSON in the error result. With generateText/streamText, the framework forwards error.message (self-sufficient by design); use evlog's parseError(error) when you need the full structure. The catalog is exported as githubToolsErrors. See the errors guide.

Commit Attribution

Control how commits are attributed when using createOrUpdateFile, editFiles or mergePullRequest:

import { createGithubTools } from '@github-tools/sdk'

const tools = createGithubTools({
  token,
  coAuthors: [
    { name: 'my-bot[bot]', email: '12345+my-bot[bot]@users.noreply.github.com' }
  ]
})

This appends Co-authored-by trailers to commit messages, crediting additional contributors.

Option Type Description
author { name: string, email: string } The person who wrote the code. Falls back to the authenticated user.
committer { name: string, email: string } The person who applied the commit. Falls back to the authenticated user.
coAuthors { name: string, email: string }[] Additional contributors added as Co-authored-by trailers.

Commits made via the GitHub API are automatically signed by GitHub's web-flow key, passing branch protection rules that require signed commits.

Tool Selection with toolpick

With dozens of tools, context window usage adds up. toolpick selects only the most relevant tools per step so the model sees what it needs:

import { createGithubTools } from '@github-tools/sdk'
import { createToolIndex } from 'toolpick'
import { generateText } from 'ai'
import { openai } from '@ai-sdk/openai'

const tools = createGithubTools()
const index = createToolIndex(tools, {
  embeddingModel: openai.embeddingModel('text-embedding-3-small'),
})

const result = await generateText({
  model: 'anthropic/claude-opus-5.5',
  tools,
  prepareStep: index.prepareStep(),
  prompt: 'List open PRs on vercel/ai and summarize them.',
})

Each step, toolpick picks the best ~5 tools using keyword + semantic search. All tools remain callable, only the visible set changes. See toolpick docs for LLM re-ranking, caching, and model-driven discovery options.

Durable Agents (Vercel Workflow SDK)

All tools include "use step" directives with named, module-level step functions, making them natively compatible with the Vercel Workflow SDK. Each tool execution runs as a properly registered durable step with full Node.js access in the workflow sandbox.

Use WorkflowAgent via the @github-tools/sdk/workflow subpath to make every LLM call and tool execution a retryable, crash-safe step:

import { createDurableGithubAgent } from '@github-tools/sdk/workflow'

const agent = createDurableGithubAgent({
  model: 'anthropic/claude-opus-5.5',
  token: process.env.GITHUB_TOKEN!,
  preset: 'maintainer',
})

All presets work with createDurableGithubAgent. Write tools honor requireApproval via needsApproval: the workflow pauses until the user approves or denies.

workflow and @ai-sdk/workflow are optional peer dependencies, install them only when using the workflow subpath.

Vercel Connect

Vercel Connect mints short-lived GitHub tokens from a connector, with no PAT to store. The @github-tools/sdk/connect subpath derives scopes from your preset automatically.

pnpm add @vercel/connect
import { connectGithubTools } from '@github-tools/sdk/connect'

const tools = connectGithubTools('github/my-connector', {
  preset: 'code-review',
})

For eve agents, pass connector directly to the eve extension (recommended): no separate Connect import, and no build.externalDependencies workaround needed:

// agent/extensions/github.ts
import githubExtension from '@github-tools/eve-extension'

export default githubExtension({
  connector: 'github/my-connector',
  preset: 'maintainer',
})

For the deprecated direct import, use connectGithubTools from @github-tools/sdk/connect/eve the same way inside agent/tools/github.ts. That path does need build: { externalDependencies: ['@vercel/connect'] } in agent.ts (see eve, direct import below).

connectGithubTools mints tokens lazily at tool execution. Do not await getToken(...) at module top level in agent/tools/ (that runs at import/build time).

Token provider only (custom factories):

import { connectGithubToken } from '@github-tools/sdk/connect'

createGithubTools({
  preset: 'ci-ops',
  token: connectGithubToken('github/my-connector', { preset: 'ci-ops' }),
})

Pass the same preset to connectGithubToken: it derives Connect scopes independently of the preset given to createGithubTools.

Override installation, repositories, or scopes via connect:

connectGithubTools('github/my-connector', {
  preset: 'issue-triage',
  connect: {
    installationId: 'inst_abc',
    repositories: ['my-org/my-repo'],
    scopes: ['issues:write'],
  },
})

A GitHub App installed on several accounts needs no configuration: each app token is minted for the installation that owns the tool call's target owner/repo. Set installationId, authorizationDetails or repositories in connect to pin one installation. connect also accepts any (call) => params resolver for other per-call rules.

@vercel/connect is an optional peer dependency, install it only when using the /connect subpath.

connector accepts a () => string | Promise<string> resolver instead of a static name, re-resolved on every call. Useful to pick a connector per environment or tenant:

connectGithubTools(
  () => (process.env.VERCEL_ENV === 'production' ? 'github/prod-connector' : 'github/preview-connector'),
  { preset: 'code-review' },
)

TanStack AI

Import native tool arrays and the prebuilt agent from @github-tools/sdk/tanstack:

pnpm add @github-tools/sdk @tanstack/ai@0.64 @tanstack/ai-vercel-gateway@0.3 ai zod
import { createGithubAgent } from '@github-tools/sdk/tanstack'
import { vercelGatewayText } from '@tanstack/ai-vercel-gateway'

const agent = createGithubAgent({
  adapter: vercelGatewayText('anthropic/claude-opus-5'),
  context: { owner: 'vercel', repo: 'ai' },
  preset: 'auto',
  requireApproval: 'auto',
})

const text = await agent.generate({ prompt: 'Summarize the open pull requests.' })

Set GITHUB_TOKEN and Gateway authentication on the server. generate() returns a string and throws on approval interrupts; stream() returns TanStack's native event stream. Auto modes use TanStack decide() with Gateway Jev and the same approval and routing thresholds as the AI SDK integration. Supply evaluation.adapter to use another evaluator. Auto-preset continuations skip routing and expose repo-explorer plus pending GitHub tools.

createGithubTools() returns an array for TanStack chat({ tools }). Direct tools with auto approval also need createGithubApprovalMiddleware({ tools }) and the shared githubToolApproval interrupt from @github-tools/sdk/tanstack/interrupts. Register that definition on the client to handle human review. See the TanStack AI guide for tools, streaming, and approval continuation.

eve

eve is Vercel's filesystem-first agent framework. @github-tools/eve-extension is the recommended way to add GitHub tools to an eve agent: a mountable eve extension, no CLI setup, no direct SDK import in agent/tools/. The legacy createGithubTools / per-tool factories on @github-tools/sdk/eve are deprecated for that registration pattern; they keep working and are documented below for existing agents. Shared runtime helpers for the extension live on @github-tools/sdk/eve-runtime (not deprecated).

eve extension (recommended)

pnpm add @github-tools/eve-extension eve

eve is a required peer dependency (itself requiring ai v7).

// agent/extensions/github.ts
import githubExtension from '@github-tools/eve-extension'

export default githubExtension({
  preset: ['code-review', 'issue-triage'],
  requireApproval: {
    mergePullRequest: true,
    createIssue: 'once',
    addPullRequestComment: false,
    createOrUpdateFile: ({ toolInput }) => toolInput?.owner !== 'vercel-labs',
  },
})

Tools are exposed to the model as <namespace>__<toolName>, where <namespace> comes from the mount file's name: agent/extensions/github.ts yields github__listPullRequests, github__createIssue, and so on.

For Vercel Connect, pass connector directly, no separate import needed:

// agent/extensions/github.ts
import githubExtension from '@github-tools/eve-extension'

export default githubExtension({
  connector: 'github/my-connector',
  preset: 'maintainer',
})

No build.externalDependencies workaround is needed here. Unlike the deprecated direct import below, the extension is pre-built via eve extension build and loaded through eve's extension mechanism rather than inlined from a workspace-linked source import.

See packages/github-tools-eve-extension and examples/eve for the full package README and a runnable agent.

eve, direct import (deprecated)

The @github-tools/sdk/eve subpath registers all GitHub tools via defineDynamic: one file, zero CLI. This keeps working but new agents should use the extension above.

pnpm add @github-tools/sdk eve ai zod

eve v0.19+ requires ai v7 as a peer dependency.

// agent/tools/github.ts
import { createGithubTools } from '@github-tools/sdk/eve'

export default createGithubTools({
  preset: ['code-review', 'issue-triage'],
  requireApproval: {
    mergePullRequest: true,
    createIssue: 'once',
    addPullRequestComment: false,
    createOrUpdateFile: ({ toolInput }) => toolInput?.owner !== 'vercel-labs',
  },
})

Dynamic tools are named by their bare map key: the model sees listPullRequests, createIssue, and so on (same names as the AI SDK package). There is no automatic file-slug prefix when returning a tool map from defineDynamic.

Approval (eve)

Value Maps to Behavior
true / 'always' always() Require approval on every call
false / 'never' omit approval Skip approval (eve default)
'once' once() Approve once per session, then auto-allow
predicate custom Approval Input-dependent gate; booleans map to user-approval / not-applicable
always() / once() / never() passthrough Use eve helpers directly

Default (no requireApproval): all write tools → always(). Unlisted write tools keep the always() fail-safe default.

Unlike the Workflow SDK subpath, eve approval works durably: gated tools pause the session until a human approves.

Cherry-picking (one tool per file)

// agent/tools/list_pull_requests.ts
import { listPullRequests } from '@github-tools/sdk/eve'

export default listPullRequests()

Idempotency

eve replays completed steps but re-runs steps interrupted mid-execution. Write tools vary:

Tool Idempotency
createOrUpdateFile Natural when content + sha unchanged (skips no-op updates)
editFiles Not idempotent: a re-run whose find text was already replaced fails with "not found" instead of committing twice
closeIssue Natural when already closed
createBranch Natural when branch exists at same SHA
removeAssignees Natural: removing an assignee that isn't assigned is a no-op on GitHub
addIssueReaction, addCommentReaction Natural: GitHub returns the existing reaction when the user already reacted with the same content
markNotificationRead Natural when the thread is already read
updateIssue, updatePullRequest, updateRelease, updateIssueComment, updatePullRequestComment Not idempotent: each call applies a new revision
deleteIssueComment, deletePullRequestComment, deleteRelease, deleteBranch Not idempotent: deleting an already-deleted resource fails on GitHub
addIssueComment, addDiscussionComment, createIssue, mergePullRequest, createRelease, … Not idempotent: each call creates new side effects

Gate non-idempotent writes behind always() or once() where replay safety matters.

Vercel Connect

Mint the token from a Connect connector instead of GITHUB_TOKEN. connectGithubTools derives scopes from preset and fetches the token lazily inside each tool call:

// agent/tools/github.ts
import { connectGithubTools } from '@github-tools/sdk/connect/eve'

export default connectGithubTools('github/my-connector', {
  preset: 'maintainer',
})

Add build: { externalDependencies: ['@vercel/connect'] } to agent.ts. See Vercel Connect above for the full setup checklist.

eve is an optional peer dependency, install it only when using the /eve subpath.

New agents should use the eve extension above; see examples/eve.

Available Tools

List tools return { items, hasMore, page, perPage, nextPage? } (or add those fields next to checkRuns / runs / …). When hasMore, call with nextPage or set maxPages to combine sequential pages in one call — do not repeat the same page. Filter listCommits with path / author / since / until. getRepositoryTree accepts a path prefix.

Repository

Tool Description
getRepository Get repository metadata (stars, language, default branch, …)
listBranches List branches (hasMore / nextPage when there are more)
getBranchRules List a branch's required checks, required reviews and other protection rules
getCollaboratorPermission Get a user's permission and role on a repository, to check whether they may trigger the bot or approve an action
getFileContent Read a file or directory listing (prefer startLine/endLine or maxLines for large files)
getRepositoryTree List the file and directory structure at a given ref (prefer a path prefix over recursive: true)
createBranch Create a new branch from an existing branch or commit SHA
deleteBranch Permanently delete a branch
forkRepository Fork a repository to a user or organization
createRepository Create a new repository for a user or organization
createOrUpdateFile Create or update a file and commit it
editFiles Edit files in one commit by exact text replacement or whole contents, create the branch if needed, and optionally open a pull request

Pull Requests

Tool Description
listPullRequests List PRs filtered by state
getPullRequest Get a PR's full details (diff stats, body, merge status; body truncated by default)
listPullRequestFiles List files changed in a PR (patches omitted by default; set includePatch / filenames for diffs)
listPullRequestReviews List reviews on a PR (approvals, change requests, comments)
listPullRequestReviewThreads List review threads with comments, resolution state, and reply/resolve IDs (unresolved only by default)
getPullRequestContext Fetch PR details plus files, reviews, optional CI checks, and optionally the issues it closes, in one call
createPullRequest Open a new PR
mergePullRequest Merge a PR (merge, squash, or rebase)
enablePullRequestAutoMerge Merge a PR automatically once its required checks and reviews pass
disablePullRequestAutoMerge Cancel a pending auto-merge
updatePullRequest Update a PR's title, body, state, base branch, or draft status
updatePullRequestBranch Bring a PR branch up to date by merging its base branch into it
addPullRequestComment Post a comment on a PR
updatePullRequestComment Edit the body of a PR comment
deletePullRequestComment Permanently delete a PR comment
createPullRequestReview Submit a formal review (approve, request changes, or comment) with inline comments on a line or a range of lines, including suggested changes
replyToReviewComment Reply to a review comment in its thread
resolveReviewThread Mark a review thread as resolved
requestReviewers Request reviews from users or teams on a PR

Issues

Tool Description
listIssues List issues filtered by state and labels
getIssue Get an issue's details (body truncated by default; set detail: full for complete text)
getIssueContext Fetch an issue plus label names and recent comments in one call
listIssueComments List comments on an issue (paginated; prefer getIssueContext for the first page)
createIssue Open a new issue, optionally in a milestone
addIssueComment Post a comment on an issue
updateIssueComment Edit the body of an issue comment
deleteIssueComment Permanently delete an issue comment
closeIssue Close an issue (completed or not planned)
updateIssue Update an issue's title, body, labels, milestone, or assignees — set state: 'open' to reopen
listLabels List labels available in a repository
addLabels Add labels to an issue or pull request
removeLabel Remove a label from an issue or pull request
createLabel Create a label in a repository
updateLabel Update a label's name, color, or description
deleteLabel Delete a label from a repository permanently
addAssignees Assign users to an issue or pull request
removeAssignees Remove assignees from an issue or pull request
listMilestones List milestones with their due dates and open and closed issue counts
listSubIssues List the sub-issues of an issue
addSubIssue Add an existing issue as a sub-issue, from the same repository or another one with the same owner

Reactions

Pull request conversations share the issue numbering, so the issue-level tools work on PRs too.

Tool Description
listIssueReactions List reactions on an issue or pull request, with per-emoji counts
addIssueReaction React to an issue or pull request (+1, -1, laugh, confused, heart, hooray, rocket, eyes)
listCommentReactions List reactions on an issue or pull request comment
addCommentReaction React to an issue or pull request comment

Discussions

Tool Description
listDiscussions List discussions, most recently updated first, optionally filtered by category name (cursor-paginated)
getDiscussion Get a discussion by number (body truncated by default; set detail: full for complete text)
addDiscussionComment Post a comment on a discussion

Notifications

Tool Description
listNotifications List notification threads for the authenticated user (unread only unless all: true)
markNotificationRead Mark a single notification thread as read

Gists

Tool Description
listGists List gists for the authenticated user or a specific user
getGist Get a gist including file contents
listGistComments List comments on a gist
createGist Create a new gist with one or more files
updateGist Update a gist's description or files
deleteGist Delete a gist permanently
createGistComment Post a comment on a gist

Workflows

Tool Description
listWorkflows List GitHub Actions workflows in a repository
listWorkflowRuns List workflow runs filtered by workflow, branch, status, or event
getWorkflowRun Get a workflow run's status, timing, and trigger info
listWorkflowJobs List jobs in a workflow run with step-level status
getWorkflowJobLogs Read a job's log output (last 200 lines by default, timestamps stripped)
triggerWorkflow Trigger a workflow via workflow_dispatch event
cancelWorkflowRun Cancel an in-progress workflow run
rerunWorkflowRun Re-run a workflow run, optionally only failed jobs

Checks and Statuses

Tool Description
listCheckRuns List check runs (Checks API: GitHub Actions and other CI providers) for a commit, branch, or tag
getCombinedStatus Get the combined commit status (Statuses API: legacy CI integrations) for a commit, branch, or tag
createCommitStatus Report a result on a commit as a commit status; works with a PAT or a GitHub App, unlike check runs
getCiFailureContext Diagnose CI failures for a ref or one workflow run: failing checks, failed jobs and steps, and the end of each failed job's log, in one call

Releases

Tool Description
listReleases List releases, newest first (includes drafts and prereleases)
getLatestRelease Get the latest published release (body truncated by default; set detail: full for complete notes)
getRelease Get a specific release by ID or tag, including its assets
getReleaseContext Fetch a release (latest, by ID, or by tag) plus the release before it and their tag comparison in one call
createRelease Create a new release (and its tag if needed)
updateRelease Update a release's tag, target, title, notes, draft, or prerelease status
deleteRelease Permanently delete a release (does not delete the underlying git tag)

Commits

Tool Description
listCommits List commits, optionally filtered by file path, author, or date range. When hasMore, pass nextPage
getCommit Get a commit's full details including changed files and diffs
getBlame Line-level git blame for a file (GitHub GraphQL)
compareCommits Compare two branches, tags, or commits: ahead/behind counts, commits in between, and files that differ

Search

Tool Description
searchCode Search code across GitHub with qualifier support (includes matching text snippets when available)
searchRepositories Search repositories by keyword, topic, language, stars, …
searchIssues Search issues and pull requests using qualifiers like is:open, type:pr, or label:bug

Security alerts

Tool Description
listCodeScanningAlerts List code scanning alerts with the rule, severity and location
listDependabotAlerts List Dependabot alerts with the advisory and first patched version (cursor pages: pass nextCursor as after)
listSecretScanningAlerts List secret scanning alerts; the secret itself is never returned

GitHub Token

All tools authenticate with a GitHub personal access token (PAT).

Fine-grained token (recommended)

Create one at GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens.

Permission Level Required for
Metadata Read-only Always required (auto-included); the only permission getCollaboratorPermission needs
Contents Read-only getRepository, listBranches, getBranchRules, getFileContent, getRepositoryTree, listCommits, getCommit, getBlame, compareCommits, listReleases, getLatestRelease, getRelease, getReleaseContext
Contents Read and write createBranch, deleteBranch, createOrUpdateFile, editFiles, createRelease, updateRelease, deleteRelease
Administration Read and write forkRepository, createRepository
Pull requests Read-only listPullRequests, getPullRequest, listPullRequestFiles, listPullRequestReviews, listPullRequestReviewThreads, getPullRequestContext
Pull requests Read and write createPullRequest, editFiles (with pullRequest), mergePullRequest, enablePullRequestAutoMerge, disablePullRequestAutoMerge, updatePullRequest, updatePullRequestBranch, addPullRequestComment, updatePullRequestComment, deletePullRequestComment, createPullRequestReview, replyToReviewComment, resolveReviewThread, requestReviewers
Issues Read-only listIssues, getIssue, getIssueContext, listIssueComments, listLabels, listMilestones, listSubIssues, listIssueReactions, listCommentReactions
Issues Read and write createIssue, addIssueComment, updateIssueComment, deleteIssueComment, closeIssue, updateIssue, addLabels, removeLabel, createLabel, updateLabel, deleteLabel, addAssignees, removeAssignees, addSubIssue, addIssueReaction, addCommentReaction
Discussions Read-only listDiscussions, getDiscussion
Discussions Read and write addDiscussionComment
Gists Read-only listGists, getGist, listGistComments
Gists Read and write createGist, updateGist, deleteGist, createGistComment
Notifications (account) Read and write listNotifications, markNotificationRead
Actions Read-only listWorkflows, listWorkflowRuns, getWorkflowRun, listWorkflowJobs, getWorkflowJobLogs, getCiFailureContext
Actions Read and write triggerWorkflow, cancelWorkflowRun, rerunWorkflowRun
Checks Read-only listCheckRuns, getCiFailureContext
Commit statuses Read-only getCombinedStatus, getCiFailureContext
Commit statuses Read and write createCommitStatus
Code scanning alerts Read-only listCodeScanningAlerts
Dependabot alerts Read-only listDependabotAlerts
Secret scanning alerts Read-only listSecretScanningAlerts

Search tools (searchCode, searchRepositories, searchIssues) work with any token.

Classic token

Scope Required for
public_repo All tools on public repositories
repo All tools on public and private repositories, except the security alert tools
security_events listCodeScanningAlerts, listDependabotAlerts, listSecretScanningAlerts

API

createGithubTools(options)

Returns an object of tools, ready to spread into tools of any AI SDK call.

type GithubToolsOptions = {
  token?: GithubTokenInput // defaults to process.env.GITHUB_TOKEN
  requireApproval?: boolean | Partial<Record<GithubWriteToolName, boolean>>
  preset?: GithubToolPreset | GithubToolPreset[]
  context?: GithubToolsContext // default owner / repo / PR / issue / ref
  guardrails?: { repositories?: string[], branches?: string[] } // where any call may act
  dryRun?: boolean // shadow mode: reads run, writes don't reach GitHub or ask anyone
}

type GithubTokenInput = string | (() => Promise<string>)

type GithubToolPreset = 'code-review' | 'issue-triage' | 'repo-explorer' | 'ci-ops' | 'security-audit' | 'release-manager' | 'discussion-moderator' | 'notification-inbox' | 'pr-author' | 'maintainer'

createGithubAgent(options)

Returns a ToolLoopAgent instance with .generate() and .stream() methods, pre-configured with GitHub tools and tailored instructions.

import { createGithubAgent } from '@github-tools/sdk'

// Prefer a preset: scoped tools + tailored prompt
const reviewer = createGithubAgent({
  model: 'anthropic/claude-opus-5.5',
  token: process.env.GITHUB_TOKEN!,
  preset: 'code-review',
  context: { owner: 'vercel', repo: 'ai', pullNumber: 42 },
})

// Add context to the built-in prompt
const triager = createGithubAgent({
  model: 'anthropic/claude-opus-5.5',
  token: process.env.GITHUB_TOKEN!,
  preset: 'issue-triage',
  additionalInstructions: 'Focus on the nuxt/ui repository. Always respond in French.',
})

// Full catalog (omit preset or use maintainer)
const agent = createGithubAgent({
  model: 'anthropic/claude-opus-5.5',
  token: process.env.GITHUB_TOKEN!,
  preset: 'maintainer',
})

// Full override: replace the built-in prompt entirely
const custom = createGithubAgent({
  model: 'anthropic/claude-opus-5.5',
  token: process.env.GITHUB_TOKEN!,
  instructions: 'You are a security auditor. Only flag security-related issues.',
})

// Use the agent
const result = await reviewer.generate({ prompt: 'Review this PR' })
const stream = await reviewer.stream({ prompt: 'Review this PR' })
Option Description
model Language model: string ('anthropic/claude-opus-5.5') or provider instance
token GitHub token string or async provider
preset Optional preset or array of presets to scope tools
context Default owner / repo / pullNumber / issueNumber / ref for tools and the system prompt
requireApproval Approval config (same as createGithubTools)
instructions Replaces the built-in system prompt entirely (context is still appended)
additionalInstructions Appended to the built-in system prompt

All other ToolLoopAgent options (stopWhen, toolChoice, onStepFinish, etc.) are passed through.

createDurableGithubAgent(options)

Returns a DurableGithubAgent instance for use inside Vercel Workflow SDK functions. Every LLM call and tool execution runs as a durable step with automatic retries and crash recovery.

Supports both .stream() (real-time output to a writable) and .generate() (non-streaming, returns the full text response).

Requires the optional peer dependencies workflow and @ai-sdk/workflow:

pnpm add workflow @ai-sdk/workflow

Streaming (chat UI)

// durable-chat.workflow.ts
import { createDurableGithubAgent } from '@github-tools/sdk/workflow'
import { getWritable } from 'workflow'
import type { ModelMessage, UIMessageChunk } from 'ai'

async function chatWorkflow(messages: ModelMessage[], token: string) {
  "use workflow"
  const agent = createDurableGithubAgent({
    model: 'anthropic/claude-opus-5.5',
    token,
    preset: 'code-review',
  })
  const writable = getWritable<UIMessageChunk>()
  await agent.stream({ messages, writable })
}

Non-streaming (bot / background job)

Call .generate() from the workflow function. Each model call and tool call is its own durable step. It needs @ai-sdk/workflow 2.0.59 or later. Return plain fields, since the result itself isn't serializable:

// review.workflow.ts
import { createDurableGithubAgent } from '@github-tools/sdk/workflow'
import type { ModelMessage } from 'ai'

async function reviewWorkflow(messages: ModelMessage[], token: string) {
  "use workflow"
  const agent = createDurableGithubAgent({ model: 'anthropic/claude-opus-5.5', token, preset: 'code-review' })
  const result = await agent.generate({ messages })
  return { text: result.text, responseMessages: result.responseMessages }
}

To run the whole loop as one step instead, call createGithubAgent inside a "use step" function:

// agent-turn.step.ts
import { createGithubAgent } from '@github-tools/sdk'

async function agentTurn(prompt: string) {
  "use step"
  const agent = createGithubAgent({
    model: 'anthropic/claude-opus-5.5',
    preset: 'code-review',
    requireApproval: false,
  })
  const { text } = await agent.generate({ prompt })
  return text
}

See examples/pr-review-agent for a complete PR review agent built with Chat SDK and Vercel Workflow.

All presets (code-review, issue-triage, ci-ops, repo-explorer, security-audit, release-manager, discussion-moderator, notification-inbox, pr-author, maintainer) work with createDurableGithubAgent. Options mirror createGithubAgent with additional pass-through for WorkflowAgentOptions fields like telemetry, onStepEnd, onEnd, and prepareStep. Write tools honor requireApproval via needsApproval.

resolveGithubToken(token?)

Resolves a GithubTokenInput (token string, async provider, or process.env.GITHUB_TOKEN) to a token string. Throws when no token is available.

createOctokit(token)

Returns a configured octokit instance. Useful for building custom tools.

License

MIT

Made by @HugoRCD

About

GitHub tools and agents for the Vercel AI SDK, wrap GitHub's API as AI SDK tools ready to plug into any agent

Topics

Resources

Contributing

Stars

139 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages