Agents Works

Создание Telegram и Slack ботов с ИИ-агентами: полное руководство
40 мин чтенияПродвинутый

Создание Telegram и Slack ботов с ИИ-агентом: полное руководство

В этой статье вы узнаете, как создать собственного Telegram-бота и Slack-бота, который будет использовать ИИ-агента из AgentsWorks для ответов на вопросы клиентов, анализа финансовых отчетов, генерации картинок и презентаций, и много чего еще.

Что вам понадобится

Перед началом убедитесь, что у вас есть:

КомпонентГде взять
ИИ-агент на AgentsWorksСоздать агента
API ключ агентаНастройки → Управление данными → Agent API Keys
Telegram-бот токен@BotFather
Slack приложениеapi.slack.com/apps

Подготовка: Если у вас ещё нет агента и API ключа, пройдите подготовку к интеграции.


Часть 1: Создание Telegram-бота

Шаг 1: Создайте бота через @BotFather

  1. Откройте @BotFather в Telegram
  2. Отправьте команду /newbot
  3. Укажите имя бота (например: MyCompanySupportBot)
  4. Укажите username (должен заканчиваться на bot, например: mycompany_support_bot)
  5. Скопируйте токен бота — он выглядит как: 123456789:ABCdefGHIjklMNOpqrsTUVwxyz

Шаг 2: Настройка webhook или polling

Выберите один из двух подходов:

Webhook (рекомендуется для продакшена)

  • Требует публичный сервер или сервис (ngrok, Heroku, VPS)
  • Более производительный
  • Не работает через polling (постоянные запросы)

Polling (для тестирования и разработки)

  • Не требует публичного сервера
  • Работает с локальной машины
  • Подходит для небольших проектов

Шаг 3: Пример кода на Node.js (polling)

Установка зависимостей:

Code
npm install node-telegram-bot-api dotenv

Файл .env:

Code
TELEGRAM_BOT_TOKEN=your_telegram_bot_token
AGENTSWORKS_API_KEY=your_agentsworks_api_key
AGENT_ID=your_agent_id

Файл bot.js:

Code
require('dotenv').config();
const TelegramBot = require('node-telegram-bot-api');

const token = process.env.TELEGRAM_BOT_TOKEN;
const bot = new TelegramBot(token, { polling: true });
const API_KEY = process.env.AGENTSWORKS_API_KEY;
const AGENT_ID = process.env.AGENT_ID;

// Хранилище контекста для каждого чата
const conversations = new Map();

// Функция вызова агента
async function callAgent(message, chatId) {
  try {
    // Получаем историю или создаем новую
    let history = conversations.get(chatId) || [];
    
    // Добавляем текущее сообщение
    history.push({ role: 'user', content: message });
    
    // Ограничиваем историю последними 20 сообщениями
    if (history.length > 20) {
      history = history.slice(-20);
    }
    
    const response = await fetch('https://agentsworks.ru/api/agents/v1/chat/completions', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        model: AGENT_ID,
        messages: history,
        agent_id: AGENT_ID,
        stream: false,
      }),
    });
    
    const data = await response.json();
    const agentResponse = data.choices[0].message.content;
    
    // Добавляем ответ агента в историю
    history.push({ role: 'assistant', content: agentResponse });
    conversations.set(chatId, history);
    
    return agentResponse;
  } catch (error) {
    console.error('Error calling agent:', error);
    throw error;
  }
}

// Обработка текстовых сообщений
bot.on('message', async (msg) => {
  const chatId = msg.chat.id;
  const userMessage = msg.text;
  
  if (!userMessage) return; // Игнорируем не текстовые сообщения
  
  console.log(`[${chatId}] User: ${userMessage}`);
  
  try {
    // Отправляем индикатор "печатает"
    await bot.sendChatAction(chatId, 'typing');
    
    // Вызываем агента
    const response = await callAgent(userMessage, chatId);
    
    // Отправляем ответ
    await bot.sendMessage(chatId, response);
    console.log(`[${chatId}] Bot: ${response.substring(0, 50)}...`);
    
  } catch (error) {
    console.error('Error:', error);
    await bot.sendMessage(
      chatId, 
      'Извините, произошла ошибка. Попробуйте позже.'
    );
  }
});

// Команда /start
bot.onText(/\/start/, async (msg) => {
  const chatId = msg.chat.id;
  await bot.sendMessage(
    chatId,
    'Привет! Я ИИ-ассистент, готовый помочь с вопросами по продукту. '
    'Просто напишите мне сообщение!'
  );
});

// Команда /help
bot.onText(/\/help/, async (msg) => {
  const chatId = msg.chat.id;
  await bot.sendMessage(
    chatId,
    'Доступные команды:\n'
    '/start — начать диалог\n'
    '/help — справка\n'
    '/clear — очистить историю диалога'
  );
});

// Команда /clear
bot.onText(/\/clear/, (msg) => {
  const chatId = msg.chat.id;
  conversations.delete(chatId);
  bot.sendMessage(chatId, 'История диалога очищена. Начнем сначала!');
});

console.log('Bot is running...');

Запуск:

Code
node bot.js

Шаг 4: Пример кода на Python (aiogram)

Установка зависимостей:

Code
pip install aiogram python-dotenv

Файл .env:

Code
TELEGRAM_BOT_TOKEN=your_telegram_bot_token
AGENTSWORKS_API_KEY=your_agentsworks_api_key
AGENT_ID=your_agent_id

Файл bot.py:

Code
import os
import asyncio
from dotenv import load_dotenv
from aiogram import Bot, Dispatcher, types
from aiogram.filters import Command
import requests

load_dotenv()

TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
API_KEY = os.getenv("AGENTSWORKS_API_KEY")
AGENT_ID = os.getenv("AGENT_ID")

bot = Bot(token=TOKEN)
dp = Dispatcher()

# Хранилище контекста
conversations = {}

def call_agent(message: str, chat_id: int) -> str:
    """Вызов ИИ-агента через API"""
    
    # Получаем или создаем историю
    history = conversations.get(chat_id, [])
    
    # Добавляем текущее сообщение
    history.append({"role": "user", "content": message})
    
    # Ограничиваем историю
    if len(history) > 20:
        history = history[-20:]
    
    response = requests.post(
        'https://agentsworks.ru/api/agents/v1/chat/completions',
        headers={
            'Authorization': f'Bearer {API_KEY}',
            'Content-Type': 'application/json',
        },
        json={
            'model': AGENT_ID,
            'messages': history,
            'agent_id': AGENT_ID,
            'stream': False,
        }
    )
    
    data = response.json()
    agent_response = data['choices'][0]['message']['content']
    
    # Добавляем ответ в историю
    history.append({"role": "assistant", "content": agent_response})
    conversations[chat_id] = history
    
    return agent_response

@dp.message(Command("start"))
async def cmd_start(message: types.Message):
    await message.answer(
        "Привет! Я ИИ-ассистент, готовый помочь с вопросами по продукту. "
        "Просто напишите мне сообщение!"
    )

@dp.message(Command("help"))
async def cmd_help(message: types.Message):
    await message.answer(
        "Доступные команды:\n"
        "/start — начать диалог\n"
        "/help — справка\n"
        "/clear — очистить историю диалога"
    )

@dp.message(Command("clear"))
async def cmd_clear(message: types.Message):
    chat_id = message.chat.id
    if chat_id in conversations:
        del conversations[chat_id]
    await message.answer("История диалога очищена. Начнем сначала!")

@dp.message()
async def handle_message(message: types.Message):
    chat_id = message.chat.id
    user_message = message.text
    
    if not user_message:
        return
    
    # Отправляем индикатор "печатает"
    await bot.send_chat_action(chat_id, 'typing')
    
    try:
        # Вызываем агента
        response = call_agent(user_message, chat_id)
        
        # Отправляем ответ
        await message.answer(response)
        
    except Exception as e:
        print(f"Error: {e}")
        await message.answer(
            "Извините, произошла ошибка. Попробуйте позже."
        )

async def main():
    print("Bot is running...")
    await dp.start_polling(bot)

if __name__ == "__main__":
    asyncio.run(main())

Запуск:

Code
python bot.py

Шаг 5: Настройка webhook (опционально)

Для продакшена рекомендуется использовать webhook вместо polling.

Пример на Node.js:

Code
const express = require('express');
const TelegramBot = require('node-telegram-bot-api');
require('dotenv').config();

const token = process.env.TELEGRAM_BOT_TOKEN;
const bot = new TelegramBot(token);
const app = express();
const PORT = process.env.PORT || 3000;

const WEBHOOK_URL = process.env.WEBHOOK_URL + '/webhook';

// Устанавливаем webhook
bot.setWebHook(WEBHOOK_URL).then(() => {
  console.log(`Webhook set to ${WEBHOOK_URL}`);
});

// Обработка webhook
app.post('/webhook', (req, res) => {
  bot.processUpdate(req.body);
  res.sendStatus(200);
});

// ... ваш код обработки сообщений

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Часть 2: Создание Slack-бота

Шаг 1: Создайте Slack-приложение

  1. Перейдите на api.slack.com/apps
  2. Нажмите «Create New App»«From scratch»
  3. Укажите имя приложения (например: AgentsWorks Support)
  4. Выберите workspace для установки
  5. Нажмите «Create App»

Шаг 2: Настройте Socket Mode

  1. Перейдите в раздел «Socket Mode»
  2. Включите Socket Mode
  3. Нажмите «Generate Token and Scopes»
  4. Скопируйте App-Level Token (начинается с xapp-)

Шаг 3: Настройте права бота (Bot Permissions)

  1. Перейдите в раздел «Bot Permissions»

  2. Добавьте следующие права (Scopes):

    • chat:write — отправлять сообщения
    • chat:write.customize — форматировать сообщения
    • app_mentions:read — читать упоминания
    • channels:history — читать историю каналов
    • groups:history — читать историю групп
    • im:history — читать личные сообщения
    • mpim:history — читать сообщения в групповых чатах
  3. Прокрутите вниз и нажмите «Install to Workspace»

  4. Скопируйте Bot User OAuth Token (начинается с xoxb-)

Шаг 4: Пример кода на Python (Slack Bolt)

Установка зависимостей:

Code
pip install slack-bolt python-dotenv

Файл .env:

Code
SLACK_BOT_TOKEN=xoxb-your-bot-token
SLACK_SIGNING_SECRET=your-signing-secret
SLACK_APP_TOKEN=xapp-your-app-token
AGENTSWORKS_API_KEY=your_agentsworks_api_key
AGENT_ID=your_agent_id

Файл slack_bot.py:

Code
import os
from dotenv import load_dotenv
from slack_bolt import App
from slack_bolt.adapter.socket_mode import SocketModeHandler
import requests

load_dotenv()

# Инициализация Slack-бота
app = App(
    token=os.environ.get("SLACK_BOT_TOKEN"),
    signing_secret=os.environ.get("SLACK_SIGNING_SECRET")
)

API_KEY = os.environ.get("AGENTSWORKS_API_KEY")
AGENT_ID = os.environ.get("AGENT_ID")

# Хранилище контекста
conversations = {}

def call_agent(message: str, channel_id: str) -> str:
    """Вызов ИИ-агента через API"""
    
    # Получаем или создаем историю
    history = conversations.get(channel_id, [])
    
    # Добавляем текущее сообщение
    history.append({"role": "user", "content": message})
    
    # Ограничиваем историю
    if len(history) > 20:
        history = history[-20:]
    
    response = requests.post(
        'https://agentsworks.ru/api/agents/v1/chat/completions',
        headers={
            'Authorization': f'Bearer {API_KEY}',
            'Content-Type': 'application/json',
        },
        json={
            'model': AGENT_ID,
            'messages': history,
            'agent_id': AGENT_ID,
            'stream': False,
        }
    )
    
    data = response.json()
    agent_response = data['choices'][0]['message']['content']
    
    # Добавляем ответ в историю
    history.append({"role": "assistant", "content": agent_response})
    conversations[channel_id] = history
    
    return agent_response

# Обработка упоминаний бота
@app.event("app_mention")
def handle_mention(event, say):
    """Обработка упоминания бота в канале"""
    user_message = event.get("text", "")
    channel_id = event.get("channel")
    bot_id = event.get("bot_id")
    
    # Удаляем упоминание бота из сообщения
    message = user_message.replace(f"<@{bot_id}>", "").strip()
    
    if not message:
        return
    
    try:
        # Вызываем агента
        response = call_agent(message, channel_id)
        
        # Отправляем ответ
        say(text=response)
        
    except Exception as e:
        print(f"Error: {e}")
        say(text="Извините, произошла ошибка. Попробуйте позже.")

# Обработка сообщений в личных сообщениях
@app.message()
def handle_direct_message(message, say):
    """Обработка личных сообщений боту"""
    channel_type = message.get("channel_type")
    
    # Обрабатываем только личные сообщения
    if channel_type != "im":
        return
    
    user_message = message.get("text", "")
    channel_id = message.get("channel")
    
    if not user_message:
        return
    
    try:
        # Вызываем агента
        response = call_agent(user_message, channel_id)
        
        # Отправляем ответ
        say(text=response)
        
    except Exception as e:
        print(f"Error: {e}")
        say(text="Извините, произошла ошибка. Попробуйте позже.")

# Слэш-команда /ask
@app.command("/ask")
def handle_ask_command(ack, body, respond):
    """Слэш-команда для запроса к агенту"""
    ack()
    
    user_message = body.get("text", "")
    channel_id = body.get("channel_id")
    
    if not user_message:
        respond(text="Пожалуйста, укажите ваш запрос после /ask")
        return
    
    try:
        # Вызываем агента
        response = call_agent(user_message, channel_id)
        
        # Отправляем ответ
        respond(text=response)
        
    except Exception as e:
        print(f"Error: {e}")
        respond(text="Извините, произошла ошибка. Попробуйте позже.")

# Запуск бота
if __name__ == "__main__":
    handler = SocketModeHandler(
        app, 
        os.environ.get("SLACK_APP_TOKEN")
    )
    handler.start()

Запуск:

Code
python slack_bot.py

Шаг 5: Добавьте слэш-команды (опционально)

  1. Перейдите в раздел «Slash Commands» вашего приложения
  2. Нажмите «Create New Command»
  3. Создайте команду:
    • Command: /ask
    • Request URL: можно оставить пустым для Socket Mode
    • Description: Задать вопрос ИИ-ассистенту
    • Usage Hint: ваш вопрос
  4. Сохраните и установите приложение в workspace

Часть 3: Расширенные возможности

3.1 Добавление кнопок и меню

Telegram — inline кнопки:

Code
bot.onText(/\/menu/, async (msg) => {
  const chatId = msg.chat.id;
  
  const keyboard = {
    reply_markup: {
      inline_keyboard: [
        [
          { text: '📚 Документация', callback_data: 'docs' },
          { text: '💬 Поддержка', callback_data: 'support' }
        ],
        [
          { text: '💰 Тарифы', callback_data: 'pricing' },
          { text: '📞 Контакты', callback_data: 'contacts' }
        ]
      ]
    }
  };
  
  await bot.sendMessage(
    chatId,
    'Что вас интересует?',
    keyboard
  );
});

// Обработка нажатий на кнопки
bot.on('callback_query', async (query) => {
  const chatId = query.message.chat.id;
  const data = query.data;
  
  let question = '';
  switch (data) {
    case 'docs': question = 'Расскажи о документации'; break;
    case 'support': question = 'Как связаться с поддержкой?'; break;
    case 'pricing': question = 'Какие тарифы доступны?'; break;
    case 'contacts': question = 'Контакты компании'; break;
  }
  
  const response = await callAgent(question, chatId);
  await bot.sendMessage(chatId, response);
  
  await bot.answerCallbackQuery(query.id);
});

Slack — Block Kit:

Code
from slack_sdk import WebClient

client = WebClient(token=os.environ.get("SLACK_BOT_TOKEN"))

def send_buttons(channel):
    """Отправка кнопок в Slack"""
    blocks = [
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "Что вас интересует?"
            },
            "accessory": {
                "type": "static_select",
                "placeholder": {
                    "type": "plain_text",
                    "text": "Выберите вариант"
                },
                "options": [
                    {
                        "text": {
                            "type": "plain_text",
                            "text": "📚 Документация"
                        },
                        "value": "docs"
                    },
                    {
                        "text": {
                            "type": "plain_text",
                            "text": "💬 Поддержка"
                        },
                        "value": "support"
                    },
                    {
                        "text": {
                            "type": "plain_text",
                            "text": "💰 Тарифы"
                        },
                        "value": "pricing"
                    }
                ]
            }
        }
    ]
    
    client.chat_postMessage(
        channel=channel,
        blocks=blocks
    )

3.2 Сохранение истории в базе данных

Для продакшена используйте Redis или PostgreSQL вместо хранения в памяти:

Пример с Redis (Python):

Code
import redis
import json

# Подключение к Redis
redis_client = redis.Redis(host='localhost', port=6379, db=0)

def get_history(chat_id: str) -> list:
    """Получение истории из Redis"""
    data = redis_client.get(f"history:{chat_id}")
    if data:
        return json.loads(data)
    return []

def save_history(chat_id: str, history: list):
    """Сохранение истории в Redis"""
    redis_client.setex(
        f"history:{chat_id}", 
        3600,  # 1 час TTL
        json.dumps(history)
    )

def call_agent(message: str, chat_id: str) -> str:
    """Вызов агента с сохранением в Redis"""
    
    # Получаем историю из Redis
    history = get_history(chat_id)
    
    # Добавляем сообщение
    history.append({"role": "user", "content": message})
    
    # Ограничиваем историю
    if len(history) > 20:
        history = history[-20:]
    
    # Вызов агента
    response = requests.post(
        'https://agentsworks.ru/api/agents/v1/chat/completions',
        headers={
            'Authorization': f'Bearer {API_KEY}',
            'Content-Type': 'application/json',
        },
        json={
            'model': AGENT_ID,
            'messages': history,
            'agent_id': AGENT_ID,
            'stream': False,
        }
    )
    
    data = response.json()
    agent_response = data['choices'][0]['message']['content']
    
    # Добавляем ответ
    history.append({"role": "assistant", "content": agent_response})
    
    # Сохраняем в Redis
    save_history(chat_id, history)
    
    return agent_response

3.3 Обработка длинных сообщений

Telegram и Slack имеют ограничения на длину сообщений. Разбивайте длинные ответы:

Code
MAX_MESSAGE_LENGTH = 4096  # для Telegram

def split_message(text: str, max_length: int = MAX_MESSAGE_LENGTH) -> list:
    """Разделение длинного сообщения на части"""
    if len(text) <= max_length:
        return [text]
    
    parts = []
    current_part = ""
    
    # Разбиваем по строкам
    for line in text.split('\n'):
        if len(current_part) + len(line) + 1 <= max_length:
            current_part += line + '\n'
        else:
            if current_part:
                parts.append(current_part.strip())
            current_part = line + '\n'
    
    if current_part:
        parts.append(current_part.strip())
    
    return parts

# Использование
response = call_agent(user_message, chat_id)
for part in split_message(response):
    await message.answer(part)

3.4 Добавление анимации загрузки

Telegram:

Code
// Отправляем "печатает"
await bot.sendChatAction(chatId, 'typing');

// Или для задержки
await bot.sendChatAction(chatId, 'upload_photo');

Slack:

Code
from slack_sdk import WebClient
import time

client = WebClient(token=os.environ.get("SLACK_BOT_TOKEN"))

# Отправляем сообщение с индикатором загрузки
response = client.chat_postMessage(
    channel=channel,
    text="🤔 Думаю..."
)

timestamp = response["message"]["ts"]

# Получаем ответ от агента
agent_response = call_agent(user_message, channel)

# Обновляем сообщение
client.chat_update(
    channel=channel,
    ts=timestamp,
    text=agent_response
)

Часть 4: Деплой в продакшн

4.1 Хостинг для Node.js (Telegram)

Варианты:

  • Heroku — бесплатный для маленьких проектов
  • Railway — простой деплой
  • Render — современный хостинг
  • VPS — полный контроль

Пример deployment на Railway:

  1. Push вашего кода на GitHub
  2. Подключите GitHub к Railway
  3. Добавьте переменные окружения
  4. Deploy! 🚀

4.2 Хостинг для Python (Slack)

Варианты:

4.3 Настройка мониторинга

Code
import logging
from datetime import datetime

# Настройка логирования
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    filename='bot.log'
)

logger = logging.getLogger(__name__)

# Использование
logger.info(f"[{chat_id}] User: {user_message}")
logger.info(f"[{chat_id}] Bot: {response[:50]}...")

4.4 Настройка Health Check

Code
// Express сервер с health check
const express = require('express');
const app = express();

app.get('/health', (req, res) => {
  res.status(200).json({
    status: 'ok',
    timestamp: new Date().toISOString(),
    uptime: process.uptime()
  });
});

app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Чек-лист запуска

ШагЗадачаСтатус
1Создать ИИ-агента на AgentsWorks
2Получить API ключ
3Создать Telegram-бота (@BotFather)
4Скопировать токен бота
5Разработать код бота (Python или Node.js)
6Протестировать локально
7Настроить webhook (для продакшена)
8Деплой на хостинг
9Настроить мониторинг и логирование
10Запустить в продакшн

Время на настройку: 1-3 часа (включая деплой)


Лучшие практики

Безопасность 🔒

  • ✅ Никогда не коммитьте API ключи в git
  • ✅ Используйте .env файлы и переменные окружения
  • ✅ Ограничьте права бота до минимума
  • ✅ Валидируйте входные данные
  • ✅ Используйте rate limiting для защиты от спама

UX/пользовательский опыт 💬

  • ✅ Добавьте приветственное сообщение
  • ✅ Используйте индикатор "печатает"
  • ✅ Форматируйте ответы (Markdown, HTML)
  • ✅ Разбивайте длинные сообщения
  • ✅ Добавьте кнопку "Связаться с человеком"

Производительность ⚡

  • ✅ Используйте Redis для хранения истории
  • ✅ Кэшируйте частые ответы
  • ✅ Настройте соединение пулами для базы данных
  • ✅ Используйте async/await для асинхронных операций
  • ✅ Настройте таймауты для API запросов

Мониторинг 📊

  • ✅ Логируйте все запросы и ответы
  • ✅ Отслеживайте качество ответов
  • ✅ Анализируйте частые вопросы
  • ✅ Настройте алерты на ошибки
  • ✅ Отслеживайте метрики (uptime, latency)

Решение проблем

Бот не отвечает

  1. Проверьте токен бота
  2. Проверьте API ключ агента
  3. Проверьте соединение с интернетом
  4. Посмотрите логи на ошибки

Ошибка 401 Unauthorized

  • Неверный API ключ или токен
  • API ключ истёк
  • Проверьте переменные окружения

Ошибка 429 Too Many Requests

  • Слишком много запросов к API
  • Добавьте rate limiting
  • Увеличьте интервал между запросами

Бот отвечает с задержкой

  • Проверьте соединение с agentsworks.ru
  • Увеличьте timeout для API запросов
  • Оптимизируйте код
  • Используйте асинхронные операции

Заключение

Создание Telegram-бота и Slack-бота с интеграцией ИИ-агента — это реализуемая задача, которая позволит автоматизировать поддержку и общение с клиентами.

Что вы получаете:

  • ✅ Мгновенные ответы клиентам 24/7
  • ✅ Единый агент во всех каналах коммуникации
  • ✅ Возможность масштабирования
  • ✅ Автоматизация рутинных задач
  • ✅ Экономию бюджета на поддержку

Следующие шаги:

  1. Выберите платформу (Telegram или Slack)
  2. Скопируйте готовый код из статьи
  3. Адаптируйте под свои нужды
  4. Протестируйте локально
  5. Деплой в продакшн

Нужна помощь с интеграцией?

Свяжитесь с нами для консультации:

  • Техническая поддержка на русском
  • Готовые примеры кода
  • Помощь в настройке интеграций

Создать агента бесплатно →


Полезные ссылки


Следующие шаги:

ИнтеграцииAPIЧат-ботыИИ агентыАвтоматизация

Ещё

Блок в разработке

Все статьи