Skip to content
Novu logoNovu

Changelog

Latest updates and improvements in the agent communication category.

Follow us on X

All changelog posts

  • Agent-Assigned Workflows

    Turn a workflow notification into the first turn of an agent conversation, with the original message and trigger payload already in context.

    Authors:
    Nikita GrossmanVictor Yakubu
    Nikita G., Victor Y.
    Cover image for Agent-Assigned Workflows

    You can now assign an agent to a workflow from the Novu Dashboard. Workflow messages are sent through the agent's connected channels, and when a subscriber replies, Novu routes the reply to that agent with the originating workflow, message, and trigger payload already in context.

    This closes the gap between notifications and conversations. A workflow can send “Your order has shipped,” the subscriber can reply “Can I change the delivery address?”, and the agent receives the order data from the original trigger without a separate correlation layer in your application.

    Turn a notification into a conversation

    Enable Send & reply via agent in the workflow editor and select the agent that should handle replies. Novu associates the outgoing workflow message with that agent and delivers it through the agent's applicable channel connection.

    When the subscriber replies, Novu maps the response back to the sent notification. Depending on the channel, this uses the email reply token, the Slack thread, a quoted message on WhatsApp, Telegram, or Microsoft Teams, or the existing one-to-one conversation history on iMessage.

    The original workflow context is attached when the conversation starts. Later replies reuse that context, so your application does not need to reload and attach the same notification data on every turn.

    For example, an order-support workflow could provide the agent with the rendered shipping message and a payload containing the order ID, tracking number, and delivery address. The agent can then use those values when it handles a follow-up question.

    Send through the agent's connected channels

    An assigned workflow can send through agent-linked Slack, Microsoft Teams DM, WhatsApp, Telegram, iMessage through Sendblue, and email integrations when the subscriber is reachable on that connection.

    Email can use an agent-specific sender and optional reply-to address, so replies return to the agent instead of a no-reply inbox.

    If the selected agent does not have an applicable channel connection, Novu falls back to the provider integration configured in the environment and adds a warning to the step. The assignment does not silently drop the delivery. A Chat step is skipped only when the subscriber has no reachable Chat channel, which matches the existing delivery behavior.

    Give custom code and managed agents the workflow context

    Custom code agents receive a typed ctx.notification field when a conversation starts from an assigned workflow:

    import { isFromWorkflow } from '@novu/framework';
    import { orderShipped } from './workflows/order-shipped';
    
    if (isFromWorkflow(ctx.notification, orderShipped)) {
      const { orderId, trackingNumber } = ctx.notification.payload;
    }

    When the workflow defines a payload schema, ctx.notification.payload uses that schema for type inference. The field is null when the conversation started with an inbound message instead of a workflow notification.

    Managed agents receive the same originating workflow and payload data automatically as conversation context. Novu adds a short assistant message that identifies the workflow, followed by the payload as JSON. There is no handler to update.

    The Agent Conversations timeline in the Dashboard also shows the originating workflow notification, so you can trace how the conversation started alongside the replies that followed.

    Override the assigned agent for one trigger

    The workflow assignment is the default. You can route a single execution to another agent by passing its public identifier as agentId:

    await novu.trigger({
      workflowId: 'order-shipped',
      to: 'subscriber-123',
      payload: {
        orderId: 'order-456',
        trackingNumber: '1Z999AA10123456784',
      },
      agentId: 'order-support-agent',
    });

    Omit agentId to use the agent assigned in the workflow. Pass agentId: null when that execution should send without agent reply routing.

    Open a workflow in the Dashboard and enable Send & reply via agent to get started. See the AI SDK quickstart, Trigger event API, and Agent Conversations documentation for the related APIs and runtime behavior.

  • LangChain adapter for Novu Connect

    Connect a LangChain or LangGraph agent to Slack, Microsoft Teams, WhatsApp, Telegram, and email, with mapped conversation history and in-channel tool approval on the adapter-managed path.

    Langchain adapter for Novu Connect

    The LangChain adapter is now available through @novu/framework/langchain. It gives teams already using LangChain or LangGraph a direct path to Novu Connect without rebuilding their agent for each communication channel.

    Your agent or graph continues to run in your application. Novu Connect handles inbound channel events, conversation context, and delivery of the response back to the user.

    For OpenAI:

    npm install @novu/framework langchain @langchain/core @langchain/openai

    For Anthropic:

    npm install @novu/framework langchain @langchain/core @langchain/anthropic
    Good to know

    This is not limited to just OpenAI and Anthropic, you can use other LangChain provider keys.

    Return a config or invoke your own agent

    The adapter supports two handoff patterns based on how much of your LangChain setup you want it to manage.

    When you return a LangChainAgentConfig from onMessage, the adapter calls createAgent().invoke() in your application, maps ctx.history, and delivers the final assistant response:

    import { agent } from '@novu/framework/langchain';
    
    export const supportBot = agent('support-bot', {
      onMessage: async (_message, ctx) => ({
        model: 'openai:gpt-4o',
        system: 'You are a helpful support agent.',
      }),
    });

    If you already invoke a LangChain agent or LangGraph graph yourself, use toLangChainMessages(ctx.history), run your existing invoke() call, and return { messages }. Novu delivers the final assistant message. Tool approval is not managed by the adapter on this bring-your-own invocation path.

    Ask for approval in the channel

    On the config path, needsApproval lets you gate sensitive tools without building a separate approval flow for every channel. When the model calls a gated tool, Novu posts an Approve / Deny card and pauses the turn. After the user responds, the adapter replays the approval cycle from conversation history and continues the agent run.

    import { tool } from '@langchain/core/tools';
    import { agent } from '@novu/framework/langchain';
    import { z } from 'zod';
    
    const issueRefund = tool(
      async ({ orderId }) => ({ orderId, status: 'refunded' }),
      {
        name: 'issueRefund',
        description: 'Issue a refund for an order',
        schema: z.object({ orderId: z.string() }),
      },
    );
    
    export const supportBot = agent('support-bot', {
      onMessage: async () => ({
        model: 'openai:gpt-4o',
        system: 'You are a helpful support agent.',
        tools: [issueRefund],
        needsApproval: (toolCall) => toolCall.name === 'issueRefund',
      }),
    });

    This approval flow does not require a separate LangGraph checkpointer. The conversation history holds the information the adapter needs to resume the turn.

    Get started with npx novu connect --runtime langchain, then follow the LangChain quickstart. See the LangChain reference for config returns, custom invocation, approval gating, Next.js setup, and error handling.

  • Vercel AI SDK adapter for Novu Connect

    Bring an existing Vercel AI SDK agent to Slack, Microsoft Teams, WhatsApp, Telegram, and email while keeping the same model, tools, and application code.

    Vercel AI SDK adapter for Novu Connect

    The Vercel AI SDK adapter is now available through @novu/framework/ai-sdk. Your agent continues to run your application. Novu Connect receives messages from each connected channel, passes the conversation context to your handler, and delivers the response that your handler returns.

    Install @novu/framework with the AI SDK and your model provider:

    npm install @novu/framework ai @ai-sdk/openai

    Use one handler across connected channels

    Return generateText() from onMessage, and the adapter handles the handoff between Novu conversation history and the Vercel AI SDK.

    import { agent, toModelMessages } from '@novu/framework/ai-sdk';
    import { openai } from '@ai-sdk/openai';
    import { generateText } from 'ai';
    
    export const supportBot = agent('support-bot', {
      onMessage: async (_message, ctx) =>
        generateText({
          model: openai('gpt-4o'),
          instructions: 'You are a helpful support agent.',
          messages: toModelMessages(ctx.history),
        }),
    });

    toModelMessages(ctx.history) converts the full conversation into AI SDK messages and already includes the current inbound message. After you connect other channel providers, the same handler can reply on Slack, Microsoft Teams, WhatsApp, Telegram, and email.

    Keep tool approval in the conversation

    AI SDK tool loops work through the adapter, including actions and tool calls that require a person to approve them. Set needsApproval: true on a tool, and Novu posts an Approve / Deny card in the conversation any time the tool is called. The turn pauses until the user decides, then resumes with the decision included in the mapped conversation history.

    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),
            }),
          },
        }),
    });

    You can also use MCP tools through the AI SDK MCP client on the custom-code path. Your application creates the client and supplies its credentials, while Novu Connect handles the conversation and channel delivery.

    Get started with npx novu connect --runtime ai-sdk, then follow the AI SDK quickstart. See the AI SDK reference for return types, tool approval, MCP tools, streaming updates, and error handling.

  • Novu Chat SDK Adapter

    Bring your Chat SDK agent to Slack, Teams, WhatsApp, Telegram, and email: deliver multi-channel notifications from one trigger, resolve every channel to one unified subscriber, and drop in React connect components to put channels in front of your end-customers.

    The @novu/chat-sdk-adapter is now available. Wire it into your Chat SDK app and Novu manages credentials, identity, and delivery across Slack, Microsoft Teams, WhatsApp, Telegram, and email.

    npm install @novu/chat-sdk-adapter

    Multi-channel notifications from one trigger

    Define a workflow once in Novu with the channels you want, then fire a single trigger from any handler. Novu fans out to every step — Slack, email, WhatsApp, and more — and routes replies back through the same agent loop, so proactive notifications and conversational replies share one handler set.

    const ctx = getNovuContext(thread);
    
    // One trigger delivers to every channel in the workflow.
    await ctx.trigger("order-shipped", {
      payload: { orderId: "1234", trackingUrl: "https://example.com/track/1234" },
    });

    One unified subscriber across every channel

    Every channel resolves to a single Novu subscriber mapped to your own user, so your agent always knows who it's talking to — with email, phone, locale, custom data, and the canonical conversation history available inside any handler.

    const ctx = getNovuContext(thread);
    
    const subscriber = await ctx.getSubscriber(); // email, phone, locale, custom data
    const history = await ctx.getHistory();       // canonical transcript — ideal for LLM context

    Expose channels to end-customers with connect components

    Drop the prebuilt SlackConnectButton from @novu/react into your app so your end-customers can install and connect their own Slack workspace to your agent — OAuth, credentials, and Slack Connect handled by Novu. Microsoft Teams and Telegram connect buttons are in pre-release.

    import { SlackConnectButton } from '@novu/react';
    
    <SlackConnectButton
      integrationIdentifier={integrationIdentifier}
      connectionIdentifier={`${subscriberId}:${integrationIdentifier}:${agent.identifier}`}
      connectionMode="subscriber"
      connectLabel={`Install ${agent.name} ↗`}
      connectedLabel="Connected to Slack"
      onConnectSuccess={handleSlackOAuthSuccess}
    />

    Get started with npx novu connect --runtime chat-sdk, or read the connect components docs.

  • In-conversation MCP authorization and message queues

    Connect external MCPs during the conversation and process incoming messages one at a time for a more predictable chat experience.

    Author:Dima Grossman
    Dima Grossman

    Connecting external MCPs is now part of the conversation itself, instead of a separate setup step. When an agent needs access to a tool, it can prompt the user to connect it right at that moment and then continue the original request once access is granted. This makes the experience feel much more natural and reduces the friction of getting started with tool-powered workflows.

    We also introduced session-level tool access, so connected tools are available only where they are relevant. That gives users a clearer sense of control over what an agent can use during a conversation, while helping keep tool usage focused on the task at hand.

    Conversation queue

    We also improved how conversations behave when several messages arrive quickly. Messages are now processed in order, one at a time, instead of competing in parallel. This creates a more predictable experience in fast-moving chats and helps reduce confusing or out-of-sequence responses.

    Each queued message gets its own ⏳ indicator, and the indicator is removed when the message is processed.