packages/framework/README.md
@novu/framework is Novu's code-first SDK for two things:
npx novu connect.Learn more in the Framework docs and managed agent quickstart.
npm install @novu/framework
The fastest path is the Novu CLI — it creates the agent in Novu Cloud, provisions channel credentials, and (for bridge runtimes) wires your local app:
npx novu@latest connect
For a self-hosted agent in your repo, pick a bridge runtime when prompted, or pass one explicitly:
# Vercel AI SDK agent
npx novu@latest connect --runtime ai-sdk
# Chat SDK multi-channel agent
npx novu@latest connect --runtime chat-sdk
Re-run npx novu connect to add another channel. Each run connects one channel to one agent.
Define agents in your codebase and serve them on a Novu bridge endpoint. Use @novu/framework/ai-sdk when your agent is built with the Vercel AI SDK:
import { serve } from '@novu/framework/next';
import { agent } from '@novu/framework/ai-sdk';
import { streamText } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
const supportAgent = agent('support-bot', {
onMessage: async (message, ctx) => {
const result = streamText({
model: anthropic('claude-sonnet-4-20250514'),
messages: await ctx.toModelMessages(),
});
return result;
},
});
const { GET, POST, OPTIONS } = serve({ agents: [supportAgent] });
For custom handlers without the AI SDK, use the core agent() export:
import { agent } from '@novu/framework';
import { serve } from '@novu/framework/next';
const supportAgent = agent('support-bot', {
onMessage: async (message, ctx) => {
await ctx.reply(`You said: ${message.text}`);
},
});
const { GET, POST, OPTIONS } = serve({ agents: [supportAgent] });
After your bridge is running, connect channels:
npx novu@latest connect --runtime ai-sdk --channel slack
npx novu@latest sync -b https://your-app.com/api/novu -s "$NOVU_SECRET_KEY"
Bridge runtimes supported by novu connect: ai-sdk, langchain, custom-code, chat-sdk.
Write notification workflows as functions that execute business logic and use your preferred libraries for email, SMS, and chat generation. Use React.Email, MJML, or any other template generator.
import { workflow, CronExpression } from '@novu/framework';
import { serve } from '@novu/framework/next';
import { z } from 'zod';
const weeklyComments = workflow(
'comment-on-post',
async ({ payload, step }) => {
const inAppResponse = await step.inApp('new-comment', async () => ({
body: `You have a new comment on your post ${payload.comment}`,
}));
const weeklyDigest = await step.digest('weekly-digest', () => ({
cron: CronExpression.EVERY_WEEK,
}));
await step.email(
'weekly-comments',
async (controls) => ({
subject: `${controls.prefix} - Weekly post comments (${weeklyDigest.events.length})`,
body: `Weekly digest: ${weeklyDigest.events.map(({ payload }) => payload.comment).join(', ')}`,
}),
{
skip: () => weeklyDigest.events.length === 0,
controlSchema: z.object({ prefix: z.string().describe('The prefix of the subject.').default('Hi!') }),
}
);
},
{ payloadSchema: z.object({ comment: z.string().describe('The comment on the post.') }) }
);
const { GET, POST, OPTIONS } = serve({ workflows: [weeklyComments] });
weeklyComments.trigger({ to: 'user:123', comment: 'This is a comment on a post' });
Sync workflows with Novu Cloud:
npx novu@latest sync -b https://your-app.com/api/novu -s "$NOVU_SECRET_KEY"
For local workflow development with Novu Studio, see the Novu CLI dev command.
Serve workflows and agents from your framework of choice:
| Import | Framework |
|---|---|
@novu/framework/next | Next.js |
@novu/framework/nest | NestJS |
@novu/framework/express | Express |
@novu/framework/h3 | H3 / Nuxt |
@novu/framework/lambda | AWS Lambda |
@novu/framework/sveltekit | SvelteKit |
@novu/framework/remix | Remix |
Additional exports:
| Import | Purpose |
|---|---|
@novu/framework/ai-sdk | Vercel AI SDK agent helpers |
@novu/framework/step-resolver | Deploy custom step handlers |
@novu/framework/validators | Schema validation utilities |