Api
Type signatures for createGithubTools, createGithubAgent, createDurableGithubAgent, and createOctokit.

Migrate Octokit calls to AI SDK tools

createGithubTools(options?)

Returns a record of AI SDK tools you can pass to generateText or streamText. All options are optional, the SDK reads GITHUB_TOKEN from your environment by default:

types.ts
type GithubToolsOptions = {
  token?: GithubTokenInput
  requireApproval?: ToolApprovalMode | Partial<Record<GithubWriteToolName, ToolApprovalMode>>
  evaluation?: GithubEvaluationOptions
  overrides?: Partial<Record<string, ToolOverrides>>
  preset?: GithubToolPreset | GithubToolPreset[]
  author?: CommitIdentity
  committer?: CommitIdentity
  coAuthors?: CommitIdentity[]
}

type ToolApprovalMode = boolean | 'auto'

// Tuning for 'auto' approval and preset: 'auto'. Every field is optional.
type GithubEvaluationOptions = {
  model?: Experimental_EvaluationModel // default 'typesafe-ai/jev'
  maxRisk?: number // default 1, on a 0–2 scale
  minIntent?: number // default 0.6
  minPresetProbability?: number // default 0.7
  maxPresets?: number // default 2
}

// Providers receive the tool call the token is requested for (undefined outside a tool call).
type GithubTokenInput = string | ((call?: GithubTokenCall) => Promise<string>)

type GithubTokenCall = {
  toolName: GithubToolName
  input: unknown // after context defaults
  owner?: string // undefined for tools without a repository target
  repo?: string
}

type CommitIdentity = {
  name: string
  email: string
}

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

Minimal usage, reads GITHUB_TOKEN automatically:

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

const tools = createGithubTools()

With a preset and explicit token:

with-options.ts
import { createGithubTools } from '@github-tools/sdk'

const tools = createGithubTools({
  token: 'github_pat_xxxxxxxxxxxx',
  preset: 'repo-explorer',
})

See Scope with presets for preset details and Control write safety for approval options.

Working context

Pass context to default owner / repo / pullNumber / issueNumber / ref on tool inputs. Matching schema fields become optional and fill from context when omitted. Agents also get a short system-prompt block describing the context:

context.ts
import { createGithubTools, createGithubAgent } from '@github-tools/sdk'

const tools = createGithubTools({
  preset: 'code-review',
  context: { owner: 'vercel', repo: 'ai', pullNumber: 42 },
})

const agent = createGithubAgent({
  model: 'anthropic/claude-opus-5.5',
  preset: 'code-review',
  context: { owner: 'vercel', repo: 'ai', pullNumber: 42 },
})

listPullRequestFiles, getCommit, and compareCommits omit diff patches by default (includePatch: false). Set includePatch: true — optionally with filenames on listPullRequestFiles — to fetch targeted diffs.

getPullRequest, getIssue, and release getters truncate bodies by default (detail: 'summary'). Pass detail: 'full' for the complete text. getIssueContext defaults to detail: 'full' (one-shot) and returns labelNames rather than full label objects.

Prefer composite tools (getPullRequestContext, getIssueContext, getReleaseContext, getCiFailureContext) for multi-part reads. Prefer getFileContent with startLine/endLine or maxLines for large files.

Tool overrides

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

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

const tools = createGithubTools({
  overrides: {
    deleteGist: { needsApproval: false },
    listIssues: { description: 'List bugs for the current sprint' },
  },
})
type.ts
import type { ToolOverrides } from '@github-tools/sdk'

Supported override properties:

PropertyTypeDescription
descriptionstringCustom tool description for the model
titlestringHuman-readable title
strictbooleanStrict mode for input generation
needsApprovalboolean | functionGate execution behind approval
providerOptionsProviderOptionsProvider-specific metadata
onInputStartfunctionCallback when argument streaming starts
onInputDeltafunctionCallback on each streaming delta
onInputAvailablefunctionCallback when full input is available
toModelOutputfunctionCustom 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 (x-ratelimit-remaining, x-ratelimit-limit, x-ratelimit-reset, x-ratelimit-resource, and retry-after when present). REST list tools now return objects ({ items, hasMore, … } or keyed collections), so they carry rateLimit too. The field is stripped before the model sees the output (toModelOutput); hooks, channels, and the chat UI still receive it.

rate-limit.ts
import type { GithubRateLimit } from '@github-tools/sdk'

const remaining = (result as { rateLimit?: GithubRateLimit }).rateLimit?.remaining

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

Commit attribution

The author, committer, and coAuthors options control how commits are attributed when using createOrUpdateFile or mergePullRequest:

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

const tools = createGithubTools({
  token: 'github_pat_xxxxxxxxxxxx',
  coAuthors: [
    { name: 'my-bot[bot]', email: '12345+my-bot[bot]@users.noreply.github.com' }
  ]
})
OptionTypeDescription
authorCommitIdentityThe person who wrote the code. Falls back to the authenticated user.
committerCommitIdentityThe person who applied the commit. Falls back to the authenticated user.
coAuthorsCommitIdentity[]Additional contributors. Added as Co-authored-by trailers to commit messages.

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

See Commit attribution for detailed guidance.

createGithubAgent(options)

Returns a ToolLoopAgent with GitHub tools and system instructions pre-configured. The token is also auto-detected from GITHUB_TOKEN:

types.ts
type GithubAgentOptions = {
  model: string
  token?: GithubTokenInput
  preset?: GithubToolPreset | GithubToolPreset[] | 'auto'
  requireApproval?: ToolApprovalMode | Partial<Record<GithubWriteToolName, ToolApprovalMode>>
  evaluation?: GithubEvaluationOptions
  system?: string
  author?: CommitIdentity
  committer?: CommitIdentity
  coAuthors?: CommitIdentity[]
}

Use this when you want:

  • reusable .generate() / .stream() calls across multiple prompts
  • preset-aware system instructions without manual wiring
  • a centralized agent definition shared across your codebase

preset: 'auto' selects presets per call from the latest user message, and requireApproval: 'auto' skips approval for low-risk writes the user asked for. See Let the agent pick presets and Auto approval.

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

const agent = createGithubAgent({
  model: 'anthropic/claude-opus-5.5',
  preset: 'code-review',
  system: 'You review PRs for security issues. Cite file paths and line numbers.',
})

createDurableGithubAgent(options)

Returns a WorkflowAgent for use inside a Vercel Workflow function ("use workflow"). Each LLM step and each GitHub tool invocation runs as a durable, retryable workflow step. Import from the workflow subpath:

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

Requires optional peer dependencies workflow and @ai-sdk/workflow, see Installation.

Options align with createGithubAgent (model, token, preset, requireApproval, instructions, additionalInstructions, stopWhen, temperature, and other agent options passed through). Write tools honor requireApproval via needsApproval: the workflow pauses until the user approves or denies.

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

export async function githubAssistant(messages: ModelMessage[], token: string) {
  'use workflow'

  const agent = createDurableGithubAgent({
    model: 'anthropic/claude-opus-5.5',
    token,
    preset: 'maintainer',
    requireApproval: true,
  })
  const writable = getWritable<ModelCallStreamPart>()
  await agent.stream({ messages, writable })
}

Conceptual overview: Durable workflows (Vercel Workflow).

githubExtension(options): eve extension

The recommended way to add GitHub tools to an eve agent. From @github-tools/eve-extension, mounted under agent/extensions/:

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

export default githubExtension({
  preset: 'code-review',
  requireApproval: {
    mergePullRequest: true,
    createIssue: 'once',
  },
})

options mirrors EveGithubToolsOptions below (token, connector, connect, preset, include, exclude, requireApproval, overrides, author/committer/coAuthors). Full config table and Connect setup: eve extension guide. Package README: packages/github-tools-eve-extension.

createGithubTools(options) : eve (deprecated)

Deprecated. Use githubExtension from @github-tools/eve-extension instead. This direct import keeps working but is no longer the recommended path. Runtime helpers for the extension are on @github-tools/sdk/eve-runtime (not deprecated).

Returns a defineDynamic sentinel for eve's agent/tools/ directory. Import from @github-tools/sdk/eve:

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

Requires optional peer dependencies eve and ai v7, see Installation and eve (direct import).

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

export default createGithubTools({
  preset: 'code-review',
  requireApproval: {
    mergePullRequest: true,
    createIssue: 'once',
    addPullRequestComment: false,
  },
})

@github-tools/sdk/eve-runtime

Shared eve primitives for @github-tools/eve-extension and advanced integrations: tool descriptors, executeGithubEveTool, formatGithubEveToolOutput / hasGithubEveToolModelOutput (built-in toModelOutput lookup by tool name), approval helpers (mapEveApprovalValue, resolveEveApproval), and related types. Not deprecated — this is the supported low-level surface the extension imports. Prefer the extension mount for agents; use this subpath only when building on top of the same runtime.

import-eve-runtime.ts
import {
  listEveToolDescriptors,
  executeGithubEveTool,
  formatGithubEveToolOutput,
  hasGithubEveToolModelOutput,
  mapEveApprovalValue,
  resolveEveApproval,
} from '@github-tools/sdk/eve-runtime'
types-eve.ts
type EveGithubToolsOptions = {
  token?: GithubTokenInput
  preset?: GithubToolPreset | GithubToolPreset[]
  include?: GithubToolName[]
  exclude?: GithubToolName[]
  requireApproval?: boolean | Partial<Record<GithubWriteToolName, EveApprovalValue>>
  overrides?: EveToolOverrides
  author?: CommitIdentity
  committer?: CommitIdentity
  coAuthors?: CommitIdentity[]
}

type EveApprovalValue =
  | boolean
  | 'always'
  | 'once'
  | 'never'
  | Approval // from eve/tools

include is a set of tool names. Pass it alone to hand-pick an exact set, or alongside preset to add tools the preset is missing (the effective set is the union of both). exclude removes tool names from that resolved preset + include set, use it to drop a couple of tools from a larger preset. Also exports individual eve tool factories (listPullRequests(), createIssue(), …) for one-tool-per-file layouts. Approval supports once, predicates, and eve helper passthrough. Unlike the Workflow subpath, approval is enforced at runtime.

connectGithubTools(connector, options?)

Import from @github-tools/sdk/connect. Returns the same tool record as createGithubTools, backed by a Vercel Connect connector. connector is a GithubConnectorInput: a name string or a () => string | Promise<string> resolver, re-resolved on every call (e.g. to pick a connector per environment or tenant). Scopes are derived from preset unless overridden in connect.scopes:

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

const tools = connectGithubTools('github/my-connector', {
  preset: 'code-review',
  connect: {
    installationId: 'inst_abc',
    repositories: ['my-org/my-repo'],
  },
})
types-connect.ts
type ConnectGithubToolsOptions = GithubToolsOptions & {
  connect?: GithubConnectParams | GithubConnectParamsResolver
}

type GithubConnectParams = Omit<ConnectTokenParams, 'subject'> & {
  subject?: ConnectTokenSubject
  repositories?: string[]
}

type GithubConnectParamsResolver = (call?: GithubTokenCall) => GithubConnectParams | Promise<GithubConnectParams>

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

subject defaults to { type: 'app' } (the project's GitHub App installation). Pass { type: 'user', id } to mint a token for that user's own connection — see per-user tokens. See the Vercel Connect guide for the dynamic connector example.

App-subject tokens target the GitHub App installation that owns the call's repository: when the call has owner / repo and the params set none of installationId, authorizationDetails or repositories, authorizationDetails: [{ type: 'github_app_installation', org: owner, repositories: [repo] }] is added. See One App installed on several accounts. A connect resolver runs on every tool call with its GithubTokenCall for other per-call rules. Scopes still derive from preset unless the resolved params set scopes.

connectGithubTools(connector, options?): eve (deprecated)

Deprecated. For the eve extension, pass connector directly to githubExtension instead; no separate Connect import is needed.

Import from @github-tools/sdk/connect/eve. Same as the AI SDK variant but returns a defineDynamic sentinel. Set build.externalDependencies: ['@vercel/connect'] in agent.ts until eve externalizes transitive Connect imports from workspace-linked packages (TODO(eve-connect-bundle)).

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

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

connectGithubToken(connector, options?)

Returns a lazy GithubTokenInput backed by getToken. connector accepts the same GithubConnectorInput (name or resolver function) as connectGithubTools. Use with createGithubTools when you only need the token provider:

connect-token-provider.ts
import { connectGithubToken } from '@github-tools/sdk/connect'
import { createGithubTools } from '@github-tools/sdk'

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

Pass the same preset (and the same include / exclude, when you use them) to connectGithubToken: it derives Connect scopes independently of the selection given to createGithubTools. With include alone, scopes follow the selected tools rather than the full preset union.

connectGithubScopesForPreset(preset?)

Returns Vercel Connect scope strings for a preset or combined presets. Without a preset, returns the union of all preset scopes.

connectGithubScopesForSelection({ preset?, include?, exclude? })

Same mapping as connectGithubToken uses when params.scopes is omitted. With no include / exclude, identical to connectGithubScopesForPreset. When either is set, scopes are derived from the resolved tool names via connectGithubScopesForTools.

connectGithubScopesForTools(names)

Returns the Connect scopes covering exactly the given tool names. Always includes metadata:read. Gist and notification tools contribute no scopes (installation tokens cannot call those APIs).

resolveGithubToken(token?)

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

createOctokit(token?)

Returns a configured @octokit/rest instance. Use this when you need lower-level GitHub API access or want to build custom tool factories:

custom-tool.ts
import { createOctokit, resolveGithubToken } from '@github-tools/sdk'

const octokit = createOctokit(await resolveGithubToken())
const { data } = await octokit.repos.get({ owner: 'HugoRCD', repo: 'github-tools' })

githubToolsErrors

The evlog error catalog behind every classifiable SDK failure (github_tools.* codes with why/fix fields). Exported from @github-tools/sdk and @github-tools/sdk/eve-runtime for consumers who want to match on specific codes or throw catalog errors from custom tools. See the errors guide for the full code list and the model-facing shape.

error-handling.ts
import { githubToolsErrors } from '@github-tools/sdk'
import { parseError } from 'evlog'

const { code, why, fix } = parseError(error)
if (code === 'github_tools.RATE_LIMITED') { /* back off */ }

TanStack AI

Import these APIs from @github-tools/sdk/tanstack. See the TanStack AI guide for installation and complete examples.

createGithubTools(options?)

Returns a native TanStack server-tool array. Accepts token, explicit or composed preset, context, requireApproval, author, committer, coAuthors, and per-tool overrides. Overrides support description and boolean needsApproval; execution and schemas are fixed. Named tool factories accept a token, with approval options on write factories.

Static approval uses TanStack's native flow. For requireApproval: 'auto', add the middleware below. The tool array alone keeps those writes approval-required.

createGithubAgent(options)

Accepts the tool options above, plus:

OptionBehavior
adapterRequired TanStack chat adapter
presetA preset, preset array, or 'auto' for routing new invocations
evaluationTanStack evaluation adapter and shared thresholds
instructionsReplaces the preset system prompt
additionalInstructionsAppends to the preset prompt; ignored when instructions is set
modelOptionsProvider-specific model settings
agentLoopStrategyTanStack loop strategy; defaults to TanStack's limit

agent.generate({ prompt }) returns Promise<string> and throws when the run ends on an interrupt. agent.stream({ prompt }) returns the native TanStack event stream. Use stream() for approval UIs. Both accept messages instead of prompt, and TanStack call options such as threadId, runId, parentRunId, resume, and abortController. Supply conversation history on each call; the agent does not retain it. Auto-preset continuations skip routing and expose repo-explorer plus pending GitHub tools.

createGithubApprovalMiddleware({ tools, evaluation? })

Returns TanStack middleware for auto approval. Pass the same tools array to the middleware and chat(), and register githubToolApproval in chat({ interrupts }). The prebuilt agent does this automatically.

evaluation accepts a TanStack adapter and the shared maxRisk, minIntent, minPresetProbability, and maxPresets thresholds. The default adapter is vercelGatewayDecider('typesafe-ai/jev'); Gateway is optional when a custom adapter is supplied.

githubToolApproval

Import this shared interrupt definition from @github-tools/sdk/tanstack/interrupts, including in browser code. Register it on the client to handle auto calls that need human review. Its payload contains toolCallId, toolName, and resolved input; its response is { approved: boolean }. Continue using TanStack's message history and resume data. Decisions apply only to the reviewed call and arguments.

External references