Refactor to createGithubAgent
One example per framework
The same 42 tools, four runtimes. Each example below is complete and runnable.
eve — a GitHub agent in 3 files
The fastest path to a standalone agent. All 42 tools, durable approval on every write, zero boilerplate (full guide, examples/eve-agent/):
You are a GitHub code-review assistant.
import { defineAgent } from 'eve'
export default defineAgent({
model: 'anthropic/claude-sonnet-5',
})
import { createGithubTools } from '@github-tools/sdk/eve'
export default createGithubTools({
preset: 'maintainer',
})
npx eve dev
AI SDK — a script
One generateText call with a preset (full guide):
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)
Vercel Workflow — a durable chat route
A crash-safe streaming agent behind an API route (full guide):
import { createDurableGithubAgent } from '@github-tools/sdk/workflow'
import { getWritable } from 'workflow'
import type { ModelMessage, UIMessageChunk } from 'ai'
export async function durableGithubChat(messages: ModelMessage[], token: string) {
'use workflow'
const agent = createDurableGithubAgent({
model: 'anthropic/claude-sonnet-4.6',
token,
preset: 'maintainer',
})
const writable = getWritable<UIMessageChunk>()
await agent.stream({ messages, writable })
}
import { start } from 'workflow/api'
import { durableGithubChat } from '../workflows/chat'
export default defineEventHandler(async (event) => {
const { messages } = await readBody(event)
const run = await start(durableGithubChat, [messages, process.env.GITHUB_TOKEN!])
setHeader(event, 'x-workflow-run-id', run.runId)
return run.readable
})
Chat SDK — a GitHub PR review bot
@mention the bot on a PR and a durable workflow reviews it (full guide, examples/pr-review-agent/):
import { createHook, getWorkflowMetadata } from 'workflow'
import { createGithubAgent } from '@github-tools/sdk'
async function runAgentTurn(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
}
export async function reviewWorkflow(prompt: string) {
'use workflow'
const { workflowRunId } = getWorkflowMetadata()
using hook = createHook<{ text: string }>({ token: workflowRunId })
await runAgentTurn(prompt)
for await (const event of hook) {
await runAgentTurn(event.text)
}
}
Recipes
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.
`,
})
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.
Add AI observability with evlog
Wrap the model with evlog to log token usage, tool calls, cost, and timing for every agent turn:
import { createGithubTools } from '@github-tools/sdk'
import { generateText } from 'ai'
import { createLogger } from 'evlog'
import { createAILogger } from 'evlog/ai'
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: 'Review the latest PR on vercel-labs/github-tools.',
})
log.emit()
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 |
| eve agent | createGithubTools from @github-tools/sdk/eve | standalone agents in 3 files, durable HITL approval (once, predicates) |
| 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.