---
title: Vercel Connect
description: Authenticate Slack, GitHub, and Linear adapters with Vercel Connect — short-lived runtime tokens for outbound calls and OIDC-verified inbound webhooks, with no stored provider secrets.
type: overview
related:
  - /docs/usage
  - /adapters/official/slack
  - /adapters/official/github
  - /adapters/official/linear
---

# Vercel Connect



[Vercel Connect](https://vercel.com/docs/connect) lets your bot use a registered connector for adapter authentication instead of storing long-lived provider secrets. You register a connector once, link it to your project and environments, and your code requests scoped, short-lived tokens at runtime.

The `@vercel/connect/chat` subpath ships a helper per platform that you spread into the matching `create*Adapter` factory:

* `connectSlackAdapter`
* `connectGitHubAdapter`
* `connectLinearAdapter`

Each helper wires both directions of traffic:

* **Outbound** (your bot calls the provider API) — a function-form token field that resolves a fresh, short-lived token per call via `getToken`.
* **Inbound** (the provider calls your bot) — a `webhookVerifier` that validates the Vercel OIDC token Connect attaches to [trigger-forwarded](https://vercel.com/docs/connect/concepts/triggers) webhooks, replacing the provider's native signature check.

<Callout type="info">
  Vercel Connect is in beta. Features and behavior, including available connectors and trigger forwarding, may change before general availability.
</Callout>

## Install

```bash
pnpm add @vercel/connect
```

`@vercel/connect` reads the deployment's OIDC token automatically. For local development, run `vercel link` followed by `vercel env pull` to download a short-lived token into `.env.local`.

## Adapter support

| Adapter                             | Helper                 | Outbound field      |
| ----------------------------------- | ---------------------- | ------------------- |
| [Slack](/adapters/official/slack)   | `connectSlackAdapter`  | `botToken`          |
| [GitHub](/adapters/official/github) | `connectGitHubAdapter` | `installationToken` |
| [Linear](/adapters/official/linear) | `connectLinearAdapter` | `accessToken`       |

Each helper accepts `(connector, params?, options?)`, where `params` is the [`getToken`](https://vercel.com/docs/connect/ts-sdk-reference) parameters minus `subject` (pinned to `{ type: "app" }`), letting you pass through `installationId`, `scopes`, or `validityBufferMs`.

## Set up a connector

1. Create a connector for the provider in the [Vercel dashboard](https://vercel.com/d?to=%2F%5Bteam%5D%2F~%2Fconnect) or with the CLI, enabling trigger forwarding so inbound webhooks reach your project:

```bash
vercel connect create slack --name acme-slack --triggers
```

2. Attach your project and register your Chat SDK webhook route (`/api/webhooks/{platform}`) as the trigger destination:

```bash
vercel connect attach slack/acme-slack \
  --project my-bot --environment production \
  --triggers --trigger-path /api/webhooks/slack
```

3. Pull a development token locally (deployments get `VERCEL_OIDC_TOKEN` automatically):

```bash
vercel link
vercel env pull
```

## Wire up the adapter

Spread the helper into the adapter factory. The webhook route is unchanged — Connect forwards verified events to the same handler.

```typescript title="lib/bot.ts" lineNumbers
import { Chat } from "chat";
import { createSlackAdapter } from "@chat-adapter/slack";
import { createRedisState } from "@chat-adapter/state-redis";
import { connectSlackAdapter } from "@vercel/connect/chat";

export const bot = new Chat({
  userName: "mybot",
  adapters: {
    slack: createSlackAdapter({
      ...connectSlackAdapter("slack/acme-slack"),
    }),
  },
  state: createRedisState(),
});
```

Replace `slack/acme-slack` with your connector UID from the Connect dashboard or `vercel connect list`. Omit `signingSecret` / `SLACK_SIGNING_SECRET` when using the helper — the OIDC `webhookVerifier` is the freshness boundary.

### GitHub

```typescript title="lib/bot.ts" lineNumbers
import { createGitHubAdapter } from "@chat-adapter/github";
import { connectGitHubAdapter } from "@vercel/connect/chat";

createGitHubAdapter({
  ...connectGitHubAdapter("github/acme-github"),
  userName: "my-bot[bot]",
});
```

`installationToken` is the installation access token a GitHub App would normally mint via its private-key JWT exchange — the adapter uses it directly and skips that exchange.

### Linear

```typescript title="lib/bot.ts" lineNumbers
import { createLinearAdapter } from "@chat-adapter/linear";
import { connectLinearAdapter } from "@vercel/connect/chat";

createLinearAdapter({
  ...connectLinearAdapter("linear/acme-linear"),
  mode: "agent-sessions",
});
```

Use `mode: "agent-sessions"` for app-actor installs. For outbound calls outside webhook handling (cron jobs, workflows), wrap them in `withInstallation()` so a request-scoped client is bound:

```typescript title="lib/jobs.ts" lineNumbers
await linear.withInstallation("org-id", async () => {
  await linear.postMessage("linear:issue-id", "Hello from a background job");
});
```

## Custom webhook verification

Each helper attaches a default verifier that matches the deployment's project and environment automatically (`projectId` defaults to `VERCEL_PROJECT_ID`, `environment` to `VERCEL_TARGET_ENV` then `VERCEL_ENV`), so production, preview, and development each accept only their own tokens. Verification fails closed — if those values are absent, every request is rejected, and the issuer is pinned to `https://oidc.vercel.com`.

To add constraints (for example to accept multiple environments), build a verifier with `createConnectWebhookVerifier` and override the field:

```typescript title="lib/bot.ts" lineNumbers
import {
  connectSlackAdapter,
  createConnectWebhookVerifier,
} from "@vercel/connect/chat";

createSlackAdapter({
  ...connectSlackAdapter("slack/acme-slack"),
  webhookVerifier: createConnectWebhookVerifier({
    environment: ["production", "preview"],
  }),
});
```

<Callout type="warn">
  Avoid hardcoding `environment: "production"` unless you only forward to production — it would reject preview and development deployments.
</Callout>

## Notes and limitations

* **App-scoped tokens.** The helpers act as the application itself (`subject: { type: "app" }`). End-user OAuth is a separate concern.
* **Freshness and replay.** OIDC verification replaces each provider's native signature (and timestamp) check, so request freshness relies on the short-lived OIDC token's expiry rather than a signed timestamp, and there is no built-in delivery de-duplication. Keep your webhook handlers idempotent.
* **Socket Mode is incompatible.** Connect trigger forwarding is HTTP-only; it doesn't apply to the Slack adapter's Socket Mode.
* **Testing.** Connect forwards to deployed URLs, not `localhost` — test against a preview or development deployment.

## Related resources

* [Vercel Connect overview](https://vercel.com/docs/connect)
* [Vercel Connect triggers](https://vercel.com/docs/connect/concepts/triggers)
* [`@vercel/connect` SDK reference](https://vercel.com/docs/connect/ts-sdk-reference)
