Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/botpress/botpress/llms.txt

Use this file to discover all available pages before exploring further.

What are Integrations?

Integrations are packages that connect Botpress bots to external platforms and services. They provide:
  • Channels: Communication pathways (Telegram chats, Slack channels, etc.)
  • Actions: Operations to perform on the platform (send message, create channel)
  • Events: Platform-specific events (message received, user joined)
  • Entities: Data models specific to the platform (users, conversations)
Integrations act as adapters between Botpress’s unified bot interface and external platform APIs.

Integration Architecture

Creating an Integration

Integration Definition

From packages/sdk/src/integration/definition/index.ts:177, integrations are defined using IntegrationDefinition:
import { IntegrationDefinition, z } from '@botpress/sdk'

export default new IntegrationDefinition({
  name: 'telegram',
  version: '1.0.3',
  title: 'Telegram',
  description: 'Engage with your audience in real-time.',
  icon: 'icon.svg',
  readme: 'hub.md',
  
  // Configuration schema
  configuration: {
    schema: z.object({
      botToken: z.string().min(1).describe('Bot Token')
    })
  },
  
  // Define channels
  channels: {
    channel: {
      title: 'Telegram Channel',
      description: 'Send and receive messages via Telegram',
      
      // Message types supported
      messages: {
        text: {
          schema: z.object({
            text: z.string()
          })
        },
        image: {
          schema: z.object({
            imageUrl: z.string().url()
          })
        },
        // ... more message types
      },
      
      // Conversation tags (metadata)
      conversation: {
        tags: {
          id: { title: 'Chat ID' },
          chatId: { title: 'Telegram Chat ID' }
        }
      },
      
      // Message tags
      message: {
        tags: {
          id: { title: 'Message ID' },
          chatId: { title: 'Chat ID' }
        }
      }
    }
  },
  
  // Custom actions
  actions: {
    sendMessage: {
      title: 'Send Message',
      description: 'Send a message to a Telegram chat',
      input: {
        schema: z.object({
          chatId: z.string(),
          text: z.string()
        })
      },
      output: {
        schema: z.object({
          messageId: z.string()
        })
      }
    }
  },
  
  // Custom events
  events: {
    messageReceived: {
      schema: z.object({
        chatId: z.string(),
        text: z.string(),
        from: z.object({
          id: z.string(),
          username: z.string().optional()
        })
      })
    }
  },
  
  // User metadata
  user: {
    tags: {
      telegramId: { title: 'Telegram User ID' },
      username: { title: 'Telegram Username' }
    }
  },
  
  // Secrets for secure configuration
  secrets: {
    SENTRY_DSN: { description: 'Sentry DSN for error tracking' }
  },
  
  // Platform-specific entities
  entities: {
    telegramUser: {
      schema: z.object({
        id: z.string(),
        username: z.string().optional(),
        firstName: z.string(),
        lastName: z.string().optional()
      })
    }
  }
})

Integration Implementation

The implementation lives in src/index.ts:
import { IntegrationImplementation } from '@botpress/sdk'
import { Telegram } from 'telegram-api-client'

export default new IntegrationImplementation({
  // Register handler - runs when integration is installed
  register: async ({ webhookUrl, configuration, client }) => {
    const telegram = new Telegram(configuration.botToken)
    
    // Register webhook with Telegram
    await telegram.setWebhook({
      url: webhookUrl
    })
  },
  
  // Unregister handler - runs when integration is uninstalled
  unregister: async ({ configuration }) => {
    const telegram = new Telegram(configuration.botToken)
    await telegram.deleteWebhook()
  },
  
  // Action implementations
  actions: {
    sendMessage: async ({ input, configuration }) => {
      const telegram = new Telegram(configuration.botToken)
      
      const result = await telegram.sendMessage({
        chat_id: input.chatId,
        text: input.text
      })
      
      return {
        messageId: result.message_id.toString()
      }
    }
  },
  
  // Channel implementations
  channels: {
    channel: {
      messages: {
        text: async ({ payload, configuration, conversation }) => {
          const telegram = new Telegram(configuration.botToken)
          
          await telegram.sendMessage({
            chat_id: conversation.tags.chatId,
            text: payload.text
          })
        }
      }
    }
  },
  
  // Webhook handler
  handler: async ({ req, client, configuration }) => {
    if (req.path === '/webhook') {
      const update = JSON.parse(req.body || '{}')
      
      if (update.message) {
        // Get or create user
        const { user } = await client.getOrCreateUser({
          tags: {
            telegramId: update.message.from.id.toString(),
            username: update.message.from.username
          }
        })
        
        // Get or create conversation
        const { conversation } = await client.getOrCreateConversation({
          channel: 'channel',
          tags: {
            chatId: update.message.chat.id.toString()
          }
        })
        
        // Create message in Botpress
        await client.createMessage({
          conversationId: conversation.id,
          userId: user.id,
          type: 'text',
          payload: {
            text: update.message.text
          },
          tags: {
            messageId: update.message.message_id.toString()
          }
        })
      }
      
      return { status: 200 }
    }
  }
})

Using Integrations in Bots

Add integrations to your bot:
import telegram from '@botpress/telegram'
import { BotDefinition } from '@botpress/sdk'

const bot = new BotDefinition({})

bot.addIntegration(telegram, {
  alias: 'mainChannel',
  configuration: {
    botToken: process.env.TELEGRAM_BOT_TOKEN
  }
})

// Add multiple instances
bot.addIntegration(telegram, {
  alias: 'supportChannel',
  configuration: {
    botToken: process.env.TELEGRAM_SUPPORT_BOT_TOKEN
  }
})
You can install multiple instances of the same integration with different configurations using unique aliases.

Implementing Interfaces

Integrations can implement interfaces to provide standard functionality. From packages/sdk/src/integration/definition/index.ts:246:
import { IntegrationDefinition, z } from '@botpress/sdk'
import llmInterface from '@botpress/interface-llm'

const anthropicIntegration = new IntegrationDefinition({
  name: 'anthropic',
  version: '1.0.0',
  title: 'Anthropic',
  
  configuration: {
    schema: z.object({
      apiKey: z.string()
    })
  },
  
  // Define entities that map to interface entities
  entities: {
    model: {
      schema: z.object({
        id: z.string(),
        name: z.string(),
        maxTokens: z.number()
      })
    }
  }
})

// Extend the LLM interface
anthropicIntegration.extend(llmInterface, ({ entities }) => ({
  // Map integration entities to interface entities
  entities: {
    modelRef: entities.model
  },
  
  // Override interface action metadata
  actions: {
    generateContent: {
      name: 'generateContent',
      title: 'Generate Content with Claude',
      billable: true
    }
  }
}))

export default anthropicIntegration

Why Implement Interfaces?

  1. Interoperability: Plugins can use any integration implementing the same interface
  2. Standardization: Common operations (LLM, storage, etc.) have consistent APIs
  3. Swappability: Switch between providers without changing bot code

Channels

Channels define how messages flow between the bot and platform:
channels: {
  dm: {
    title: 'Direct Messages',
    messages: {
      text: { schema: z.object({ text: z.string() }) },
      image: { schema: z.object({ imageUrl: z.string() }) },
      file: { schema: z.object({ fileUrl: z.string() }) }
    }
  },
  group: {
    title: 'Group Chats',
    messages: {
      text: { schema: z.object({ text: z.string() }) }
    }
  }
}
Disable specific channels when adding to a bot:
bot.addIntegration(slack, {
  configuration: { botToken: process.env.SLACK_TOKEN },
  disabledChannels: ['dm'] // Only allow group channels
})

Multiple Configurations

Integrations can support multiple configuration schemas:
new IntegrationDefinition({
  name: 'database',
  
  // Default configuration
  configuration: {
    schema: z.object({
      connectionString: z.string()
    })
  },
  
  // Alternative configurations
  configurations: {
    postgres: {
      schema: z.object({
        host: z.string(),
        port: z.number(),
        database: z.string(),
        username: z.string(),
        password: z.string()
      })
    },
    mongodb: {
      schema: z.object({
        uri: z.string(),
        database: z.string()
      })
    }
  }
})

// Use alternative configuration
bot.addIntegration(database, {
  configurationType: 'postgres',
  configuration: {
    host: 'localhost',
    port: 5432,
    database: 'mydb',
    username: 'user',
    password: 'pass'
  }
})

Identity Extraction

Extract user identity from platform-specific data:
new IntegrationDefinition({
  name: 'slack',
  
  identifier: {
    // VRL script to extract user ID
    extractScript: `
      .user.id = .body.event.user
    `,
    // Fallback handler for anonymous users
    fallbackHandlerScript: `
      .user.id = "anonymous"
    `
  }
})

Secrets Management

Define secrets for sensitive configuration:
new IntegrationDefinition({
  name: 'myintegration',
  
  secrets: {
    SENTRY_DSN: {
      description: 'Sentry DSN for error tracking'
    },
    API_SECRET: {
      description: 'Secret key for API authentication'
    }
  }
})

// Access in implementation
export default new IntegrationImplementation({
  actions: {
    callApi: async ({ ctx }) => {
      const secret = ctx.secrets.API_SECRET
      // Use secret in API calls
    }
  }
})
Secrets are never exposed in logs or client-side code. They’re only accessible server-side in action handlers.

States

Integrations can define their own state:
new IntegrationDefinition({
  name: 'oauth-provider',
  
  states: {
    authToken: {
      type: 'integration',
      schema: z.object({
        accessToken: z.string(),
        refreshToken: z.string(),
        expiresAt: z.string()
      })
    }
  }
})

Publishing Integrations

1

Develop

Create and test your integration locally:
bp init
# Select "Integration" template
2

Deploy Private

Deploy to your workspace for testing:
bp deploy
3

Test

Install in a test bot and verify functionality
4

Deploy Public

Make it available on the Botpress Hub:
bp deploy --visibility public
Once a version is deployed as public, it cannot be modified. Always test thoroughly with private deployments first.

Advanced Features

Custom Metadata

new IntegrationDefinition({
  name: 'myintegration',
  
  attributes: {
    category: 'Communication & Channels',
    featured: 'true',
    pricing: 'free'
  }
})

ESBuild Configuration

new IntegrationDefinition({
  name: 'myintegration',
  
  __advanced: {
    esbuild: {
      external: ['some-native-module'],
      platform: 'node'
    }
  }
})

Best Practices

Error Handling

Always handle external API errors gracefully. Use try-catch blocks and return meaningful error messages.

Rate Limiting

Implement rate limiting to avoid hitting platform API limits. Use queues for high-volume operations.

Idempotency

Make webhook handlers idempotent. The same webhook may be delivered multiple times.

Validation

Validate all incoming data with Zod schemas. Never trust external data.

Next Steps

Interfaces

Learn how to implement standard interfaces

Plugins

Use interfaces to build cross-platform plugins

Examples

Browse integration examples

Hub

Explore published integrations