docs/agents/get-started/ai-sdk.mdx
Connect a Vercel AI SDK agent to Novu Connect. Return generateText() from onMessage; Novu delivers the reply on Slack. After you add other providers, the same handler serves Teams, WhatsApp, Telegram, and email.
This guide uses Slack first and assumes an existing Node.js app. Examples use OpenAI or Anthropic via the AI SDK.
<Note> Starting from scratch? See [Scaffold with the CLI](#scaffold-with-the-cli). </Note>OPENAI_API_KEY or ANTHROPIC_API_KEY (or another AI SDK provider key)In the Novu dashboard:
The token is used once to create the Slack app. Novu does not store it. Screenshots: Create a Slack app.
Alternatively run npx novu connect, choose AI SDK and Slack, and skip creating a starter project when prompted.
</Step>
Add to .env.local (or your app env file):
NOVU_SECRET_KEY=your-novu-secret-key
OPENAI_API_KEY=sk-... # or ANTHROPIC_API_KEY
Copy NOVU_SECRET_KEY from API Keys in the dashboard.
</Step>
Create app/novu/agents/<your-identifier>.ts (or the equivalent path). Match agent('...') to the dashboard Identifier.
export const supportBot = agent('support-bot', { onMessage: async (_message, ctx) => generateText({ model: openai('gpt-4o'), instructions: 'You are a helpful support agent. Keep answers short.', messages: toModelMessages(ctx.history), }), });
</Tab>
<Tab title="Claude">
```typescript
import { agent, toModelMessages } from '@novu/framework/ai-sdk';
import { anthropic } from '@ai-sdk/anthropic';
import { generateText } from 'ai';
export const supportBot = agent('support-bot', {
onMessage: async (_message, ctx) =>
generateText({
model: anthropic('claude-sonnet-4-20250514'),
instructions: 'You are a helpful support agent. Keep answers short.',
messages: toModelMessages(ctx.history),
}),
});
Export it from your agents index:
export { supportBot } from './support-bot';
toModelMessages(ctx.history) already includes the current inbound message. Returning generateText(...) delivers the reply. Do not call ctx.reply() on this path.
</Step>
For Next.js, create app/api/novu/route.ts:
import { serve } from '@novu/framework/next';
import { supportBot } from '../../novu/agents';
export const { GET, POST, OPTIONS } = serve({
agents: [supportBot],
});
For Express, Hono, and other servers, see Connecting your app. </Step>
<Step> ## Run locally and message Slacknpx novu dev --port 4000
Or npm run dev:novu if that script exists. Keep the process running.
DM or @mention the bot in Slack. The reply should come from your model in the same thread.
If nothing comes back:
Gate a tool so the turn pauses for Approve / Deny in Slack:
import { agent, toModelMessages } from '@novu/framework/ai-sdk';
import { openai } from '@ai-sdk/openai';
import { generateText, tool } from 'ai';
import { z } from 'zod';
export const supportBot = agent('support-bot', {
onMessage: async (_message, ctx) =>
generateText({
model: openai('gpt-4o'),
messages: toModelMessages(ctx.history),
tools: {
issueRefund: tool({
inputSchema: z.object({ orderId: z.string() }),
needsApproval: true,
execute: async ({ orderId }) => refund(orderId),
}),
},
}),
});
See Tool approval and the AI SDK reference.
If you do not have an app yet:
npx novu connect
Choose AI SDK, name the agent, authenticate the model, choose Slack, and accept the starter project. Then run npm run dev:novu.
For an existing codebase, use Connect an existing app instead.
<Prompt description="Connect my Vercel AI SDK agent to Slack with Novu" icon="plug" actions={["copy", "cursor"]}>
Follow https://docs.novu.co/agents/get-started/ai-sdk
Add Novu bridge + AI SDK handler to this repo and connect Slack. Prefer the existing project over scaffolding a new one.
ALWAYS:
agent('id') to the Novu dashboard agent IdentifiertoModelMessages(ctx.history) for conversation contextNEVER:
ctx.reply() when returning generateText() (Novu delivers the result)