GitHub
Build bots that respond to pull request and issue comment threads. Treats issues and PRs as threads, comments as messages.
Create a new bot
Scaffold a Next.js bot with the GitHub adapter using create-chat-sdk:
pnpm create chat-sdk@latest my-bot --adapter github memory -yThe generated app uses the Memory state adapter for local development. To add the adapter to an existing app, start at Install.
Install
pnpm add @chat-adapter/github @chat-adapter/state-memoryQuick start
The adapter auto-detects credentials from GITHUB_TOKEN (or GITHUB_APP_ID/GITHUB_PRIVATE_KEY), GITHUB_WEBHOOK_SECRET, and GITHUB_BOT_USERNAME.
For managed credentials and webhook verification, see Vercel Connect.
The memory state adapter keeps subscriptions and locks in process memory, which suits local development. Use Redis or PostgreSQL in production.
Then create the webhook route:
Authentication
Vercel Connect
Use Vercel Connect to source installation access tokens at runtime instead of storing a GitHub App private key. The connectGitHubAdapter() helper from @vercel/connect/chat wires an installationToken resolver, which skips the App JWT exchange, and a webhookVerifier for Connect trigger-forwarded webhooks:
installationToken accepts a string or () => string | Promise<string> resolver invoked per API call. When webhookVerifier is set it takes precedence over webhookSecret and GITHUB_WEBHOOK_SECRET.
In Connect mode the adapter holds only an installation token, so it can't auto-detect its own bot user ID: the /app lookup needs the App's JWT. Without that ID, the adapter can't recognize its own comments and replies to itself in a loop. It learns the ID from the first comment it posts, but only in memory, which isn't enough on serverless where each webhook can hit a fresh instance. Pass botUserId, the numeric ID of your your-app[bot] user, so every instance knows it up front. You can look it up with curl -s 'https://api.github.com/users/your-app%5Bbot%5D'.
Or set the GITHUB_BOT_USER_ID environment variable, which the adapter auto-detects.
Create the connector and attach it to your project with the Vercel CLI. --trigger-path registers the GitHub webhook route as the trigger destination, and vercel env pull downloads a development OIDC token for local runs:
Without --trigger-branch, Connect forwards webhooks to your production deployment. See Vercel Connect for the full setup.
GitHub App
We recommend a GitHub App. It has better rate limits and security than a personal access token and supports multiple installations.
Create the app
- Go to Settings then Developer settings then GitHub Apps then New GitHub App.
- Set Webhook URL to
https://your-domain.com/api/webhooks/github. - Set a Webhook secret.
- Under permissions, set Issues and Pull requests to Read & write, and Metadata to Read-only.
- Subscribe to events: Issue comment, Pull request review comment.
- Click Create GitHub App and generate a private key.
Install the app
- From your app's settings click Install App and choose repositories.
- Note the Installation ID in the URL:
https://github.com/settings/installations/12345678.
Single-tenant configuration
Set installationId to accept comments only from that GitHub App installation. After verification, a new comment (issue_comment or pull_request_review_comment with action created) from a different installation gets a 404, handlers don't run, and the adapter logs a warning with both IDs. The check runs whether you verify with webhookSecret or a custom webhookVerifier, and other event types and actions aren't checked.
Deliveries without an installation object still reach handlers. GitHub omits it from repository and organization webhooks, so those keep working in this mode. Vercel Connect mode (installationToken) has no configured installation ID and skips this check.
Multi-tenant configuration
Omit installationId:
The adapter extracts installation IDs from incoming webhooks and caches API clients per installation.
Personal access token
A personal access token suits personal projects, testing, and single-repo bots.
- Go to Settings then Developer settings then Personal access tokens.
- Create a token with
reposcope. - Set
GITHUB_TOKEN.
Configuration
Prop
Type
One of token, appId+privateKey, or installationToken (Vercel Connect) is
required, plus either webhookSecret or a webhookVerifier.
Environment variables
| Variable | Required | Description |
|---|---|---|
GITHUB_TOKEN | One auth mode required | Personal access token. |
GITHUB_APP_ID | One auth mode required | GitHub App ID. Use with GITHUB_PRIVATE_KEY. |
GITHUB_PRIVATE_KEY | One auth mode required | GitHub App private key (PEM). Use with GITHUB_APP_ID. |
GITHUB_INSTALLATION_ID | No | Installation ID for a single-tenant GitHub App. Omit for multi-tenant setups. |
GITHUB_WEBHOOK_SECRET | Yes, unless using a webhookVerifier | Webhook secret. |
GITHUB_BOT_USERNAME | No | Bot username for @mention detection. Defaults to github-bot. |
GITHUB_BOT_USER_ID | Recommended with Vercel Connect | Numeric ID of the bot user, so the adapter can recognize its own comments. |
Webhooks
For repository or organization webhooks:
- Open Settings then Webhooks then Add webhook.
- Set the payload URL to
https://your-domain.com/api/webhooks/github. - Set Content type to
application/json. The defaultapplication/x-www-form-urlencodeddoes not work. - Set Secret to match
webhookSecret. - Select events: Issue comments, Pull request review comments.
You configure GitHub App webhooks when you create the app. Make sure to select application/json there too.
Reactions
| SDK emoji | GitHub reaction |
|---|---|
thumbs_up | +1 |
thumbs_down | -1 |
laugh | laugh |
confused | confused |
heart | heart |
hooray | hooray |
rocket | rocket |
eyes | eyes |
Installation lookup
Resolve the GitHub App installation ID associated with a Thread or Message:
The result depends on the auth mode:
- With a personal access token, it returns
undefined. - With a single-tenant GitHub App, it returns the configured installation ID.
- With a multi-tenant GitHub App, it succeeds only after the adapter has received a webhook for that repository and cached the mapping. Use a persistent state adapter so the mapping survives restarts.
Direct API client
Access the underlying Octokit instance through .octokit:
Personal access token and single-tenant App modes return the same client anywhere. Multi-tenant mode requires webhook handler context, and calling .octokit outside a handler throws.
The previous .client getter still works as a deprecated alias for .octokit.
Thread IDs
Issues and pull requests map to threads, and comments map to messages:
| Type | Context | Thread ID format |
|---|---|---|
| PR-level | PR Conversation tab | github:{owner}/{repo}:{prNumber} |
| Review comments | PR Files Changed tab | github:{owner}/{repo}:{prNumber}:rc:{commentId} |
| Issue comments | Issue thread | github:{owner}/{repo}:issue:{issueNumber} |
Feature support
Messaging
| Feature | Supported |
|---|---|
| Post message | |
| Message replies | |
| Edit message | |
| Delete message | |
| File uploads | |
| Streaming | Buffered |
| Scheduled messages |
Rich content
| Feature | Supported |
|---|---|
| Card format | GFM Markdown |
| Buttons | |
| Link buttons | |
| Select menus | |
| Tables | GFM |
| Charts | |
| Fields | |
| Images in cards | |
| Modals |
Conversations
| Feature | Supported |
|---|---|
| Slash commands | |
| Mentions | |
| Add reactions | |
| Remove reactions | Partial |
| Typing indicator | |
| Mark as read | |
| Message edit events | |
| Message delete events | |
| DMs | |
| Ephemeral messages | |
| User lookup | |
| Parent subject | |
| Native client | |
| Custom API endpoint |
Message history
| Feature | Supported |
|---|---|
| Fetch messages | |
| Fetch single message | |
| Fetch thread info | |
| Fetch channel messages | |
| List threads | |
| Fetch channel info | |
| Post channel message |
Resources
- Ship a GitHub code review bot with Hono and Redis: build a GitHub bot that reviews pull requests on demand. When a user @mentions the bot on a PR, Chat SDK picks up the mention, spins up a Vercel Sandbox with the repo cloned, and uses AI SDK to analyze the diff.
See all guides and templates on the resources page.