skills/telegram-agents/SKILL.md
Configure and manage Telegram-connected Claude agents with heartbeat scheduling on macOS. Use when the user wants to "set up Telegram agent", "add heartbeat", "configure Telegram channel", "管理 Telegram agent", "配置心跳", "添加定时任务", "Telegram 多 agent", "配置 Telegram", "添加 Telegram agent", "给 Telegram bot 创建身份", "设置定时任务", "新增定时任务", "每天X点执行Y", "schedule a task", "run this automatically", "set up a cron job", or encounters Telegram polling conflicts, 409 Conflict, file upload failures through proxy, or needs to add recurring/periodic automated task execution for Claude agents.
npx skillsauth add kanlac/agent-steroids telegram-agentsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
让多个 Claude agent 各自绑定独立 Telegram bot,通过 tmux 常驻,配合 launchd 定时发送心跳消息。
agents.yaml(统一配置)
│
├── tmux session: channels
│ ├── window: sage ──── Telegram Plugin(getUpdates + sendMessage)
│ ├── window: herald 各自独立 bot token + 状态目录
│ ├── window: ... 一个 session 管理所有 agent
│ └── [每个 window 一个 agent 身份文件]
│
└── launchd(每分钟触发)
│
dispatcher.py
│ 匹配 cron 表达式
└── 心跳消息 → Telegram Bot API → channel session 接收处理
三个核心原则:
~/.config/telegram-agents/agents.yaml 是唯一配置源:
# 所有 agent 共用一个 tmux session,每个 agent 一个 window(window 名 = agent key)
tmux_session: channels
# 定时重启所有 agent(用于加载插件更新),标准 5 字段 cron 表达式
restart_schedule: "0 4 * * *"
agents:
sage:
state_dir: telegram-sage # 相对于 ~/.claude/channels/
agent: sage # agent 身份 (~/.claude/agents/<name>.md)
dir: ~/projects/my-project # 工作目录(claude 启动路径)
heartbeats:
- schedule: "0 9 * * *" # 标准 5 字段 cron:分 时 日 月 周
prompt: 早报摘要
- schedule: "0 20 * * *"
prompt: 晚间回顾
customer-bot:
state_dir: telegram-customer # 面向外部用户的 bot
agent: customer-bot
dir: ~/projects/customer
user_session: customer-user # 使用独立的 Telethon session(见「多用户认证」)
heartbeats:
- schedule: "0 9 * * *"
prompt: 推送每日内容
default:
state_dir: telegram # 默认 agent 用 telegram/
agent: my-assistant
dir: ~
常用 cron 表达式:
| 表达式 | 含义 |
|---|---|
| 0 9 * * * | 每天 9:00 |
| 0 */6 * * * | 每 6 小时 |
| 0 9 * * 1-5 | 工作日 9:00 |
| */30 * * * * | 每 30 分钟 |
| 0 0 1 * * | 每月 1 号 0:00 |
常驻的 channel session 在启动时加载插件(skill 列表、hook、MCP server)。插件更新后,已运行的 session 不会自动感知结构性变更。restart_schedule 通过定时重建 tmux window 解决这个问题。
dispatcher 匹配到 restart_schedule 时,依次对每个 agent 执行:从 tmux pane 状态栏捕获 session ID → kill tmux window → 用 --resume <session-id> 重建 window(与 /tg-restart 命令相同的逻辑)。这样重启后 agent 保持之前的会话上下文。重启当分钟跳过心跳发送,避免向正在启动的 agent 发消息。
dispatcher.py 每分钟被 launchd 触发,读取 agents.yaml,找到当前时间命中的 heartbeat,通过 Telegram Bot API 的 sendMessage 向对应的 channel session 发送消息。
消息格式:[定时任务 YYYY-MM-DD HH:MM] <prompt>
[定时任务] 前缀:作为协议标记,让 agent 身份文件可以包含针对此前缀的特定处理指令Agent 身份文件的系统提示词中应包含心跳处理说明,例如:
[定时任务] 消息时自动开始执行对应任务每个 channel session 绑定一个 agent 身份文件,赋予 bot 独立人格和能力范围。
文件位置:~/.claude/agents/<name>.md(全局)或 .claude/agents/<name>.md(项目内)
格式:
---
name: sage
description: |
<触发条件,支持 example 块>
model: inherit
color: purple
memory: user
---
<系统提示词:角色定义、能力范围、交流风格、心跳处理规则>
注意事项:
description 多行内容必须用 | block scalar,否则解析失败、agent 无法加载name 只能用小写字母、数字和连字符(3-50 字符)color 只接受 8 种值:red, blue, green, yellow, purple, orange, pink, cyanmemory: user 用于全局 agent(跨项目记忆),memory: project 用于项目 agent回复排版:Telegram reply 默认传 format: "markdownv2" 以及完整转义规则属于 Telegram 通用约定,写在用户全局 CLAUDE.md 的「Telegram Channel 交互」章节,所有接入 Telegram 的会话自动加载,不需要在每个 agent 身份文件里重复。
不配置心跳的场景:如果只需要 Telegram channel session(双向对话),不需要定时心跳,可以跳过 dispatcher 和 launchd 的安装。只需创建 agents.yaml、状态目录和 agent 身份文件,然后启动 tmux session。
配置心跳的完整安装:
~/.config/telegram-agents/,复制 ${SKILL_PATH}/scripts/dispatcher.py 和 auth.py 进去pip3 install pyyaml telethon 'python-socks[asyncio]'python3 ~/.config/telegram-agents/auth.py 完成默认用户的 Telethon 认证(一次性,输入手机号 + Telegram App 内验证码)。这使 dispatcher 能以用户身份发送消息给 bot,bot 的 getUpdates 才能收到~/Library/LaunchAgents/com.$USER.telegram-agents.plist,每分钟触发,StartInterval: 60cat dispatcher.py | python3 执行(绕过 macOS provenance 限制)为什么需要 Telethon:Telegram Bot API 的 sendMessage 发出的消息不会出现在 bot 自己的 getUpdates 中——这是 Telegram 的设计限制。Dispatcher 使用 Telethon(User API)以用户身份发送心跳消息,bot 的 channel session 才能正常接收。使用 Telegram Desktop 的公开 API 凭据,安全性等同于官方客户端。
当 bot 面向的不是 bot 拥有者本人,而是其他 Telegram 用户时,心跳需要以该用户的身份发送,否则 bot 的 access control(allowFrom)会拒绝消息。
架构:每个需要独立用户身份的 agent 在 agents.yaml 中指定 user_session 字段,指向一个独立的 Telethon session 文件。不指定则使用默认的 user.session。
添加新用户认证:
user_session: <session-name>python3 ~/.config/telegram-agents/auth.py <session-name>,以该用户的手机号完成认证~/.config/telegram-agents/<session-name>.sessionauth.py 支持命名参数:不带参数创建默认 user.session,带参数创建命名 session。
dispatcher 行为:发送心跳时按 session 分组,同一 session 的心跳共用一个 TelegramClient 连接。缺失 session 文件时跳过对应 agent 并记录错误日志,不影响其他 agent。
关键陷阱:
| 陷阱 | 原因 | 解决 |
|---|---|---|
| AbandonProcessGroup: true | launchd 主进程退出后会杀进程组,后台任务被终止 | plist 中加此键 |
| PATH 极简 | launchd 只有 /usr/bin:/bin,找不到 python3/pip 等 | plist 的 PATH 中补充 Homebrew、~/.local/bin、~/.bun/bin 等 |
| macOS provenance | Claude 创建的文件带 com.apple.provenance,launchd 拒绝直接执行 | cat \| python3 管道执行 |
| MTProto 被墙 | 中国大陆直连 Telegram MTProto 服务器会失败 | dispatcher 从 all_proxy/http_proxy 环境变量检测代理,但 launchd 环境没有这些变量——必须在 plist 的 bash 脚本中显式 export,否则 Telethon 会直连超时 |
方向:BotFather 建 bot → 创建状态目录 → 写 agent 身份 → 更新 agents.yaml → 在 tmux session 中添加 window。
状态目录结构:
~/.claude/channels/telegram-<name>/
├── .env # TELEGRAM_BOT_TOKEN=...(chmod 600)
└── access.json # 权限控制(见下方格式)
access.json 必须预填 bot 拥有者的 Telegram user ID,否则 bot 启动后进入 pairing 模式(要求用户发配对码),增加不必要的操作步骤。从已有 agent 的 access.json 中复制 allowFrom 列表即可:
{
"dmPolicy": "allowlist",
"allowFrom": ["<owner_telegram_user_id>"],
"groups": {},
"pending": {}
}
查找自己的 user ID:cat ~/.claude/channels/telegram/access.json | grep allowFrom
Channel session 管理:
所有 agent 共用一个 tmux session(名称在 agents.yaml 的 tmux_session 中定义),每个 agent 一个 window。
# 创建 session(首个 agent,window 名 = agent key)
tmux new-session -d -s <tmux_session> -n <name> -c <dir> "<command>"
# 添加更多 agent 到同一 session
tmux new-window -t <tmux_session> -n <name> -c <dir> "<command>"
其中 command 为:
TELEGRAM_STATE_DIR=~/.claude/channels/<state_dir> \
claude --channels 'plugin:telegram@claude-plugins-official' \
--agent <agent> --dangerously-skip-permissions \
--settings '{"enabledPlugins": {"telegram@claude-plugins-official": true}}'
默认 agent(state_dir=telegram)不需要设置 TELEGRAM_STATE_DIR。
启动前检查 409 冲突:ps eww 查找已有 bun 进程使用同一 token,有则先 kill。
首个配置心跳的 agent 必须经过此验证。确认整条链路通畅:dispatcher → Telethon → Telegram → bot getUpdates → channel session 处理。
方向:
~/.config/telegram-agents/user.session 存在)。未认证则先引导运行 auth.py/tmp/telegram-agents.log 确认出现 "Sent heartbeat for agent=..."tmux capture-pane 搜索 定时任务)常见问题排查:
auth.pyauth.pylaunchctl list | grep telegram-agents,确认 plist 已加载--debug-file 启动检查是否有 spawn bun ENOENT,确认 bun 在 PATH 中(launchd 重启的 agent 继承精简 PATH)~/.claude/settings.json 的 enabledPlugins 中删除 telegram@claude-plugins-official(禁止普通 session 轮询),不要卸载插件本身~/.claude.json 的 mcpServers 中注册 send-only 的 telegram-notify MCP,token 读取顺序:$TELEGRAM_BOT_TOKEN 环境变量 → ~/.claude/channels/telegram/.env仅影响使用 HTTP 代理的环境,无代理可跳过。
现象:通过 Telegram plugin 发送文件时报 Network request for 'sendDocument' failed!
根因:grammy 用 ReadableStream 构造 multipart body,Bun 1.3.x 的 fetch 在通过 proxy 发送 ReadableStream body 时有 TLS 记录排序 bug(oven-sh/bun#17434)。文本消息不受影响。
Workaround:在 Telegram plugin 的 server.ts 中,用 undici 的 fetch + ProxyAgent 替代文件上传请求。不改 grammy 源码,plugin 更新后需重新应用。
验证 Bun 是否已修复:运行 ${SKILL_PATH}/scripts/test-bun-proxy-stream.sh <chat_id>。输出 FIXED 则可移除 undici patch。
AbandonProcessGroup: true,否则 dispatcher 后台化任务后主进程退出,后台任务被立即终止com.apple.provenance 扩展属性,launchd 无法直接执行。用 cat | python3(dispatcher)和 echo | bash(shell 任务)绕过~/.local/bin 和 ~/.bun/bin。Telegram 插件的 MCP server 用 bun 启动(.mcp.json 中 "command": "bun"),缺少 bun 路径会导致 spawn bun ENOENT,agent 看似正常运行但完全收不到消息tools
Turn a YouTube link into a polished single-file bilingual (Chinese + original) transcript reading page. Use when the user gives a YouTube URL and asks to "转录" "做转录稿" "生成转录页面" "中英对照" "bilingual transcript" "transcribe this video", or wants a readable HTML transcript with clickable timestamps, chapter navigation, highlighted key points, and proper-noun annotations. Fetches captions + chapters via yt-dlp, the agent translates and curates, then a script renders the HTML.
development
Use when a user asks the agent to "learn" from a file, example, correction, failed workflow, or feedback and persist that learning into skills or agent instructions. Guides semantic skill refactoring: extract the transferable behavior, update the owning skill so it becomes clearer and easier to execute, avoid append-only note dumping, and decide when not to create new reference files.
development
以「配置即代码」的方式管理、调试 Clash Verge Rev(mihomo 内核)的配置,并实现不依赖 GUI 的配置更新。涵盖:哪些字段扩展脚本能改 / 不能改(external-controller、secret、端口被内核接管)、改了为什么不生效、如何在纯命令行下让配置重新生成并生效、mihomo external controller 这个内核 RESTful API 的用法、用 external-ui 自托管 Web 面板、以及判断流量「走没走代理 / 命中哪条规则」的排查方法。只要用户在改 Clash Verge / mihomo 的扩展脚本(script)、扩展配置(merge)、订阅规则、external-controller / secret / 端口、或抱怨「clash 配置改了不生效」「规则不命中」「远程连不上面板」「想自动化更新代理配置」,就应该用这个 skill。
data-ai
Configure and manage Telegram-connected Claude agents with heartbeat scheduling on macOS. Use when the user wants to "set up Telegram agent", "add heartbeat", "configure Telegram channel", "管理 Telegram agent", "配置心跳", "添加定时任务", "Telegram 多 agent", "配置 Telegram", "添加 Telegram agent", "给 Telegram bot 创建身份", "设置定时任务", "新增定时任务", "每天X点执行Y", "schedule a task", "run this automatically", "set up a cron job", or encounters Telegram polling conflicts, 409 Conflict, file upload failures through proxy, or needs to add recurring/periodic automated task execution for Claude agents.