Skip to main content
Conversations are the primary way your agent handles user messages. Each conversation handler defines how your agent responds to messages from specific channels.

Creating a conversation

Create a conversation handler in src/conversations/:
import { Conversation } from "@botpress/runtime";

export default new Conversation({
  channel: "*",
  handler: async ({ execute }) => {
    await execute({
      instructions: "You are a helpful assistant.",
    });
  },
});

Channel matching

The channel property determines which integration channels the Conversation handles:
export default new Conversation({
  channel: "*",
  handler: async ({ execute }) => {
    await execute({
      instructions: "You are a helpful assistant.",
    });
  },
});

Conversation handler

The handler function receives context about the incoming message and provides APIs to execute your agent’s logic:
export default new Conversation({
  channel: "chat.channel",
  handler: async ({ execute, message }) => {
    const userMessage = message.payload.text;
    await execute({
      instructions: `You are a helpful assistant. The user said: ${userMessage}`,
    });
  },
});
When using channel: "*", the message type is unknown since the concrete channel is only known at runtime. Use a specific channel to get full type safety on message properties.

Using knowledge bases

Provide knowledge to your agent’s AI model:
import { WebsiteKB } from "../knowledge/docs";

export default new Conversation({
  channel: "*",
  handler: async ({ execute }) => {
    await execute({
      instructions: "You are a helpful assistant.",
      knowledge: [WebsiteKB],
    });
  },
});

Using hooks

Add hooks to customize behavior at different stages:
export default new Conversation({
  channel: "*",
  handler: async ({ execute }) => {
    await execute({
      instructions: "You are a helpful assistant.",
      hooks: {
        onBeforeTool: async (props) => {
          // Custom logic before tool execution
        },
        onTrace: (props) => {
          // Log or monitor trace events
        },
      },
    });
  },
});

Conversation instance

The handler receives a conversation object that provides methods to interact with the current conversation. It exposes conversation.id (the conversation ID) and conversation.channel (the channel name) as read-only properties.

Loading a conversation by ID

You can load any conversation by passing its ID as a string to the static Conversation.get() method:
import { Conversation } from "@botpress/runtime";

const otherConversation = await Conversation.get("your-conversation-id");
await otherConversation.send({ type: "text", payload: { text: "Hello from another conversation!" } });

Sending messages

Send a message to the conversation:
await conversation.send({
  type: "text",
  payload: { text: "Hello!" },
});

Typing indicators

Control typing indicators:
await conversation.startTyping();
// ... do some work ...
await conversation.stopTyping();

Conversation tags

Access and modify conversation tags:
// Read tags
const priority = conversation.tags.priority;

// Set tags
conversation.tags.priority = "high";

Multiple conversations

You can create multiple conversation handlers for different channels or use cases:
src/conversations/
├── webchat.ts        # Webchat-specific handler
├── slack.ts          # Slack-specific handler
└── support.ts        # Support-focused handler

Reference

Conversation props

Handler parameters

The handler receives different parameters depending on the request type. Check the type field to determine what kind of request you’re handling. All handler types share these common parameters:

Message handler

When type is "message":

Event handler

When type is "event":
To receive events in a conversation, you must specify the events prop on the Conversation definition. By default, conversations only receive messages.

Workflow request handler

When type is "workflow_request":

Workflow callback handler

When type is "workflow_callback":

Execute props

The execute function accepts the following props:
Last modified on April 21, 2026