[{"data":1,"prerenderedAt":350},["ShallowReactive",2],{"content-tgdyk-ru":3},{"id":4,"title":5,"articleTitleSource":6,"articleValid":7,"articleWarnings":8,"body":9,"comments":7,"date":335,"date_updated":8,"description":336,"extension":337,"icon":338,"image":339,"language":340,"meta":341,"navigation":7,"path":342,"publish-to":8,"readingTime":343,"seo":345,"stem":346,"titleEasterEgg":8,"titleLines":347,"topics":348,"translationKey":33,"__hash__":349},"content/tgdyk-ru.md","tgdyk: Telegram как поток событий для локальных агентов","h1",true,null,{"type":10,"value":11,"toc":328},"minimark",[12,18,22,25,35,40,43,86,89,121,124,151,154,158,161,164,258,261,264,268,275,285,291,301,305,310,314,317,324],[13,14],"external-link-card",{"icon":15,"title":16,"url":17},"streamline-ultimate-color:github-logo-1","pavel-voronin/tgdyk","https://github.com/pavel-voronin/tgdyk",[19,20,21],"p",{},"Telegram — это место, где у многих из нас живут сигналы: рабочие чаты, каналы, алерты, личные сообщения. Если вы строите агента или автоматизацию, рано или поздно возникает задача: дать инструменту глаза в вашем Telegram.",[19,23,24],{},"Bot API для этого не подходит. Бот — отдельная сущность: он не видит ваши диалоги, не читает каналы, на которые подписаны вы, и работает только там, куда его явно добавили. Нужна пользовательская сессия. Библиотеки вроде Telethon или gramjs решают задачу, но каждый скрипт тащит за собой клиент целиком: авторизацию, хранение сессии, реконнекты. Когда инструментов становится несколько, это превращается в дублирование одной и той же инфраструктуры.",[19,26,27,28,34],{},"Я написал ",[29,30,33],"a",{"href":17,"rel":31},[32],"nofollow","tgdyk"," — маленький локальный демон, который решает ровно одну задачу: держит одну пользовательскую сессию Telegram и раздаёт живые обновления TDLib локальным инструментам в виде NDJSON.",[36,37,39],"h2",{"id":38},"как-это-работает","Как это работает",[19,41,42],{},"Один бинарник на Rust поверх TDLib. Четыре команды:",[44,45,46,68,74,80],"ul",{},[47,48,49,53,54,57,58,61,62,67],"li",{},[50,51,52],"code",{},"setup"," — вводите ",[50,55,56],{},"api_id",", ",[50,59,60],{},"api_hash"," с ",[29,63,66],{"href":64,"rel":65},"https://my.telegram.org/apps",[32],"my.telegram.org/apps",", телефон и код. Один раз.",[47,69,70,73],{},[50,71,72],{},"daemon"," — запускает TDLib и публикует обновления через локальный Unix-сокет.",[47,75,76,79],{},[50,77,78],{},"stream"," — печатает сырые обновления TDLib построчно как JSON.",[47,81,82,85],{},[50,83,84],{},"doctor"," — проверяет TDLib, конфиг, пути и связь с демоном.",[19,87,88],{},"Дальше — обычная Unix-композиция:",[90,91,96],"pre",{"className":92,"code":93,"language":94,"meta":95,"style":95},"language-bash shiki shiki-themes material-theme","./tgdyk stream | jq .\n","bash","",[50,97,98],{"__ignoreMap":95},[99,100,103,107,111,115,118],"span",{"class":101,"line":102},"line",1,[99,104,106],{"class":105},"s5Dmg","./tgdyk",[99,108,110],{"class":109},"sfyAc"," stream",[99,112,114],{"class":113},"sAklC"," |",[99,116,117],{"class":105}," jq",[99,119,120],{"class":109}," .\n",[19,122,123],{},"Только новые текстовые сообщения:",[90,125,127],{"className":92,"code":126,"language":94,"meta":95,"style":95},"./tgdyk stream | jq -r 'select(.[\"@type\"] == \"updateNewMessage\") | .message.content.text.text // empty'\n",[50,128,129],{"__ignoreMap":95},[99,130,131,133,135,137,139,142,145,148],{"class":101,"line":102},[99,132,106],{"class":105},[99,134,110],{"class":109},[99,136,114],{"class":113},[99,138,117],{"class":105},[99,140,141],{"class":109}," -r",[99,143,144],{"class":113}," '",[99,146,147],{"class":109},"select(.[\"@type\"] == \"updateNewMessage\") | .message.content.text.text // empty",[99,149,150],{"class":113},"'\n",[19,152,153],{},"На этом ответственность tgdyk заканчивается. Всё, что дальше — фильтрация, роутинг, реакция — собирается из того, что у вас уже есть: shell, jq, Python-скрипт, вызов LLM.",[36,155,157],{"id":156},"зачем-это-агентам","Зачем это агентам",[19,159,160],{},"Типичный сценарий: агент работает в фоне, и вам нужно, чтобы события из Telegram попадали к нему без опроса и без вашего участия. Сообщение в рабочем чате, алерт из канала мониторинга, реплай на ваш пост — всё это приходит в поток как структурированный JSON, и дальше вы решаете, что с этим делать: разбудить агента, положить в очередь, дёрнуть вебхук.",[19,162,163],{},"Пайплайн собирается из одной строки:",[90,165,167],{"className":92,"code":166,"language":94,"meta":95,"style":95},"./tgdyk stream \\\n  | jq -c 'select(.[\"@type\"] == \"updateNewMessage\")' \\\n  | while read -r msg; do\n      # здесь ваш обработчик: скрипт, очередь, вызов агента\n      echo \"$msg\" >> inbox.ndjson\n    done\n",[50,168,169,179,200,224,231,252],{"__ignoreMap":95},[99,170,171,173,175],{"class":101,"line":102},[99,172,106],{"class":105},[99,174,110],{"class":109},[99,176,178],{"class":177},"svy0-"," \\\n",[99,180,182,185,187,190,192,195,198],{"class":101,"line":181},2,[99,183,184],{"class":113},"  |",[99,186,117],{"class":105},[99,188,189],{"class":109}," -c",[99,191,144],{"class":113},[99,193,194],{"class":109},"select(.[\"@type\"] == \"updateNewMessage\")",[99,196,197],{"class":113},"'",[99,199,178],{"class":177},[99,201,203,205,209,213,215,218,221],{"class":101,"line":202},3,[99,204,184],{"class":113},[99,206,208],{"class":207},"s6cf3"," while",[99,210,212],{"class":211},"sdLwU"," read",[99,214,141],{"class":109},[99,216,217],{"class":109}," msg",[99,219,220],{"class":113},";",[99,222,223],{"class":207}," do\n",[99,225,227],{"class":101,"line":226},4,[99,228,230],{"class":229},"s0_hs","      # здесь ваш обработчик: скрипт, очередь, вызов агента\n",[99,232,234,237,240,243,246,249],{"class":101,"line":233},5,[99,235,236],{"class":211},"      echo",[99,238,239],{"class":113}," \"",[99,241,242],{"class":177},"$msg",[99,244,245],{"class":113},"\"",[99,247,248],{"class":113}," >>",[99,250,251],{"class":109}," inbox.ndjson\n",[99,253,255],{"class":101,"line":254},6,[99,256,257],{"class":207},"    done\n",[19,259,260],{},"Никакого SDK, никакой привязки к языку. Если инструмент умеет читать stdin или Unix-сокет, он умеет читать ваш Telegram.",[19,262,263],{},"Писать эти пайплайны руками, кстати, не обязательно. Современные агенты хорошо владеют CLI и Unix-композицией — jq, потоки, редиректы, systemd-юниты. Достаточно сказать своему агенту «подпишись на канал X и складывай алерты в очередь», и он соберёт обвязку сам. tgdyk даёт ему примитив, из которого это собирается надёжно.",[36,265,267],{"id":266},"дизайн-решения","Дизайн-решения",[19,269,270,274],{},[271,272,273],"strong",{},"Сырые обновления."," tgdyk не придумывает свою схему поверх TDLib. Типы TDLib — это и есть контракт: они документированы, стабильны и покрывают всё, что происходит в аккаунте. Любая обёртка означала бы потерю информации и ещё один слой, который надо поддерживать.",[19,276,277,280,281,284],{},[271,278,279],{},"Только live."," tgdyk не хранит историю и не умеет replay. Если вам нужна персистентность — это одна строчка в вашем пайплайне (",[50,282,283],{},">> inbox.ndjson","), и вы сами выбираете формат и место хранения. Единственное, что лежит на диске — стандартная локальная база TDLib с сессией и кэшем.",[19,286,287,290],{},[271,288,289],{},"Локальный Unix-сокет."," Никаких портов, токенов и слоя авторизации. Доступ к потоку определяется правами файловой системы. Это осознанное сужение: tgdyk — инструмент для вашей машины, а не сетевой сервис.",[19,292,293,296,297,300],{},[271,294,295],{},"TDLib в комплекте."," Сборка TDLib — известная боль. Релизы включают ",[50,298,299],{},"libtdjson"," для macOS (Intel и Apple Silicon) и Linux (x64 и arm64), так что путь от скачивания до потока — несколько команд.",[36,302,304],{"id":303},"ограничения","Ограничения",[19,306,307,309],{},[50,308,78],{}," отдаёт только то, что происходит после подключения — запускайте его до событий, которые хотите поймать. Демон работает в foreground: systemd, tmux или supervisor — на ваше усмотрение. И главное: это ваша пользовательская сессия. Всё, что подключается к сокету, видит ваш аккаунт целиком — относитесь к машине, где крутится демон, соответственно.",[36,311,313],{"id":312},"итог","Итог",[19,315,316],{},"tgdyk занимает одно узкое место в пайплайне: живой мост между вашим Telegram-аккаунтом и локальными инструментами. Всё остальное — ваша композиция.",[19,318,319,320],{},"Rust, MIT, бинарные релизы для macOS и Linux: ",[29,321,323],{"href":17,"rel":322},[32],"github.com/pavel-voronin/tgdyk",[325,326,327],"style",{},"html pre.shiki code .s5Dmg, html code.shiki .s5Dmg{--shiki-default:#FFCB6B}html pre.shiki code .sfyAc, html code.shiki .sfyAc{--shiki-default:#C3E88D}html pre.shiki code .sAklC, html code.shiki .sAklC{--shiki-default:#89DDFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .svy0-, html code.shiki .svy0-{--shiki-default:#EEFFFF}html pre.shiki code .s6cf3, html code.shiki .s6cf3{--shiki-default:#89DDFF;--shiki-default-font-style:italic}html pre.shiki code .sdLwU, html code.shiki .sdLwU{--shiki-default:#82AAFF}html pre.shiki code .s0_hs, html code.shiki .s0_hs{--shiki-default:#546E7A;--shiki-default-font-style:italic}",{"title":95,"searchDepth":226,"depth":226,"links":329},[330,331,332,333,334],{"id":38,"depth":181,"text":39},{"id":156,"depth":181,"text":157},{"id":266,"depth":181,"text":267},{"id":303,"depth":181,"text":304},{"id":312,"depth":181,"text":313},"2026-07-07","Локальный демон на Rust поверх TDLib: одна пользовательская сессия Telegram, Unix-сокет и живой поток сырых обновлений в NDJSON для агентов и пайплайнов.","md","streamline-ultimate-color:send-email-fly","og-image.jpg","ru",{},"/tgdyk-ru",{"wordCount":344},714,{"title":5,"description":336},"tgdyk-ru","2","AI toolchain, Telegram","jurNJIieNahBN_dsDTBzinvvgLDnFyfH7n6L4qRlQqw",1783484429887]