Summarize open pull requests
This script lists every open PR on a repository and generates a one-line summary for each. It uses generateText with the default tool set:
import { createGithubTools } from '@github-tools/sdk'
import { generateText } from 'ai'
const { text } = await generateText({
model: 'anthropic/claude-sonnet-4.6',
tools: createGithubTools({
preset: 'code-review',
}),
prompt: 'List all open pull requests on vercel-labs/github-tools and write a one-line summary for each.',
})
console.log(text)
Triage incoming issues
This agent reads new issues, classifies them by priority, and posts a comment with the classification. It uses issue-triage with selective approval:
import { createGithubTools } from '@github-tools/sdk'
import { generateText } from 'ai'
const { text } = await generateText({
model: 'anthropic/claude-sonnet-4.6',
tools: createGithubTools({
preset: 'issue-triage',
requireApproval: {
addIssueComment: false,
closeIssue: true,
createIssue: true,
},
}),
prompt: `
Read all issues labeled "needs-triage" on vercel-labs/github-tools.
For each one, classify it as bug, feature, or question.
Post a comment with the classification and a suggested next step.
`,
})
Build a reusable review agent
When you need the same review behavior across multiple calls, use createGithubAgent to create a persistent agent with shared instructions:
import { createGithubAgent } from '@github-tools/sdk'
const reviewer = createGithubAgent({
model: 'anthropic/claude-sonnet-4.6',
preset: 'code-review',
system: `
You review pull requests for code quality and security issues.
Always cite specific file paths and line numbers.
Never approve a PR that introduces console.log statements.
`,
})
AI assistant prompt (createGithubAgent)
Refactor this code to use createGithubAgent from @github-tools/sdk.
- Choose a preset that matches the task (code-review, issue-triage, ci-ops, repo-explorer, or maintainer)
- Preserve or improve system instructions; use patterns from https://github-tools.com/guide/examples
- If destructive GitHub writes must be human-gated, set requireApproval and follow https://github-tools.com/guide/approval-control
Explore a repository interactively
A read-only script that searches code and reads file content. No write permissions needed:
import { createGithubTools } from '@github-tools/sdk'
import { streamText } from 'ai'
const result = streamText({
model: 'anthropic/claude-sonnet-4.6',
tools: createGithubTools({
preset: 'repo-explorer',
}),
prompt: 'Find all TypeScript files that export a function named "create" in vercel-labs/github-tools and explain what each one does.',
})
for await (const chunk of result.textStream) {
process.stdout.write(chunk)
}
Run a maintainer workflow with full approval
A complete workflow that can create issues, open PRs, and merge — all gated behind approval:
import { createGithubTools } from '@github-tools/sdk'
import { generateText } from 'ai'
const { text } = await generateText({
model: 'anthropic/claude-sonnet-4.6',
tools: createGithubTools({
preset: 'maintainer',
requireApproval: true,
}),
prompt: `
Check if there are any stale issues (no activity for 30 days) on vercel-labs/github-tools.
For each stale issue, post a comment asking the author for an update.
If no response after the comment, close the issue with a polite message.
`,
})
Reduce tool context with toolpick
When using many tools, the model sees all tool definitions on every step — eating tokens and increasing latency. toolpick selects only the most relevant tools per step using keyword + semantic search:
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: 'Check if the CI is passing on the main branch of vercel/ai.',
})
Each step, toolpick picks the best ~5 tools. All tools remain callable — only the visible set changes. Add a rerankerModel for maximum accuracy on ambiguous queries:
const index = createToolIndex(tools, {
embeddingModel: openai.embeddingModel('text-embedding-3-small'),
rerankerModel: openai('gpt-4o-mini'),
})
See toolpick docs for caching, description enrichment, and model-driven discovery options.
Durable streaming agent (Vercel Workflow)
For production chat or long GitHub automations, pair createDurableGithubAgent with "use workflow" so the run survives timeouts and restarts. Each tool call is already a durable "use step":
import { createDurableGithubAgent } from '@github-tools/sdk/workflow'
import { getWritable } from 'workflow'
import type { ModelMessage, UIMessageChunk } from 'ai'
export async function streamDurableGithubChat(
messages: ModelMessage[],
token: string,
model: string
) {
'use workflow'
const agent = createDurableGithubAgent({
model,
token,
preset: 'maintainer',
})
const writable = getWritable<UIMessageChunk>()
await agent.stream({ messages, writable })
}
requireApproval is not enforced by DurableAgent today — plan access control in your route or use createGithubAgent when you need approval UX. More detail: Durable workflows (Vercel Workflow).
GitHub bot (Chat SDK + Workflow)
A complete, durable PR review agent connected to GitHub via Chat SDK. When someone @mentions the agent on a PR, a durable workflow runs the code-review agent — reading files, commits, and diffs using GitHub tools — then posts the review as a comment. Follow-up messages resume the same workflow.
The full example lives in examples/pr-review-agent/. It combines four primitives in ~60 lines of code:
@github-tools/sdk—createGithubToolswith thecode-reviewpreset- Chat SDK —
@chat-adapter/githubfor webhook handling and thread management - Vercel Workflow —
"use workflow"+createHookfor durable, multi-turn sessions - evlog —
createAILoggerfor AI observability (tokens, tool calls, cost)
import { createGithubTools } from '@github-tools/sdk'
import { generateText } from 'ai'
import { createLogger } from 'evlog'
import { createAILogger } from 'evlog/ai'
async function runAgentTurn(prompt: string) {
'use step'
const log = createLogger()
const ai = createAILogger(log, { toolInputs: { maxLength: 500 } })
const result = await generateText({
model: ai.wrap('anthropic/claude-sonnet-4.6'),
tools: createGithubTools({ preset: 'code-review' }),
prompt,
maxSteps: 15,
})
log.emit()
return result.text
}
Choose the right pattern
| Pattern | Entry point | Best for |
|---|---|---|
| One-shot generation | generateText + createGithubTools | scripts, CLI tools, batch jobs |
| Streaming | streamText + createGithubTools | chat UIs, interactive terminals |
| Reusable agent | createGithubAgent | multi-turn assistants, persistent bots |
| Durable agent + streaming | createDurableGithubAgent + "use workflow" | hosted chat, crash-safe tool loops, Nuxt/Next APIs on Vercel |
| Platform bot | createGithubTools + Chat SDK + Workflow | GitHub/Slack/Discord bots with durable multi-turn sessions |
See API Reference for the full type signatures and Tools Catalog for every available tool.