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, Vercel Workflow, and Chat SDK.
Docs: github-tools.com
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 tool() objects |
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 | Every call is a "use step" |
No | No | No |
| Scoped by task | Presets (7 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 |
| 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 |
| Production agents that must survive restarts and timeouts | Durable Agents |
| A GitHub, Slack, or Discord bot | Chat SDK docs |
79 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.
pnpm add @github-tools/sdkai and zod are peer dependencies (ai v6 or v7; the eve subpath requires v7):
pnpm add ai zod// 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.',
})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, getPullRequestContext, getFileContent, listCommits, getCommit, getBlame, compareCommits, getRepository, listBranches, searchCode, listCheckRuns, getCombinedStatus, updatePullRequest, addPullRequestComment, updatePullRequestComment, deletePullRequestComment, createPullRequestReview, requestReviewers |
issue-triage |
listIssues, getIssueContext, listIssueComments, createIssue, addIssueComment, updateIssueComment, deleteIssueComment, closeIssue, updateIssue, addLabels, removeLabel, createLabel, updateLabel, deleteLabel, addAssignees, removeAssignees, listIssueReactions, addIssueReaction, listCommentReactions, addCommentReaction, getRepository, searchRepositories, searchCode, searchIssues |
repo-explorer |
All read-only tools including discussions, gists, workflows, checks/statuses, and releases (no write operations) |
ci-ops |
listWorkflows, listWorkflowRuns, getWorkflowRun, listWorkflowJobs, listCheckRuns, getCombinedStatus, getCiFailureContext, triggerWorkflow, cancelWorkflowRun, rerunWorkflowRun, getRepository, listBranches, listCommits, getCommit |
security-audit |
Read-only exploration (getFileContent, getRepositoryTree, searchCode, listCommits, getCommit, getBlame, compareCommits), PR and CI visibility, plus createIssue, addIssueComment, addLabels to report findings (no destructive writes) |
release-manager |
listReleases, getLatestRelease, getRelease, getReleaseContext, createRelease, updateRelease, deleteRelease, compareCommits, listCommits, getCommit, listWorkflowRuns, getWorkflowRun, listPullRequests, getPullRequest, getRepository, listBranches |
discussion-moderator |
listDiscussions, getDiscussion, addDiscussionComment, getRepository, searchIssues, getIssueContext, addIssueComment |
notification-inbox |
listNotifications, markNotificationRead, getIssue, getPullRequest, getRepository (requires a Notifications PAT) |
pr-author |
getRepository, listBranches, getFileContent, createBranch, createOrUpdateFile, createPullRequest, updatePullRequest, getPullRequest, listPullRequestFiles, compareCommits, getCommit |
maintainer |
All 79 tools |
Start with the smallest preset that fits. Use maintainer or omit preset when you need the full catalog. Full breakdown: Tools Catalog.
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.
Write operations (creating issues, merging PRs, pushing files, …) require user approval by default. This is designed for human-in-the-loop agent workflows.
// All writes need approval (default)
createGithubTools({ token })
// No approval needed
createGithubTools({ token, requireApproval: false })
// 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, forkRepository, createRepository, createOrUpdateFile, createPullRequest, mergePullRequest, updatePullRequest, addPullRequestComment, updatePullRequestComment, deletePullRequestComment, createPullRequestReview, requestReviewers, createIssue, addIssueComment, updateIssueComment, deleteIssueComment, closeIssue, updateIssue, addLabels, removeLabel, createLabel, updateLabel, deleteLabel, addAssignees, removeAssignees, addIssueReaction, addCommentReaction, addDiscussionComment, markNotificationRead, createGist, updateGist, deleteGist, createGistComment, triggerWorkflow, cancelWorkflowRun, rerunWorkflowRun, createRelease, updateRelease, deleteRelease.
All other tools are read-only and never require approval.
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.
Control how commits are attributed when using createOrUpdateFile 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.
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: openai('gpt-4o'),
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.
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-sonnet-4.6',
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.
workflowand@ai-sdk/workfloware optional peer dependencies, install them only when using the workflow subpath.
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/connectimport { 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'],
},
})
@vercel/connectis an optional peer dependency, install it only when using the/connectsubpath.
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' },
)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).
pnpm add @github-tools/eve-extension eveeve 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-extension-agent for the full package README and a runnable agent.
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 zodeve 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.
| 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.
// agent/tools/list_pull_requests.ts
import { listPullRequests } from '@github-tools/sdk/eve'
export default listPullRequests()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) |
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 |
Not idempotent: deleting an already-deleted resource returns 404 from 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.
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.
eveis an optional peer dependency, install it only when using the/evesubpath.
See examples/eve-agent for a minimal agent.
List tools (listCommits, listPullRequests, listIssues, listWorkflowRuns, listCheckRuns, listReleases) accept an optional maxPages alongside perPage. Set it to sequentially fetch and combine up to that many pages in one call, stopping early once a page comes back short.
| Tool | Description |
|---|---|
getRepository |
Get repository metadata (stars, language, default branch, …) |
listBranches |
List branches |
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 |
createBranch |
Create a new branch from an existing branch or commit SHA |
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 |
| 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) |
getPullRequestContext |
Fetch PR details plus files, reviews, and optional CI checks in one call |
createPullRequest |
Open a new PR |
mergePullRequest |
Merge a PR (merge, squash, or rebase) |
updatePullRequest |
Update a PR's title, body, state, base branch, or draft status |
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 |
requestReviewers |
Request reviews from users or teams on a PR |
| 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 |
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 |
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 |
| 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 |
| Tool | Description |
|---|---|
listNotifications |
List notification threads for the authenticated user (unread only unless all: true) |
markNotificationRead |
Mark a single notification thread as read |
| 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 |
| 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 |
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 |
| 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 |
getCiFailureContext |
Diagnose CI failures for a ref — combined status, failing checks, and failed workflow jobs in one call |
| 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, including its assets |
getReleaseContext |
Fetch a release plus the previous release and 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) |
| Tool | Description |
|---|---|
listCommits |
List commits, optionally filtered by file path, author, or date range |
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 |
| 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 |
All tools authenticate with a GitHub personal access token (PAT).
Create one at GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens.
| Permission | Level | Required for |
|---|---|---|
| Metadata | Read-only | Always required (auto-included) |
| Contents | Read-only | getRepository, listBranches, getFileContent, getRepositoryTree, listCommits, getCommit, getBlame, compareCommits, listReleases, getLatestRelease, getRelease, getReleaseContext |
| Contents | Read and write | createBranch, createOrUpdateFile, createRelease, updateRelease, deleteRelease |
| Administration | Read and write | forkRepository, createRepository |
| Pull requests | Read-only | listPullRequests, getPullRequest, listPullRequestFiles, listPullRequestReviews, getPullRequestContext |
| Pull requests | Read and write | createPullRequest, mergePullRequest, updatePullRequest, addPullRequestComment, updatePullRequestComment, deletePullRequestComment, createPullRequestReview, requestReviewers |
| Issues | Read-only | listIssues, getIssue, getIssueContext, listIssueComments, listLabels, listIssueReactions, listCommentReactions |
| Issues | Read and write | createIssue, addIssueComment, updateIssueComment, deleteIssueComment, closeIssue, updateIssue, addLabels, removeLabel, createLabel, updateLabel, deleteLabel, addAssignees, removeAssignees, 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, getCiFailureContext |
| Actions | Read and write | triggerWorkflow, cancelWorkflowRun, rerunWorkflowRun |
| Checks | Read-only | listCheckRuns, getCiFailureContext |
| Commit statuses | Read-only | getCombinedStatus, getCiFailureContext |
Search tools (searchCode, searchRepositories, searchIssues) work with any token.
| Scope | Required for |
|---|---|
public_repo |
All tools on public repositories |
repo |
All tools on public and private repositories |
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
}
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'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-sonnet-4.6',
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-sonnet-4.6',
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-sonnet-4.6',
token: process.env.GITHUB_TOKEN!,
preset: 'maintainer',
})
// Full override: replace the built-in prompt entirely
const custom = createGithubAgent({
model: 'anthropic/claude-sonnet-4.6',
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 = reviewer.stream({ prompt: 'Review this PR' })| Option | Description |
|---|---|
model |
Language model: string ('anthropic/claude-sonnet-4.6') 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.
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 @workflow/ai:
pnpm add workflow @workflow/ai// 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-sonnet-4.6',
token,
preset: 'code-review',
})
const writable = getWritable<UIMessageChunk>()
await agent.stream({ messages, writable })
}// agent-turn.step.ts
import { createGithubAgent } from '@github-tools/sdk'
async function agentTurn(prompt: string) {
"use step"
const agent = createGithubAgent({
model: 'anthropic/claude-sonnet-4.6',
preset: 'code-review',
requireApproval: false,
})
const { text } = await agent.generate({ prompt })
return text
}See
examples/pr-review-agentfor 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 experimental_telemetry, onStepEnd, onEnd, and prepareStep. Write tools honor requireApproval via needsApproval.
Resolves a GithubTokenInput (token string, async provider, or process.env.GITHUB_TOKEN) to a token string. Throws when no token is available.
Returns a configured octokit instance. Useful for building custom tools.
Made by @HugoRCD
