Blueprint

Blueprint: Telegram + Claude

Свой Telegram как память и руки агента — локальный индекс, поиск через MCP, отправка только после твоего ✅

22 сентября 2026 г. · 39 мин чтения
Для кого

Для тех, у кого Telegram — основной канал общения, и кто хочет дать агенту доступ к переписке без стороннего сервиса и без риска, что он напишет что-то от твоего имени сам

Blueprint: Telegram + Claude

Прочитай до того, как строить. Личный Telegram-userbot по MTProto — серая зона Terms of Service: Telegram терпит личное использование, но не одобряет automation, spam и scraping. Session-файл = полный доступ к аккаунту: храни как секрет (chmod 0600, не в git, с бэкапом) — кто получил файл, получил твой Telegram целиком. Никаких mass-send, broadcast и scraping чатов, в которых ты не member. Любой outbound — только через approval gate: финальный ✅ всегда твой, никакого «trusted» пути в обход карточки.

Status: living. Все 4 базовые фазы реализованы и обкатаны в реальном использовании (месяцы in production), сверху с августа 2026 вырос пятый слой — штаб-контур: мост из Telegram к оркестратору (@hq), алерты прод-ботов в инбокс оркестратора, scoped-MCP для второго агента и второй бот с собственной персоной для чужих групп. Архитектура, рабочие паттерны и грабли ниже — из практики, а не из плана. Документ прирастает по мере роста системы; v2.2 (19.09.2026) добавляет Phase 5 и правит дефолты, которые не выдержали эксплуатации (окно approval 5 → 30 мин).

Telegram копит твои разговоры годами — клиенты, друзья, рабочие чаты, каналы по теме. Поиск через Telegram UI слабый, граф связей теряется, а если ты не у компьютера — ты вне Claude. И при этом отдать Claude доступ к Telegram-account через сторонний сервис — нет, спасибо.

Этот Blueprint решает три проблемы одной системой:

  1. Поиск/анализ по своему Telegram — Claude получает MCP-инструменты для full-text search, чтения чатов, поиска контактов
  2. Безопасный outbound — Claude может предлагать сообщения от твоего имени, но физически отправляет только после твоего ✅ в Telegram-карточке с use-once токеном
  3. Pocket Claude — отдельный bot становится chat-интерфейсом к Claude Code в твоём vault’е, доступным с телефона
  4. Штаб-контур (Phase 5) — тот же бот становится входом к твоему оркестратору (@hq … уходит не в карманную сессию, а в живую главную сессию агента), группа с алертами прод-ботов льётся в его инбокс, а второй бот с персоной живёт в чужих группах по белому списку

Данные — локально. Никаких сторонних сервисов с доступом к твоей переписке: индекс в SQLite на твоей машине, MCP-сервер на stdio, HTTP API на 127.0.0.1, approval bot для callback’ов через стандартный Telegram Bot API. Честная оговорка: инференс живёт там, где живёт твой агент — у Claude Code это API Anthropic, и всё, что агент читает из индекса, попадает в контекст модели. Это не «облачный сервис с доступом к переписке», но и не «ничего не покидает Mac»; для бота в чужой группе (Phase 5) это надо проговаривать участникам.

Что ты получишь

  • Local daemon который индексирует все входящие сообщения в SQLite + FTS5 в реальном времени, плюс backfill за N дней при первом запуске
  • MCP-инструменты для Claude в любом MCP-клиенте (Claude Code, Cursor, Codex): read-набор (tg_search_messages, tg_search_contacts, tg_get_chat_info, tg_read_chat, tg_list_recent_chats), outbound (tg_propose_send), admin (tg_backfill_chat — подтянуть историю за пределами launch-окна, tg_transcribe_media — голосовые/кружочки → текст) и scoped-режим сервера (--scope digest: второй агент видит только каналы из правил дайджеста и тулзу tg_digest, а не всю переписку)
  • Транскрибация голосовых и видео-кружочков локальным Whisper (offline) — распознанный текст кэшируется в БД и становится searchable наравне с обычными сообщениями
  • Approval bot в Telegram — Claude предлагает текст, ты получаешь карточку с ✅ Send / ✏️ Edit / ❌ Cancel, физическая отправка только после approve, токен use-once и привязан к (chat_id, sha256(text))
  • Persistent chat-сессия с Claude через того же бота: пишешь DM → daemon spawn’ит coding-agent в твоём vault’е через --resume, ответ возвращается reply’ем
  • Audit log каждого outbound-события + ежедневный digest
  • Kill switch одной командой
  • Мост к оркестратору (Phase 5): сообщение боту с префиксом @hq минует карманную сессию и падает прямо в инбокс твоей главной агент-сессии; группа «Alerts» с админ-алертами прод-ботов — туда же
  • Второй бот с персоной для чужих групп (Phase 5): свой токен, свой белый список, свои таблицы; расшифровывает голосовые всем участникам, разбирает фото, рисует, делает итоги дня и напоминания — и физически не имеет доступа к индексу переписки, vault’у и мосту

Как применить

  1. Открой coding agent (Claude Code, Cursor, Codex) в trusted directory, где ты обычно держишь персональный код / эксперименты (НЕ в vault’е — там будут только логи)
  2. Покажи ему этот Blueprint: «собери по этому Blueprint Telegram + Claude integration у меня»
  3. Агент задаст вопросы из секции Вопросы для адаптации
  4. Ответь про свою OS, vault, какие чаты критичные, как организовать always-on
  5. Агент создаст project, реализует 4 фазы по очереди — каждая фаза самостоятельно ценна, можно остановиться на любой
  6. После фазы 3 ты заведёшь bot в @BotFather и скажешь его token агенту

Контекст: одна сессия coding-agent’а, отдельный git-репо для проекта (НЕ внутри vault), data-dir в OS-стандартном месте. Telegram API credentials получаются на my.telegram.org (нужны api_id + api_hash).

Когда использовать

  • Telegram — твой основной канал коммуникации, и в нём копятся месяцы/годы переписки
  • Поиск через Telegram UI тебя бесит (медленный, нет boolean, нет advanced syntax)
  • Хочется задавать Claude вопросы по своей переписке: «что мы решили с X на прошлой неделе?», «найди контактов из Y», «дай дайджест канала Z»
  • Хочется чтобы Claude мог писать с твоего account, но без риска разослать что-то странное — каждое сообщение через approval
  • Хочется Claude-сессию доступной с телефона / в дороге — без терминала и без ssh
  • Готов держать always-on daemon на своей машине (десктоп / NAS / VPS под твоим контролем)

Когда не использовать

  • Telegram у тебя на минималках (несколько контактов, паблик-каналы), нет смысла
  • Тебя устраивает Telegram UI search
  • Ты не доверяешь идее «своего MTProto userbot’а» (Telegram tolerates personal use, но не одобряет — gray zone)
  • Ты не хочешь держать always-on процесс — без daemon’а индекс отстаёт от реальности

Ключевая идея

Approval gate — единственный safety story для outbound. Userbot читает всё (он же — твой account через MTProto). Outbound идёт только через bot-side approval с use-once токенами. Никакого «trusted» пути в обход карточки. Если карточка сломалась — никто не пишет.

Разделение ролей:

Человек:

  • Создаёт Telegram API credentials и approval bot (one-time setup)
  • Получает approval-карточки в Saved Messages, нажимает ✅/✏️/❌
  • Использует MCP-инструменты в coding agent’е для read-операций
  • Пишет тому же боту чтобы говорить с Claude в vault’е (Phase 4)
  • Решает, какие рабочие паттерны и расширения ему нужны (см. «Как мы работаем» / Roadmap)

Coding agent (Claude/Codex/etc.):

  • Использует tg_* MCP-инструменты для поиска/анализа Telegram
  • Предлагает outbound через tg_propose_send — НИКОГДА не отправляет напрямую
  • В Phase 4 chat-сессии может вызвать любой tg_* инструмент включая outbound (всё равно через approval)

Daemon (background):

  • Индексирует входящие в реальном времени
  • Держит approval-bot polling
  • Spawn’ит coding-agent subprocess для chat-сессий
  • Audit log, rate limits, kill switch — всё в нём

Архитектура

                ┌─────────────────────────────────┐
                │      Твой Telegram account       │
                │  (private chats, groups,         │
                │   channels you subscribe to)     │
                └─────────────────┬───────────────┘
                                  │ MTProto (userbot SDK)
                                  ▼
       ┌─────────────────────────────────────────────────┐
       │   Local daemon (always-on background service)    │
       │                                                  │
       │   ┌──────────────┐    ┌────────────────────┐    │
       │   │   Indexer    │───→│ SQLite + FTS5      │    │
       │   │  (New/Edit/  │    │  • messages        │    │
       │   │   Deleted)   │    │  • transcripts     │    │
       │   │  + Whisper   │    │  • chats / users   │    │
       │   │  transcribe  │    │  • audit_log       │    │
       │   └──────────────┘    │  • approval_reqs   │    │
       │                       └─────────┬──────────┘    │
       │                                 │               │
       │   ┌─────────────────────────────▼─────────┐     │
       │   │  Local HTTP API (127.0.0.1, X-API-Key)│     │
       │   │  /search /chats /outbound /control    │     │
       │   └─┬───────────────────┬───────────────┬─┘     │
       │     │                   │               │       │
       │     ▼                   ▼               ▼       │
       │  ┌─────────┐    ┌──────────────┐  ┌──────────┐ │
       │  │MCP shim │    │Approval bot  │  │  CLI     │ │
       │  │(stdio,  │    │(Bot API,     │  │ commands │ │
       │  │ 8 tools)│    │ separate     │  │ for ops  │ │
       │  └────┬────┘    │ identity)    │  └──────────┘ │
       │       │         └──────┬───────┘                │
       │       │                │                        │
       └───────┼────────────────┼────────────────────────┘
               │                │
               ▼                │
        Coding agent            │
        (Claude Code,           │
         Codex, Cursor...)      │
               │                │
        ┌──────▼──────┐         │  ✅ approve / chat
        │tg_*  tools  │         │  ✏️ edit / ❌ cancel
        │for read /   │         │
        │propose_send │         │ ┌────────────────────┐
        └─────────────┘         └→│ Telegram (your     │
                                  │ Saved Messages or  │
        Phase 4 chat:             │ bot's DM with you) │
        Bot DM ───────────┐       └────────────────────┘
                          │
                ┌─────────▼──────────────────┐
                │  Coding-agent subprocess   │
                │  (claude --print --resume) │
                │  cwd = твой vault          │
                │  persistent session        │
                └────────────────────────────┘

Пять слоёв

  1. Read intelligence — userbot indexer + FTS5 store + read API + MCP read-tools. Голосовые и кружочки транскрибируются локальным Whisper и попадают в тот же индекс. Claude может искать и читать, но не писать. Capability A.
  2. Outbound with approval — propose-send через бота с use-once токенами и audit. Claude предлагает, ты одобряешь. Capability B.
  3. Inbound chat session — бот = persistent Claude conversation с твоим vault как контекстом. Capability C.
  4. Cross-cutting — owner-only checks, rate limits, kill switch, daily digest, audit log. Безопасность поверх всех слоёв.
  5. Штаб-контур (Phase 5) — мост @hq к оркестратору, алерты в его инбокс, scoped-MCP для дополнительных агентов, второй бот-персона в группах. Это уже не «Telegram для одного агента», а Telegram как транспорт для команды агентов; каждая идентичность в демоне — со своим гейтом.

Ключевые принципы

  1. Approval gate is the entire safety story. Нет trusted-path для outbound. Любой код пути всегда через карточку с use-once токеном. Если кто-то предлагает «оптимизацию через bypass» — отказ.

  2. Owner-only на bot. Approval bot принимает callback’и и DM’ы только от одного chat_id (твой собственный Telegram user_id). Любой посторонний — silent ignore (DM) или Not authorized toast (callbacks).

  3. Use-once токены, привязанные к содержимому. Approval-token = (random nonce, chat_id, sha256(text), expires_at, used). При press-✅ daemon validates все четыре поля и атомарно ставит used=true. Подмена content или повторный send — отказ.

  4. Local-only по умолчанию. HTTP API на 127.0.0.1, MCP через stdio. Никаких cloud-сервисов в data path. Даже approval-bot работает через стандартный Bot API (через Telegram’овские серверы), но callback’и принимаются на локальный polling, не через webhook.

  5. Audit append-only. Каждое событие (PROPOSED, APPROVED, EDITED, SENT, SEND_FAILED, RATE_LIMITED, REJECTED, CANCELLED, TIMEOUT) пишется в отдельную таблицу. Только INSERT, никогда UPDATE/DELETE. Reasoning: forensics после факапа.

  6. Rate limits как defence-in-depth. Конфигурируемые caps: per-hour (например 30), per-minute (10), per-peer cooldown (3s). Triggered limits → RATE_LIMITED audit + reject, не throttle.

  7. Kill switch видимый. Команда /pause через бот или CLI мгновенно остановит всё outbound. /resume — включит. Используется при подозрении на bug или пока разбираешься с инцидентом.

  8. Group/channel writes — opt-in. В config.yaml дефолт allow_groups: false, allow_channels: false. Phase 3 отказывает на group/channel пока не флипнули флаг. Reasoning: гораздо чувствительнее, blast radius шире. (В нашем инстансе allow_groups включён с 17.09.2026 — понадобился для постов в группу потока курса; approval gate при этом никуда не делся.)

  9. Vault-as-context (Phase 4). Coding-agent subprocess запускается в твоём knowledge-base directory. Он читает твой CLAUDE.md/AGENTS.md, видит вашу структуру, может call MCP-инструменты Telegram’а. Persistent session через --resume — конверсация копится.

  10. TOS hygiene. Telegram tolerates personal userbots без spam/automation/scraping. Никаких mass-send, broadcast, scraping чатов в которых ты не member, обхода UI. Owner-only + rate limits — это и есть твоя защита.

  11. Use it, see what hurts. После каждой фазы — soak period. Реальные friction-points добавляются в backlog, не плановые refactors. Code review до merge — да; pre-emptive optimization — нет.

  12. Одна идентичность — один гейт (Phase 5). Когда в демоне живёт больше одного бота или больше одного агента-потребителя, у каждого свой оператор допуска первым в каждом хендлере: approval bot — только owner chat_id; бот-персона — только группы из белого списка плюс личка владельца; второй агент через MCP — только --scope. Границы стерегут тесты (AST-тест «гейт первым оператором», boundary-тест «референт не трогает messages/vault/мост»), а не дисциплина.

Фазы

Четыре базовые фазы + пятая, штабная (появляется, когда Telegram становится транспортом для команды агентов, а не для одного). Каждая фаза самостоятельно ценна. Можно остановиться на любой. Реалистичный объём: каждая ~1-2 рабочих дня с coding agent’ом, ~15-25 задач, ~50-100 unit tests.

Phase 1 — Foundation (read intelligence)

Что строится:

  • Project skeleton (separate git repo, не в vault)
  • Telegram API credentials в config.yaml
  • Userbot (MTProto client) — авторизация через SMS+2FA, session-файл хранится локально. Session-файл = полный доступ к аккаунту: храни как секрет (chmod 0600, не в git, сделай бэкап). Не запускай одну и ту же session из двух мест одновременно — Telegram видит конфликт и может ревокнуть сессию или флагнуть аккаунт
  • Always-on daemon (см. Cross-platform notes ниже про OS-specific подъём)
  • SQLite schema: messages (+ transcript колонка для распознанного голоса) + FTS5 virtual table, chats, users, meta, плюс заранее audit_log и approval_requests (Phase 3 их будет использовать без миграций)
  • Real-time indexer на 3 события: NewMessage, MessageEdited, MessageDeleted
  • Initial backfill за N дней при первом запуске (например 30), persisted-флаг чтобы не повторять. Backfill — батчами с паузами, не «всё за раз»: массовое чтение легко ловит FloodWait (Telegram просит подождать N секунд)
  • CLI commands: setup, status, search, contacts, chat

Capability A: ты можешь искать через CLI по своей переписке.

Что нужно решить:

  • Какой MTProto-SDK для твоего языка (Python: Telethon / Pyrogram. JS: gramjs. Go: gotd. Rust: grammers)
  • Где data-dir (см. вопросы)
  • Сколько дней backfill’а
  • Какие токенайзеры FTS5 поддерживает твой язык/SQLite (для русского + английского — обычно unicode61 remove_diacritics 2)

Phase 2 — Local API + MCP integration

Что строится:

  • HTTP server на 127.0.0.1:<port>, X-API-Key auth (auto-generated random key хранится в data dir с режимом 0600)
  • Endpoints: POST /search/messages, POST /search/contacts, GET /chats/{id}, GET /chats/{id}/messages, GET /chats/recent, GET /health, GET /stats
  • MCP shim — отдельный binary/script который подключается через stdio к coding agent’у. Внутри он делает HTTP calls на свой же local API
  • 5 read MCP-инструментов: tg_search_messages, tg_search_contacts, tg_get_chat_info, tg_read_chat, tg_list_recent_chats
  • Admin-инструменты (добавляются по мере использования, не обязательны для MVP): tg_backfill_chat (history pull за пределами launch-окна через iter_messages) и tg_transcribe_media (голосовые/кружочки → текст через локальный Whisper, результат кэшируется в БД и индексируется в FTS)

Capability A через Claude: Claude Code (или другой MCP-клиент) видит 5 read-инструментов и может ими пользоваться.

Что нужно решить:

  • HTTP framework (Python: FastAPI/Starlette. JS: Hono/Express. Go: chi/Echo)
  • MCP SDK (есть для Python, TypeScript, Go)
  • Как хранить API key (генерится один раз, в data dir, не в repo)

Phase 3 — Outbound with approval

Что строится:

  • Создание approval-bot через @BotFather (one-time, твоё действие)
  • Bot SDK интегрирован в daemon (тот же процесс): aiogram (Python), grammY (JS), telegram-bot-api (Go) — что подходит языку
  • Endpoints: POST /outbound/propose, POST /control/pause, POST /control/resume
  • Storage primitives: tokens.py (issue/validate/consume), audit.py (append-only writer), ratelimit.py (in-memory three-cap limiter), proposals.py (CRUD над approval_requests)
  • Approval card: HTML message с inline keyboard ✅ Send / ✏️ Edit / ❌ Cancel, callback_data = <action>:<proposal_id>
  • Orchestrator (state machine): propose → создаёт row, отправляет card, parks future, ждёт callback или timeout. На ✅ — issues token → validates → sender (через userbot) → audit SENT
  • MCP tool: tg_propose_send(chat_id, text, chat_type, ...) — long-poll на HTTP уровне до окна approval (у нас 30 минут), blocks в coding agent’е до решения
  • CLI: tg propose, tg pause, tg resume, tg setup-bot

Capability B: Claude может предлагать сообщения, ты одобряешь.

Что нужно решить:

  • Имя бота (что-то опознаваемое: @MyClaudeApprovalBot etc.)
  • Где хранить bot token (config.yaml; data dir; encrypted)
  • Default rate limits (рекомендация: 30/hr, 10/min, 3s/peer для personal use)
  • Approval timeout (рекомендация: 30 минут default, настраиваемо; стартовали с 5 — не хватало, когда телефон не в руке: карточки протухали, агент повисал в ожидании)
  • Группы/каналы — включать сразу или держать off?

Phase 4 — Inbound chat session (тг-сессия)

Что строится:

  • tgsession package: meta.py (k-v session state в той же SQLite), transcript.py (per-session markdown writer), agent_runner.py (async-обёртка над coding-agent CLI — см. «Agent Runner» ниже), manager.py (lock + queue + state), formatting.py (Markdown → Telegram-HTML + length splitter), commands.py (/new /status /help renderers)
  • В daemon msg_handler: dispatch для /new /status /help (новое) + /pause /resume (существующее) + plain text → manager.handle() → Agent Runner
  • Per-session markdown transcript в отдельной папке внутри vault’а (например Claude-tg-sessions/) — он же служит контекст-стором для стратегии B (ниже)
  • UX: ⚡ reaction на твоё сообщение (in progress), ⏳ если queued, “typing…” indicator пока агент работает, bot menu commands (/new /status /help появляются в Telegram menu кнопке)
  • Concurrency: lock + queue (max 5), 6+ → reject. Late replies (queued messages) приходят отдельным message в тот же чат
  • (Опц.) 50% context warning: если CLI отдаёт usage-метаданные — когда cumulative tokens пересекли половину contextWindow, добавить one-time prefix ⚠️ контекст 50%+ (подумай о /new). Нет usage-метаданных — просто пропусти.

Agent Runner — контракт и стратегии (вот что делает Phase 4 переносимой)

Не привязывайся к одному CLI. Опиши Agent Runner как компонент с контрактом и реализуй под свой агент. Контракт:

  • (обязательно) принять текст сообщения + working directory = vault → вернуть текстовый ответ;
  • (желательно) держать контекст разговора между сообщениями;
  • (опционально) вернуть метаданные: session_id, token usage.

«Память между сообщениями» — три стратегии по убыванию предпочтения, выбираешь под возможности своего CLI:

Стратегия Когда Как
A. Нативный resume CLI умеет resumable-сессии (Claude Code: --resume <id>) Хранить session_id в meta, передавать на каждом запросе. Агент сам держит контекст. Дешевле всего по токенам.
B. Replay транскрипта CLI делает one-shot без памяти (Codex exec, Gemini non-interactive, aider --message) Ты и так пишешь markdown-транскрипт — подавай его как контекст на каждый запрос (stdin / context-файл / --message). Работает с любым one-shot CLI; дороже по токенам.
C. Stateless one-shot Минимальная реализация / простые вопросы Каждое сообщение — независимый запрос без истории. Деградация UX, но заводится за час.

Аналогично для остальных capability:

  • System-prompt injection (проинструктировать: отвечает через Telegram, ≤4096 chars, лёгкий Markdown, без таблиц): нативный флаг если есть (--append-system-prompt), иначе префиксь инструкцию в начало сообщения / context-файла.
  • session_id / usage: парсь из structured output, если CLI даёт JSON (--output-format json); иначе генери свой session_id (uuid) на стороне демона, а context-warning отключи.

Capability C: ты пишешь боту с телефона/планшета — агент отвечает с контекстом твоего vault’а.

Что нужно решить:

  • Какой coding-agent CLI (claude от Anthropic, codex от OpenAI, gemini CLI, aider…) — и умеет ли он resumable-сессии (это и определяет стратегию A/B/C выше)
  • Где transcript-папка (внутри vault — recommended; для стратегии B это ещё и контекст-стор)
  • Default model (если CLI multi-model): для coding-style вопросов — посильнее; для chit-chat — побыстрее/подешевле
  • Таймаут subprocess (рекомендация: 10–20 минут — долгие сессии с большим контекстом реально упираются в маленький таймаут)

Phase 5 — Штаб-контур (оркестратор, алерты, второй бот)

Появляется, когда у тебя не «один агент с Telegram-тулзами», а команда агентов с главной сессией-оркестратором, и Telegram становится для неё транспортом. Пять независимых кусков, каждый включается отдельно:

5a. Мост к оркестратору (@hq). Сообщение approval-боту, начинающееся с @hq … (или @main …), перехватывается в коде демона до карманной тг-сессии и доставляется в живую главную сессию агента: либо в unix-сокет, который сессия публикует при старте, либо (дефолт, надёжнее) секцией ## TG <дата время> в append-only inbox-файл в vault’е, за которым главная сессия держит monitor. Ответ боту в Telegram — «Передал ✓ (сокет|инбокс)». Reasoning: карманная сессия — отдельный процесс без контекста оркестратора; штабу нужен прямой вход с телефона. Медиа-альбомы с подписью @hq идут старым путём через тг-сессию.

5b. Алерты в инбокс. Отдельная Telegram-группа «Alerts», куда прод-боты (сообщество, продукт) дублируют админ-алерты; userbot видит её как обычный чат, модуль alerts кладёт сообщения секциями ## ALERTS в тот же inbox-файл. Главная сессия верифицирует фактуру, действует и шлёт человеку только резюме «что случилось → что сделали». Каналы человека остаются дублем, не переездом.

5c. Scoped-MCP для второго агента. Тот же MCP-сервер, запущенный с --scope digest, отдаёт второму агенту (у нас — Codex, собирающий дайджест каналов) только каналы из правил дайджеста и тулзу tg_digest, а не всю переписку. Один демон, разные окна доступа по агенту.

5d. Второй бот с персоной для чужих групп. Отдельный Bot API-токен и отдельный Dispatcher в том же процессе (handle_signals=False у второго, иначе aiogram дерётся за сигналы). Свой контур: свои таблицы (скользящее окно 7 дней истории группы), свой гейт первым оператором — группа из белого списка allowed_chats или личка владельца, всё остальное молчит (fail-closed, пустой список = молчит везде). Privacy mode у бота выключен в BotFather, он читает всю группу и честно говорит это по /privacy. Умеет то, что нужно группе, а не владельцу: ответ по упоминанию/реплаю в персоне, автотранскрипт голосовых и кружочков локальным Whisper для всех участников, разбор фото, «нарисуй…», итоги дня, напоминания, шутки по контексту, консилиум персон, дуэль двух моделей. Артефакт «сделай дек из этой ветки» уходит секцией ## REFERENT в инбокс оркестратора, файл возвращается в группу через POST /referent/send_file (чат — только из таблицы задач, путь — только из белого списка папок). Кап расходов в день, rate limit, stale-фильтр апдейтов (Mac спал — старое только в память). Границы по построению: референт не прикасается к messages, vault’у, карманной сессии, MCP и мосту — это стерегут boundary-тесты.

5e. Карточки других контуров через тот же бот. Approval bot оказался удобной «почтой карточек» для всего штаба: почтовый вотчер шлёт через него карточки писем с кнопками, вотчер прода — алерты. Правило то же — кнопки принимает только owner.

Что нужно решить:

  • Куда доставлять @hq: сокет живой сессии (мгновенно, но зависит от того, что сессия жива) или inbox-файл с monitor’ом (переживает рестарты). Рекомендация: файл — дефолт, сокет — опционально.
  • Нужен ли второй бот вообще. Он даёт новое только в группе с другими людьми; для владельца всё то же делает карманная сессия. Не заводить «потому что можно».
  • Что видит бот-персона и кому это проговорено: группа чужая, ответы уходят в API модели — участники должны знать.

Как мы работаем (рабочие паттерны)

Это та часть, ради которой система вообще существует. Четыре фазы выше — что построено; ниже — как этим живёшь день за днём. Паттерны описаны обобщённо (узнаваемые сценарии, не привязанные к конкретным чатам); реплики курсивом — иллюстрации, подставь свои.

Каждый паттерн: когда → что делает агент → инструменты → пример.

1. Research по своей переписке

  • Когда: нужно вспомнить или найти что-то в собственной истории — «что мы решили с X», «найди контакты из Y», «дай дайджест канала Z за неделю».
  • Агент: ищет по FTS, читает релевантные чаты, суммирует. Отдаёт выжимку, а не сырые тела сообщений (см. принципы приватности).
  • Инструменты: tg_search_messages, tg_search_contacts, tg_read_chat, tg_get_chat_info, tg_list_recent_chats.
  • Пример: «о чём договаривались с Игорем в последний раз?» → найти контакт → прочитать чат → саммари ключевых договорённостей.

2. Восстановление истории (backfill) перед research

  • Когда: нужный чат/канал старше окна индексации (демон копит с момента запуска + N дней backfill при старте). Старая переписка просто отсутствует в индексе.
  • Агент: подтягивает историю чата по требованию, затем работает с ней как с обычным индексом.
  • Инструменты: tg_backfill_chattg_search_messages / tg_read_chat.
  • Пример: «подними всю переписку с подрядчиком за полгода и найди, где согласовали смету».

3. Голос → текст перед поиском/саммари

  • Когда: в чате важные голосовые или кружочки, которых нет в текстовом поиске.
  • Агент: транскрибирует локальным Whisper (offline, кэш — каждый клип один раз), текст попадает в индекс, дальше — обычный research.
  • Инструменты: tg_transcribe_mediatg_search_messages / tg_read_chat.
  • Пример: «в чате созвона были только голосовые — расшифруй и собери список задач».

4. Ассистированный outbound от твоего имени

  • Когда: «напиши X-у, что …» — агент формулирует сообщение от твоего лица.
  • Агент: составляет текст с учётом контекста переписки → tg_propose_send → ждёт твой ✅ в карточке. Никогда не отправляет напрямую.
  • Инструменты: tg_propose_send (+ read-инструменты для контекста).
  • Пример: «напиши Игорю, что встреча переносится на четверг» → карточка в Saved Messages → ✅ → отправлено.

5. Агент пишет от своего лица, представляясь

  • Когда: ты хочешь, чтобы ответил сам агент, а не ты его руками — «ответь за меня», «пусть твой агент ему напишет». Агент не выдаёт себя за тебя: он представляется как твой AI-агент.
  • Агент: читает контекст переписки, отвечает по сути от первого лица («это агент такого-то»), всё равно проходит через approval. Сам факт такого ответа — демонстрация того, что агент видит контекст и имеет доступы (чего нет у чата в вакууме).
  • Инструменты: tg_read_chattg_propose_send.
  • Пример: собеседник спрашивает «чем твой агент лучше обычного чат-бота?» — ты отвечаешь «пусть он сам и объяснит», агент пишет ему напрямую, на ходу доказывая разницу.

6. Pocket Claude — работа с телефона

  • Когда: ты не за компьютером, но нужно спросить или сделать что-то в своей базе знаний.
  • Агент: пишешь боту DM → daemon поднимает coding-agent в твоём vault через --resume → ответ возвращается reply’ем. Сессия persistent, /new сбрасывает контекст.
  • Инструменты: тг-сессия (Phase 4) + любые tg_* изнутри сессии.
  • Пример: из метро — «что у меня по календарю завтра и накидай тезисы к созвону».

7. Daily digest

  • Когда: хочешь держать под контролем outbound-активность без ручной проверки логов.
  • Система: в заданное время шлёт в approval-чат сводку (что предложено / отправлено / отклонено / таймаут за сутки).
  • Инструменты: digest scheduler в демоне.
  • Пример: утренняя сводка «вчера: 3 предложено, 2 отправлено, 1 отклонено».

8. Штаб с телефона (@hq)

  • Когда: ты не у компьютера, а оркестратору нужно поручение или ответ — не карманной сессии, а той, что держит контекст и решения.
  • Ты: пишешь боту @hq выложи вчерашнюю запись — и получаешь «Передал ✓».
  • Система: демон кладёт секцию в inbox-файл, monitor главной сессии будит её, она делает и отвечает тебе через approval-карточку или в живом диалоге.
  • Инструменты: мост в демоне + inbox-файл + monitor на стороне агента.

9. Бот в чужой группе

  • Когда: в группе с друзьями/коллегами хочется «домашнего» бота: расшифровать голосовое всем, разобрать скрин, сделать итоги дня, пошутить в тон.
  • Ты: добавляешь бота, вписываешь id группы в белый список, участникам говоришь, что ответы уходят в API модели.
  • Система: отвечает только по обращению, помнит окно группы, к твоей переписке и vault’у доступа не имеет.
  • Инструменты: Phase 5d.

Инвариант поверх всех паттернов: read-паттерны (1–3) полностью локальны — данные не покидают твою машину. Любой outbound (4–5) проходит через approval gate — финальный ✅ всегда твой, никаких исключений.

Cross-platform notes

macOS

  • Always-on: launchd plist в ~/Library/LaunchAgents/<your-app>.plist. RunAtLoad=true, StartCalendarInterval для cron-like jobs (бэкап).
  • Data dir: ~/Library/Application Support/<app>/
  • Coding-agent CLI: установка через brew обычно. Path: /opt/homebrew/bin/<cli> (Apple Silicon) или /usr/local/bin/<cli> (Intel).
  • PATH gotcha: launchd subprocess НЕ наследует interactive shell PATH. Жёстко прописывай <абсолютный путь>/cli в spawn-args, или установи env via EnvironmentVariables в plist.
  • Sleep: при закрытом крышке — daemon продолжит, MTProto-клиент догонит через getDifference после wake.

Linux

  • Always-on: systemd user unit в ~/.config/systemd/user/<app>.service (systemctl --user enable --now <app>) — recommended если десктоп/server. Альтернативы: supervisord, runit.
  • Data dir: ~/.local/share/<app>/ (XDG-spec) или $XDG_DATA_HOME/<app>/.
  • Coding-agent CLI: install через npm/pip/curl, path обычно /usr/local/bin/ или ~/.local/bin/.
  • PATH gotcha: systemd user services обычно наследуют user environment если Type=simple без User= overrides — но всё равно лучше абсолютный путь в spawn-args.
  • Headless server: вообще удобнее — никакого sleep, никаких VPN-проблем.

Windows

  • Always-on: вариантов несколько, выбирать по комфорту:
    • Task Scheduler — встроенный, можно настроить trigger “At log on” + “Restart on failure”, запуск как hidden window
    • NSSM (Non-Sucking Service Manager) — обёртка сделать любую программу в Windows Service
    • WSL2 — если ты Linux-фанат и хочешь systemd, WSL2 supports systemd (нужно включить в .wslconfig). Bonus: одинаковый install как на Linux desktop
  • Data dir: %APPDATA%\<app>\ (C:\Users\<you>\AppData\Roaming\<app>\)
  • Coding-agent CLI: установка зависит от CLI. Claude CLI — через npm i -g @anthropic-ai/claude-code или scoop. Codex — npm. Path в %USERPROFILE%\AppData\Roaming\npm\ или scoop’е ~\scoop\shims\.
  • Path separators: используй pathlib.Path (Python) или эквивалент — никаких "/" в string-конкатенациях
  • Subprocess gotcha: Windows не любит asyncio.subprocess.PIPE без asyncio.WindowsProactorEventLoopPolicy. На Python 3.8+ это default, но verify
  • WSL2 alternative: запустить весь daemon внутри WSL2 — проще mental model, но coding-agent CLI должен быть тоже в WSL2 чтобы paths совпадали

Docker (универсально)

  • Один контейнер с daemon (indexer + HTTP API + approval bot polling + tg-session subprocess host)
  • Volume для data dir + vault dir
  • Единственный gotcha: subprocess для coding-agent должен быть в том же image. Т.е. контейнер должен иметь claude/codex CLI установленным
  • Plus: если ты на VPS / NAS — Docker самый чистый путь
  • Минус: на Mac/Windows — overhead Docker Desktop, и Telethon/grammers всё-таки эффективнее напрямую

Tech stack — рекомендация по умолчанию

Если совсем без предпочтений — Python:

  • Telethon (MTProto userbot) — зрелый, активный, кросс-платформенный
  • aiogram 3.x (Bot API для approval bot) — async, чистый
  • aiosqlite (SQLite async) — без отдельного DB-сервера
  • FastAPI или Starlette (HTTP API)
  • MCP SDK от Anthropic для Python (mcp package на PyPI)
  • pytest + pytest-asyncio

JS-фанат → Telethon-aналог gramjs + grammY (Bot API) + better-sqlite3 + Hono + MCP TypeScript SDK.

Go → gotd/td (MTProto) + go-telegram/bot (Bot API) + sqlite3 driver + chi/Echo + MCP Go SDK.

Вопросы для адаптации

Это центральная секция Blueprint. Coding agent должен задать эти вопросы пользователю до того как начнёт писать код. Без ответов реализация будет ломаться о specifics.

Окружение

  1. OS: macOS / Linux / Windows / Docker host?
  2. Always-on механизм: launchd / systemd / Task Scheduler / Docker / WSL2 / vps?
  3. Где код проекта: какая директория для repo (НЕ внутри vault)?
  4. Где vault / knowledge base: путь? (нужно для Phase 4)
  5. Где data dir: предпочтения по конкретному пути или OS-default?
  6. Какой язык / стек: Python / JS / Go / другой?

Telegram

  1. API credentials: уже есть api_id + api_hash от my.telegram.org? Если нет — создать app в первую очередь.
  2. Phone number / аккаунт: с каким номером проходит authentication? Рекомендация — твой основной живой аккаунт, а не свежесозданный: новый аккаунт + резкая автоматизация = выше риск флага.
  3. Backfill depth: сколько дней назад индексировать при первом запуске? (рекомендация: 30 для активных юзеров, 7 для тяжёлых каналов)
  4. Approval bot username: что-то предполагаемое? Будет создаваться в @BotFather после Phase 3.
  5. Твой Telegram user_id: для owner-only check. Если не знаешь — узнаешь после Phase 1 запуска через tg status или прямой DB-query.
  6. Группы/каналы — outbound с самого начала или later? Default — выключено, opt-in через config.
  7. Транскрибация голосовых: нужна ли? Если да — какой Whisper-движок (mlx-whisper для Apple Silicon, faster-whisper / whisper.cpp для CPU/CUDA, либо cloud API для прототипа на не-чувствительных данных) и какой язык доминирует в твоих чатах?

Coding agent

  1. Какой MCP-клиент будет вызывать tg_* инструменты: Claude Code / Cursor / Codex / Gemini CLI / другой?
  2. Phase 4 agent CLI: claude / codex / gemini / aider / другой? Умеет ли resumable-сессии (определяет стратегию памяти A/B/C в Phase 4)? Какая модель по умолчанию?
  3. Твой timezone (для daily digest и логов).

Возможные расширения (Roadmap)

Текущее использование описано в разделе «Как мы работаем». Ниже — то, что ещё не построено и требует отдельного дизайна (Phase 5+):

  • Мониторинг конкретных каналов / чатов с keyword alerts (Claude тегает interesting message → ping в Saved Messages) — частично закрыто Phase 5b другим путём: алерты не по keyword, а по выделенной группе
  • Background digests по темам («что было в AI-каналах за неделю»)
  • Image OCR pipeline (картинки → текст в FTS5; голос уже сделан, см. паттерн 3)
  • Cross-chat thread tracking (одна тема обсуждается в 5 чатах → консолидированный feed)
  • Auto-categorization входящих (work / personal / promo / …)
  • Templated outbound (tg_compose <template> <recipient> для часто-повторяющихся заданий)
  • Multi-account support (личный + рабочий аккаунт в одной системе)
  • Voice replies (TTS из ответа Claude → голосовое сообщение в bot-чате)
  • Медиа через approval-карточку (tg_propose_send_file: файл/аудио с тем же ✅) — сейчас бот шлёт только текст, медиа — разовым скриптом на userbot-сессии
  • Вторая волна бота-персоны: память между группами через семантический стор, радар по темам, регулярные итоги — только с согласия участников и белыми списками

Пользователь брейнстормит с агентом, какие из них relevant, и какие появятся новые из его реальной работы.

Нюансы и грабли

Из реальной эксплуатации — то, на чём спотыкаешься, и как не споткнуться.

  • Окно approval в 5 минут — мало. Стартовали с 5, карточки протухали каждый раз, когда телефон не в руке, а агент повисал в long-poll впустую. 30 минут — рабочий дефолт; токен всё равно use-once.
  • Approval-карточку надо успеть нажать. Токен живёт ограниченное окно (например 60 сек после выдачи), сам proposal — до timeout’а (минуты). Прозеваешь — статус timeout, сообщение не уходит, и это правильно: молчаливая доотправка хуже промаха. Просто предложи заново. (Ловили вживую: карточка ушла, человек отвлёкся — пришлось повторять propose.)
  • Бот шлёт только текст. Approval-путь рассчитан на текст. Файл / фото / аудио через него не отправить. Workaround для разовой отправки медиа — отдельный скрипт на userbot-сессии (send_file), вне approval-петли. Не прикручивай медиа к карточке «на лету».
  • Приватность: суммируй, не вываливай. Это личная переписка. Агент по умолчанию отдаёт выжимку, а не сырые тела сообщений в чат, и никогда не выгружает переписку во внешние сервисы.
  • database is locked. Обычно — два запущенных демона (orphan + launchd/systemd) дерутся за БД, либо длинная write-транзакция. WAL + busy_timeout снимают 99%; если осталось — убей процесс-дубль.
  • In-flight state не переживает рестарт демона. Pending-proposals и активные тг-сессии живут в памяти. Рестарт посреди ожидания → HTTP-caller получает timeout, в чате остаётся «призрак»-карточка со старыми кнопками. Known follow-up: на старте помечать висящие pending как expired.
  • FTS5 и спецсимволы. Дефисы, URL, спецсимволы ломают FTS5-синтаксис, если запрос не санитизировать (фразовое экранирование) — иначе search падает в 500. При этом advanced-синтаксис (кавычки, *, AND/OR/NOT, NEAR) надо пропускать как есть.
  • Транскрибация: кэш и устойчивость к битым клипам. Распознал один раз → закэшировал в БД, больше не гоняешь. Батч голосовых не должен падать целиком из-за одного битого клипа — каждый обрабатывается изолированно.
  • launchd/systemd не наследуют shell PATH. Subprocess coding-agent’а не найдёт claude/codex по имени. Прописывай абсолютный путь к CLI в spawn-args (детали — в Cross-platform notes).
  • Session-файл — ключ от аккаунта. Не коммить, не шарь, бэкапь, права 0600. Кто получил файл — получил твой Telegram целиком. Потеря/инвалидация = снова SMS+2FA.
  • Одна session — одно место. Тот же session-файл, запущенный с двух машин/процессов, Telegram читает как конфликт → может ревокнуть сессию или флагнуть аккаунт. (Это про Telegram-сессию — в отличие от database is locked, который про два демона на одной БД.)
  • FloodWait — уважай, не долби. При backfill / массовом чтении Telegram отвечает FloodWaitError с числом секунд. SDK обычно ждёт сам, но не всегда — не ретрай агрессивно поверх. Backfill батчами с паузами; первый 30-дневный backfill на активном аккаунте — это реально много запросов.
  • Тесты — без живого Telegram. Те самые 50–100 тестов гоняй против фейкового MTProto-клиента (мокни интерфейс SDK, не реальную сеть) + in-memory SQLite. Дёргать настоящий Telegram из тестов — это и флаки, и FloodWait-риск.
  • Два бота в одном процессе — второй Dispatcher с handle_signals=False. Иначе aiogram ставит обработчики сигналов дважды и демон не останавливается штатно.
  • Privacy mode бота меняется только с переустановкой в группу. После /setprivacy в BotFather бота надо удалить из группы и добавить заново — иначе он продолжает видеть только упоминания.
  • Гейт — в каждом хендлере, а не «где-то в начале». Один раз owner-only check стоял в одном месте, новые хендлеры его обошли, и бот отвечал чужим личкам. Теперь гейт первым оператором в каждом хендлере, и это проверяет AST-тест.
  • Mac спал — апдейты протухли. Бот в группе после сна ловит пачку старых сообщений; отвечать на них — спам. Stale-фильтр по возрасту апдейта: старое только в память, без ответа.
  • Phase 4 завязана на возможности CLI. Нативный --resume есть не у всех агентов. Если твой CLI без resumable-сессий — не эмулируй его флагами, бери стратегию B (replay транскрипта), см. «Agent Runner» в Phase 4.
  • Agent Runner пишет в stdout, не в Telegram — петлю замыкает демон. Самый частый косяк при сборке Phase 4: агент «отвечает в консоль», а не в чат. Две причины. (1) CLI запущен в интерактивном режиме — гоняй его one-shot / non-interactive (claude -p / codex exec / aider --message), иначе агент открывает TUI и печатает в терминал, а не в захватываемый stdout. (2) Демон получил return value Agent Runner’а, но не отправил его обратно — bot.reply(answer) пропущен, вывод осел в daemon.log. Замыкание петли «DM → Agent Runner → bot.reply(answer)» — обязательный явный шаг, не «само получится». Проверка: пишешь боту DM → ответ приходит в тот же чат, а не только в лог демона. (Ловили у человека, собиравшего по блюпринту: всё работало, но ответы уходили в консоль — не хватало замыкающего reply.)

TOS / Safety constraints

Personal Telegram userbot — gray zone в Terms of Service. Telegram tolerates личное использование, но не одобряет automation/spam/scraping. Что нельзя:

  • Mass-send / broadcast — owner-only check + rate limits + approval gate. Каждое сообщение ручное (через ✅).
  • Scraping channels you’re not in — userbot читает только то, в чём твой account уже member.
  • Reverse-engineering Telegram UI / web client — никаких клиентских хаков, только официальный MTProto API.
  • Automation that mimics a person — approval gate означает что финальный ✅ всегда твой; coding agent предлагает, ты решаешь.
  • Sharing Telegram-data в сторонние сервисы — local-only design, MCP через stdio, HTTP на 127.0.0.1.
  • Bot identity confusion — approval bot имеет явное имя бота, не претендует быть человеком.

Что можно и поощряется:

  • Personal search / analytics своей переписки
  • Local LLM-augmented assistant
  • Approval-gated outbound от своего имени
  • Backup своих сообщений (это твои данные)

Что НЕ входит в Blueprint (out of scope)

  • Multi-account — система рассчитана на один Telegram account на инстанс. Можно поднять второй инстанс в другой data dir, но cross-account features (объединённый поиск, switching) не предусмотрено
  • Web UI — никаких dashboards / browser-interfaces. Всё через CLI / MCP / Telegram bot
  • Public bot service — approval bot owner-locked, нельзя превратить в shared service. Бот-персона для групп (Phase 5d) — не исключение из этого, а отдельная идентичность с отдельным гейтом; она тоже не публичный сервис, а бот в твоих группах по белому списку
  • Cloud deployment — система предполагает контролируемую тобой машину (десктоп / NAS / VPS под твоим аккаунтом). Managed cloud сервисы выходят за рамки local-first design
  • Persistent in-flight state — pending proposals / pending chat sessions живут в памяти. Daemon restart их теряет (HTTP caller получит timeout, ghost-карточки в чате). Это известное ограничение, фиксится в follow-up
  • Real-time streaming output — chat-сессия выдаёт ответ полностью когда subprocess закончил. Streaming/typing-buffer — feature для Phase 5+

Workflow

Setup (one-time, ~30-60 мин)

  1. Получить Telegram API app credentials на https://my.telegram.org
  2. Coding agent создаёт project skeleton, реализует Phase 1
  3. tg setup — авторизация через SMS + 2FA, session-файл сохраняется
  4. tg status — verify всё подключилось, daemon запущен через выбранный always-on механизм
  5. Backfill (30 дней по умолчанию) — займёт несколько минут на активном Telegram
  6. Phase 2: HTTP API + MCP shim, регистрация MCP в coding-agent клиенте
  7. Verify через MCP: tg_search_messages("test") возвращает результаты
  8. Phase 3: создать @BotFather бота, сохранить токен в config, реализовать approval flow
  9. Manual smoke: tg propose <self_user_id> "hello" --timeout 60 → карточка в Saved Messages → ✅ → message received
  10. Phase 4: реализовать tgsession, restart daemon, написать боту первое сообщение

Daily use

  • Read / research: в coding-agent (Claude Code/etc.) — «найди что обсуждали с Игорем по проекту X», «какие AI-каналы упоминали Y», и т.п. Claude использует MCP-инструменты.
  • Outbound: «напиши Игорю что встреча перенеслась» — Claude вызывает tg_propose_send, ты получаешь карточку, нажимаешь ✅/✏️/❌
  • Pocket Claude (Phase 4): пишешь боту с телефона — «что у меня по календарю сегодня», «найди тот рецепт что я сохранял в избранном» — Claude отвечает в чате через subprocess в твоём vault’е
  • Daily digest (если включен): в 09:00 (или твоё время) бот шлёт summary outbound-активности за сутки

Maintenance

  • tg pause / tg resume — kill switch когда что-то странное
  • /new через бот — сбросить chat-сессию когда контекст устал
  • Daily backup DB через cron / launchd (Phase 1 supplement)
  • Monitor daemon.log для FloodWait warnings (Telegram serverside rate limit’ы — обычно SDK сам обрабатывает, но stay alert)

Чеклист готовности

После всех 4 фаз и smoke test’а у тебя должно быть:

  • Daemon запущен через always-on механизм твоей OS
  • DB растёт (msg count увеличивается со временем)
  • HTTP /health отвечает ok
  • MCP инструменты видны в coding-agent клиенте, search возвращает results
  • Approval bot отвечает на tg setup-bot
  • CLI tg propose <self> "test" приводит к карточке в Saved Messages
  • Bot reaction (⚡), typing indicator, menu commands (/new /status /help) работают
  • Audit log заполняется (sql SELECT * FROM audit_log ORDER BY ts DESC LIMIT 20)
  • Group/channel write properly rejected (тест: tg propose <group_id> "x" --type supergroup)
  • Kill switch работает (tg pause → propose → rejected, tg resume → propose → ok)
  • (опц.) Транскрибация: tg_transcribe_media на голосовом → распознанный текст появляется в tg_search_messages
  • (опц.) Backfill: tg_backfill_chat подтягивает историю старше launch-окна

Реализация-пример

Референсная реализация (Python: Telethon + aiogram + FastAPI + MCP, все пять фаз, ~360 unit-тестов, транскрибация голосовых локальным Whisper, backfill истории, демон под launchd) — приватная; блюпринт описывает её архитектуру и грабли.

Известные follow-ups

Блюпринт живой — это не дыры, а осознанный backlog.

Система (engineering):

  1. Persistent in-flight state. На старте демона помечать висящие pending как timeout и, по возможности, править ghost-карточки на «expired». Сейчас рестарт теряет in-flight.
  2. Atomic token store. Если token store переедет из памяти в SQLite — переходить на UPDATE ... WHERE used = 0 + проверку rowcount, вместо неатомарного check-then-set.
  3. Background-task done-callbacks. Если polling бота умрёт (отозванный токен, сеть), демон жив, но outbound молча сломан. Нужен done-callback, который громко логирует и триггерит graceful stop.
  4. Server-side recipient resolution. recipient_username / recipient_name сейчас приходят от вызывающего. Резолвить через БД (users.get(chat_id)), чтобы карточка всегда была доверенной.
  5. Медиа через approval. tg_propose_send — только текст; файл/аудио — разовый скрипт на копии userbot-сессии вне approval-петли. Зеркало send_file_after_approval + тулза — ~50 строк, пока не понадобилось регулярно.

Пункты 1–4 на 19.09.2026 не закрыты — в эксплуатации не болят настолько, чтобы обогнать продуктовые задачи.

Сам блюпринт (doc):

  1. Верифицировать Cross-platform notes на реальных Linux/Windows (сейчас — на основе общих знаний).
  2. Decision-tree для tech-stack — flowchart «язык X + OS Y → этот SDK» вместо текстовых рекомендаций.
  3. Cost estimates — RAM/CPU/disk демона, число API-калов coding-agent’а в Phase 4.
  4. Migration path — как сосуществовать, если у пользователя уже есть Telegram-tooling (другой userbot, старый bot).