TanStack AI
Import from @github-tools/sdk/tanstack to use GitHub tools with TanStack AI. The entry point exports native server-tool arrays, individual tool factories, and a prebuilt agent with generate() and stream().
Install
These examples use Vercel AI Gateway for chat and Jev evaluation:
pnpm add @github-tools/sdk @tanstack/ai@0.64 @tanstack/ai-vercel-gateway@0.3 ai zod
npm install @github-tools/sdk @tanstack/ai@0.64 @tanstack/ai-vercel-gateway@0.3 ai zod
yarn add @github-tools/sdk @tanstack/ai@0.64 @tanstack/ai-vercel-gateway@0.3 ai zod
bun add @github-tools/sdk @tanstack/ai@0.64 @tanstack/ai-vercel-gateway@0.3 ai zod
The SDK retains ai and zod as package peers. The TanStack entry point uses TanStack's execution loop. @tanstack/ai-vercel-gateway is optional when you supply another chat adapter and, for auto modes, your own evaluation.adapter.
Set GITHUB_TOKEN on the server with the permissions your tools need. For Gateway, set AI_GATEWAY_API_KEY or use Vercel OIDC authentication. Enable typesafe-ai/jev for auto evaluation. Keep these credentials on the server.
Use the prebuilt agent
import { createGithubAgent } from '@github-tools/sdk/tanstack'
import { vercelGatewayText } from '@tanstack/ai-vercel-gateway'
const agent = createGithubAgent({
adapter: vercelGatewayText('anthropic/claude-opus-5'),
preset: 'repo-explorer',
context: { owner: 'vercel', repo: 'ai' },
})
const text = await agent.generate({
prompt: 'Summarize the open pull requests.',
})
console.log(text)
generate() returns a string and throws if the run requires human review. stream() returns TanStack's native event stream, which you can pass to its transport helpers:
import { toServerSentEventsResponse } from '@tanstack/ai'
// Use the agent defined above in your server route.
const response = toServerSentEventsResponse(agent.stream({
prompt: 'Summarize the open pull requests.',
}))
Use messages instead of prompt for conversation history. The agent keeps no conversation state between calls. Pass TanStack continuation fields, including threadId, runId, parentRunId, and resume, with the message history when resuming an interrupted call. Pass an abortController to cancel a call.
Presets, working context, token providers, and commit attribution follow the shared SDK options. Set instructions to replace the preset prompt or additionalInstructions to append guidance to the preset prompt. When instructions is supplied, additionalInstructions is ignored. Pass provider settings through modelOptions and a TanStack loop strategy through agentLoopStrategy.
Use tools in an existing chat
import { chat } from '@tanstack/ai'
import { vercelGatewayText } from '@tanstack/ai-vercel-gateway'
import { createGithubTools } from '@github-tools/sdk/tanstack'
const tools = createGithubTools({
preset: ['repo-explorer', 'code-review'],
context: { owner: 'vercel', repo: 'ai' },
})
const stream = chat({
adapter: vercelGatewayText('anthropic/claude-opus-5'),
tools,
messages: [{ role: 'user', content: 'Review pull request #42.' }],
})
Tools are an array, so combine them with other TanStack tools using [...tools, yourTool]. Each tool is also available as a named factory:
import { getRepository, addIssueComment } from '@github-tools/sdk/tanstack'
const tools = [
getRepository(process.env.GITHUB_TOKEN!),
addIssueComment(process.env.GITHUB_TOKEN!, { needsApproval: true }),
]
Writes require approval by default. Static boolean policies use TanStack's native tool approval flow. Set requireApproval globally or per tool, or use overrides to change a tool's description or needsApproval policy. Execution functions and schemas cannot be overridden.
Enable Jev auto modes
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',
})
The agent uses TanStack's decide() with vercelGatewayDecider('typesafe-ai/jev'). It selects presets from the latest user message once per new invocation and checks eligible writes before execution. The same risk, intent, and preset thresholds apply across integrations. Evaluation failures log a warning, require human approval for writes, and select repo-explorer for routing. Cancellation stops the call. When resume contains continuation data, auto routing is skipped: the agent exposes repo-explorer plus the GitHub tools named in pending calls.
Use evaluation.adapter to supply a TanStack evaluation adapter. The remaining evaluation options are maxRisk, minIntent, minPresetProbability, and maxPresets.
Direct tools with auto approval
When using chat() directly, install the approval middleware and register the shared interrupt definition:
import { chat } from '@tanstack/ai'
import { vercelGatewayText } from '@tanstack/ai-vercel-gateway'
import {
createGithubApprovalMiddleware,
createGithubTools,
} from '@github-tools/sdk/tanstack'
import { githubToolApproval } from '@github-tools/sdk/tanstack/interrupts'
const tools = createGithubTools({
preset: 'issue-triage',
requireApproval: 'auto',
context: { owner: 'vercel', repo: 'ai' },
})
const stream = chat({
adapter: vercelGatewayText('anthropic/claude-opus-5'),
tools,
middleware: [createGithubApprovalMiddleware({ tools })],
interrupts: [githubToolApproval],
messages: [{ role: 'user', content: 'Add the bug label to issue #42.' }],
})
Pass evaluation to createGithubApprovalMiddleware to customize its evaluator or thresholds. The prebuilt agent installs this middleware and server interrupt definition automatically. Without the middleware, auto tools still require approval.
Continue after human review
Use stream() for approval UIs: generate() throws when the run ends on an interrupt. Auto approval uses a generic GitHub interrupt when a call needs review. Register githubToolApproval in your TanStack client's interrupts array as well as on the server. Import it from the browser-safe @github-tools/sdk/tanstack/interrupts entry point.
The interrupt payload contains toolCallId, toolName, and the resolved input. Display that action to the user, then use TanStack's resolveInterrupt with { approved: true } or { approved: false }. Preserve the client-generated resume data and message history in the next server request. See TanStack's generic interrupt client flow for wiring the UI and transport.
Approval applies to the specific call and its arguments. Rejected calls return a denial result without executing the write. New calls or changed arguments require a new decision. Boolean approval policies continue to use TanStack's native tool-approval UI.
Forward TanStack's validated request fields to the agent on your server:
import { chatParamsFromRequestBody, toServerSentEventsResponse } from '@tanstack/ai'
// Use the auto agent defined above in your server route.
export async function POST(request: Request) {
const { messages, threadId, runId, parentRunId, resume } =
await chatParamsFromRequestBody(await request.json())
return toServerSentEventsResponse(agent.stream({
messages,
threadId,
runId,
parentRunId,
resume,
}))
}
Chat SDK
Connect GitHub tools to Chat SDK for durable GitHub, Slack, and Discord bots, a complete PR review agent in about 60 lines of code.
Overview
Complete, copy-pasteable GitHub agents for every framework, eve, the AI SDK, Vercel Workflow, and Chat SDK, plus a manager agent that delegates to scoped sub-agents.