Урок 6. Темы в боте и расширенный контекст — Курс OpenClaw
Урок 6

Урок 6. Темы в боте и расширенный контекст

~20 мин чтения ·
Содержание

Если ты много общаешься с ботом, личный чат быстро превращается в свалку: серверные дела вперемешку с заметками про поездку, кодом и личными напоминаниями. В этом уроке разберёмся, как разложить личный чат с ботом по темам — это новая фича Telegram, бот может включить её сам и сам же создавать темы. Заодно посмотрим на две команды, без которых живое общение с ботом некомфортно: /btw (быстрый побочный вопрос) и steering (вмешательство в уже идущий ответ).

Темы прямо в чате с ботом

Что это и зачем

Один и тот же 1-на-1 чат с ботом разбивается на несколько параллельных лент со своими названиями и иконками. Сверху чата появляется навигация по разделам, у каждой темы — своя история и свой контекст.

Чат с ботом, разбитый на темы: Сервер и инфраструктура, Быстрые задачи, Код и разработка, Память и настройки, Исследования, Проекты, Поездки и планирование, Напоминания и ожидания
Темы прямо в DM с ботом — каждая со своим названием и иконкой

Зачем это нужно:

  • Контекст одного направления не сваливается в другое. Утром обсуждал миграцию, вечером пишешь про поездку — бот не тащит серверные детали в разговор про авиабилеты.
  • Каждая тема доступна одним тапом из шапки чата — не нужно скроллить ленту назад.
  • В каждой теме у бота своя сессия: своя история, свой контекст, свои настройки.
  • Можно завести «постоянные» темы под повторяющиеся направления (Сервер, Код, Поездки, Напоминания) и не плодить отдельных ботов.

Включаем Threaded Mode в BotFather

Темы в личном чате с ботом нужно сначала разрешить на стороне бота. Это делается в BotFather:

  1. Открой @BotFather → выбери своего бота → раздел Bot Settings.
  2. Найди пункт про Threads / Threaded Mode / разрешение на создание тем в DM. Точное название иногда меняется, ориентируйся на формулировки про threads и темы в личных чатах.
  3. Включи Threaded Mode.
Threads Settings в BotFather: тумблер Threaded Mode включён, Disallow users to create new threads выключен
Threads Settings в BotFather

Под ним есть второй тумблер — Disallow users to create new threads. С ним стоит разобраться отдельно, потому что он сильно меняет поведение чата.

Когда Disallow users to create new threads выключен, каждое новое сообщение, которое ты отправляешь мимо уже существующей темы, автоматически создаёт новую тему. Это удобно на этапе ознакомления — наглядно видно, как работают темы, и каждая мысль сразу получает свою «папку». Но в повседневной работе это быстро мешает: чат заваливается одноразовыми темами «привет», «а ещё», «короче», в которых лежит по одному сообщению. Поэтому в нормальном режиме этот тумблер включают — сообщения без темы идут в общую ленту, а темы заводятся осмысленно: либо тобой вручную через интерфейс Telegram, либо ботом по твоему запросу.

После включения Threaded Mode у тебя в личном чате с ботом появляется навигация по темам, а у бота — право их создавать и переименовывать.

Как OpenClaw работает с темами в DM

Внутри Telegram каждая тема в DM — это просто числовой thread ID, который автоматически прикрепляется к сообщениям в этой теме. OpenClaw на основе этого ID делает три вещи:

  • Отдельная сессия на каждую тему. Сообщения из разных тем идут в разные сессии — у каждой темы своя история, свой контекст, своя память сессии.
  • Сохраняет thread ID в исходящих ответах, чтобы ответ бота приходил именно в ту тему, откуда был задан вопрос.
  • Прокидывает thread ID в шаблоны и логику ответа, если ты сам захочешь ветвить поведение по теме.

С точки зрения авторизации это всё ещё DM — tools.elevated.allowFrom.telegram со списком твоих ID работает в любой теме. Никаких дополнительных настроек в openclaw.json после включения тем в BotFather прописывать не нужно: OpenClaw подхватит темы автоматически.

Бот сам создаёт и поддерживает темы

Главное удобство — темы можно не придумывать вручную. У бота есть действие topic-create (под капотом — Telegram-метод createForumTopic), и оно включено по умолчанию. И самое приятное: списком направлений тоже не обязательно загружать его руками — бот уже знает, о чём вы регулярно говорите, и сам предложит разумную структуру. Достаточно написать:

Посмотри на свою память и на наши последние разговоры. Выдели направления, которые повторяются чаще всего, и заведи под них темы прямо здесь в Telegram. Названия и иконки придумай сам. Соответствие thread ID → название сохрани в TOPICS.md, чтобы дальше понимал, куда что относить.

Бот пройдётся по MEMORY.md, дневным заметкам и текущей сессии, выделит повторяющиеся направления (у каждого пользователя они получатся свои), создаст под них темы, выставит иконки и запишет соответствие thread ID → название в TOPICS.md. Дальше можно подтягивать новые темы по ходу:

Заведи отдельную тему «Wildberries API» и положи туда заметку про авторизацию.
Перенеси разговор про деплой в тему «Сервер и инфраструктура».
Каждое утро публикуй свод задач в тему «Быстрые задачи».

Зачем нужен TOPICS.md. Telegram отдаёт боту thread ID числом (3, 7, 42), а не названием. Без таблички соответствия в памяти бот не знает, что «3» — это «Код и разработка», особенно после нового запуска или сброса сессии. Файл вида:

# Темы в DM

| ID | Название |
|----|----------|
| 2  | 📺 Сервер и инфраструктура |
| 3  | ⚡ Быстрые задачи |
| 4  | 🔧 Код и разработка |
| 5  | 🧠 Память и настройки |
| 6  | 🧪 Исследования |
| 7  | 📌 Проекты |
| 8  | ✈️ Поездки и планирование |
| 9  | ⏰ Напоминания и ожидания |

— решает проблему раз и навсегда. Бот сам его обновит, когда заведёт новую тему.

Разные настройки для разных тем

Поскольку каждая тема в DM — это отдельная сессия, у неё может быть свой systemPrompt, свой набор навыков, свои правила. Конфигурируется так же, как темы форума, через channels.telegram.groups.<chatId>.topics.<threadId> — chatId здесь будет твоим Telegram user ID, потому что DM с точки зрения routing-а — это личный «канал» между ботом и тобой.

Пример: в теме «Поездки» включаем только travel-search, в теме «Код и разработка» — дев-инструменты:

{
  channels: {
    telegram: {
      groups: {
        "123456789": {           // твой Telegram user ID
          topics: {
            "4": {                // Код и разработка
              skills: ["web-search-plus", "github"],
              systemPrompt: "Ты дев-ассистент. Отвечай по делу, проверяй код на безопасность."
            },
            "8": {                // Поездки
              skills: ["travel-search", "web-search-plus"]
            }
          }
        }
      }
    }
  }
}

После правки:

openclaw gateway restart

Эта часть конфига — продвинутая и может в будущем измениться: сам факт DM-thread routing’а в OpenClaw встроен надёжно, а вот форма «развешивания» systemPrompt/skills на конкретные темы DM — менее обкатанная. Если в openclaw doctor или логах увидишь предупреждение про неподдерживаемое поле — скинь скрин в телеграм-канал курса, разберёмся вместе.

Если хочется отдельную память и навыки для каждой темы целиком, проще пока не настраивать темы вручную, а опираться на то, что у каждой темы и так свой ключ сессии: бот в каждой теме помнит только её собственный контекст, и этого на старте достаточно.

/btw — побочный вопрос без последствий

Бывает: ты обсуждаешь с ботом большую задачу (например, миграцию). Контекст разговора уже плотный, бот в курсе, что ты делаешь. И тут хочется быстро спросить «а сколько 17 × 19?» или «какой сейчас курс доллара?» — но не хочется, чтобы этот побочный вопрос осел в истории и тащился в контекст потом.

Для этого есть /btw:

/btw сколько сейчас занимает свободного места на диске

Что происходит:

  1. Бот смотрит на текущий контекст сессии — он видит, о чём ты говорил.
  2. Делает отдельный одноразовый вызов модели без инструментов и без агентского цикла.
  3. Возвращает ответ как side-result — отдельный, визуально выделенный ответ.
  4. Ничего не пишет в историю сессии. После перезагрузки этого обмена не будет.

Правило простое: /btw — это «спрошу мимоходом, забудем». Если ответ нужен дальше в работе — спрашивай обычным сообщением.

Чем /btw отличается от /new:

  • /new начинает чистую сессию, теряя весь контекст. Хорошо для смены задачи целиком.
  • /btw сохраняет текущую сессию нетронутой, не тратит контекст и сразу даёт ответ. Хорошо для микро-вопросов внутри большой задачи.

Где /btw особенно полезен:

  • Идёт долгий run (бот что-то делает несколько минут), а ты хочешь уточнить что-то параллельно. Обычное сообщение встанет в очередь и подождёт окончания. /btw отвечает сразу, не вмешиваясь в основной запуск.
  • Нужно быстро посчитать или проверить факт, не засоряя память сессии.
  • Хочешь спросить «что сейчас происходит, на каком файле мы остановились» — /btw даст ответ и не запутает основную задачу.

Примеры:

/btw на каком файле мы сейчас?
/btw как называлась команда из урока 3?
/btw 17 * 19
/btw переведи рубли в доллары: 84 000 ₽

Подробности — в документации /btw.

Active-run steering — править бота на лету

Бот ушёл выполнять длинную задачу: ставит пакеты, лезет в API, разбирается с конфигом. Прошла минута, ты понимаешь, что он идёт не туда — взял не ту библиотеку или начал делать лишнее. Хочется крикнуть «стоп, не туда!» и направить.

Для этого есть steering — возможность вмешаться в уже идущий запуск. По умолчанию OpenClaw собирает все твои сообщения, пока бот занят, и отдаёт их одной пачкой после окончания текущего ответа. Это режим collect. Steering — другой режим: новое сообщение впрыскивается в текущий run, бот видит его на следующей границе цикла и корректирует поведение.

Режимы очереди

OpenClaw умеет несколько стратегий обработки сообщений во время активного запуска (документация):

Режим Что делает
collect (по умолчанию) Все сообщения, пришедшие за время run’а, склеиваются в один followup-запрос. Бот закончит то, что начал, потом ответит на всё разом.
followup Сообщения копятся, но не склеиваются — каждое запускает свой ход после окончания текущего.
steer Сообщение впрыскивается в текущий run. Бот увидит его на ближайшей границе модели/инструмента и учтёт. История продолжается.
steer-backlog То же, что steer, плюс сообщение сохраняется как followup — после steer’а бот ещё раз ответит уже как на отдельный ход.
interrupt (legacy) Жёстко прерывает текущий run и запускает новый с последним сообщением.

Steering важно понимать правильно: твоё сообщение прилетает между шагами модели. Бот сначала доделает текущий tool call (например, докачает файл), потом увидит твоё сообщение, и только потом решит, что делать дальше. То есть «выключить» уже отправленный shell-command нельзя, но можно перенаправить логику до следующего шага.

Что значит «склеиваются» в collect

collect опирается на debounce — окно тишины перед запуском followup-хода. Дефолтное значение в OpenClaw — debounceMs: 1000, то есть 1 секунда. Логика такая:

  • Ты отправил сообщение, пока бот ещё работает или сразу после — оно попадает в очередь.
  • Каждое следующее сообщение, пришедшее в течение 1 секунды после предыдущего, склеивается с ним в одну пачку.
  • Как только проходит 1 секунда тишины (и текущий run закончился), вся пачка уходит боту одним followup-запросом, и он отвечает на неё разом.
  • Если хоть одно новое сообщение пришло до истечения этой секунды — таймер сбрасывается, окно продлевается.

На практике это значит: успел набрать и отправить следующую мысль за ~1 секунду — она приклеится к предыдущей. Замешкался дольше — стартует отдельный ход. Поэтому короткий «дописал, забыл, вот ещё» обычно склеивается, а пауза в полминуты на чай — нет.

Дефолт в 1 секунду — компромисс между «не сидеть лишнее у Telegram-индикатора печати» и «дать пользователю успеть дописать продолжение». Если ты пишешь медленно или часто отправляешь мысли по частям, его стоит увеличить — например, до 2–3 секунд через /queue collect debounce:2s (тогда поток коротких сообщений склеится надёжнее, но на каждое последнее придётся подождать пару лишних секунд перед стартом ответа). Если, наоборот, хочется максимально быстрых реакций и одиночных ответов — поставь debounce:0 (тогда followup стартует сразу после конца run’а, без склейки).

Ещё две настройки рядом, которые редко трогают, но полезно знать:

  • cap — максимум сообщений в одной пачке (дефолт 20). Если ты упёрся в лимит, дальше включается drop.
  • drop — что делать при переполнении: old (выбросить старые сообщения из пачки), new (выбросить новые, оставить старые), summarize (дефолт — склеить выброшенные в краткую сводку и подложить в followup, чтобы ничего не потерялось по смыслу).

Команда /queue

Режим переключается на лету, без правки конфига:

/queue steer            # хочу вмешиваться в текущий run
/queue collect          # вернуть дефолт (склеивать в один followup)
/queue steer-backlog    # вмешаться сейчас + получить отдельный followup-ответ
/queue default          # сбросить override для сессии

Можно подкрутить параметры:

/queue collect debounce:2s cap:25 drop:summarize
  • debounce — сколько ждать тишины перед запуском followup-хода (защищает от «продолжай, продолжай» одно за другим).
  • cap — лимит сообщений в очереди.
  • drop — что делать при переполнении: old (выбросить старые), new (выбросить новые), summarize (склеить выброшенные в краткую сводку и подложить в followup).

Постоянно прописать в ~/.openclaw/openclaw.json:

{
  messages: {
    queue: {
      mode: "collect",
      debounceMs: 1000,
      cap: 20,
      drop: "summarize",
      byChannel: {
        telegram: "steer",   // в Telegram удобно вмешиваться на лету
        discord: "collect"
      }
    }
  }
}

Что выбрать на практике

  • collect (дефолт) — оставляй, если у тебя в целом одиночные запросы и ты редко хочешь что-то поправить в процессе. Самый предсказуемый режим: один input → один output.
  • steer — включай, если часто работаешь с длинными задачами в Telegram и хочешь корректировать ход в реальном времени. Минус: можно случайно «толкнуть» бота под локоть короткой репликой и получить неожиданный поворот.
  • steer-backlog — на любителя. Получаешь два ответа: один с учётом steer’а, второй уже как followup. Полезно, если хочется явно увидеть, что бот понял твоё уточнение, а потом отдельно ответил на него же.
  • interrupt — старый режим, в большинстве случаев не нужен. Используй только если действительно хочешь оборвать выполнение и начать с нуля по последнему сообщению.

Удобный паттерн для Telegram — поставить steer глобально и держать /btw в кармане для микро-вопросов мимо очереди. Тогда вместо «отправил → ждёшь → дополнил → ждёшь» получается живой разговор: бот занят, ты подкручиваешь по ходу, он подхватывает.

Если что-то пошло не так

Бот не создаёт темы. Проверь, что в группе включён режим форума и что в BotFather у бота включён Threaded Mode.

Что дальше

С темами, /btw и steering жить с ботом в Telegram становится заметно удобнее. В следующем уроке — про то, как держать бота в форме на длинной дистанции:

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

Если что-то не получается или есть вопросы — заходи в телеграм-канал курса. Там помогут разобраться.

Обсуждение