不是"AI 应用"的空话。一份能跑、能改、能上线的教程 — 以 Telegram 团队 standup bot 为例,从 0 到生产部署。
这是 bot 真实发到我 Telegram 的一条消息。
周日早上 8:00,Hetzner 上的 systemd 触发,Claude 用懂我的 prompt 生成。
注意几个细节:它知道我在 Heidelberg(给具体徒步路线), 知道我会沿 Neckar 河骑车,知道我久坐一周。 这是 context engineering 的力量 — 不是 model 在猜,是 prompt 里已经写清楚了。
周日只发一条 — 不是技术限制,是纪律设计: 周日 bot 也休息,你也休息。
短答案:网页版 ChatGPT 只能你一个人聊天。但你真正想要的是 — bot 在你团队里自动工作。
| 能力 | 网页版 | 自建 bot |
|---|---|---|
| 定时主动触发 | 不能 | 能(每天 18:00 自动提醒) |
| 多人协作 | 不能 | 能(整个 TG 群共享) |
| 访问私有数据 | 每次粘贴 | 能(数据库 / API) |
| 定制人设 | 每次重复 | system prompt 一次写好 |
| 跨平台调用 | 不能 | Telegram / Slack / 钉钉 / 微信都能 |
自建的核心价值 — bot 是异步在线的同事,不是你的私人助手。
不要被"AI 应用"的概念吓到。一个能跑的 Claude bot 只需要 4 个组件。
# 整体架构
用户在 Telegram 群发消息
↓
Python Bot (你自己写,跑在服务器上)
- python-telegram-bot
- apscheduler (定时任务)
- sqlite3 (本地数据库)
↓
CLIProxyAPI (LLM 网关)
- OpenAI/Anthropic 兼容
- 多 provider 路由 + load balance
↓
Claude API (Anthropic)
- claude-sonnet-4-5 (日常)
- claude-opus-4-7 (深度分析)
这是你的"应用",处理 TG 消息、定时触发、调用 Claude。本教程展示的 ~600 行代码就是它。
CLIProxyAPI 是一个开源 proxy,把多个 LLM provider 统一成 OpenAI 兼容 API。好处:换 model 不改代码、统一鉴权、多 key 负载均衡。
最强的 LLM 之一。这个页面就是 Claude 写的。
整个 bot 的"LLM 入口"。15 分钟,在你服务器上装好。
git clone https://github.com/router-for-me/CLIProxyAPI.git
cd CLIProxyAPI
go build -o cli-proxy-api ./cmd/server
# Claude OAuth (需要 Claude Pro/Max 订阅)
./cli-proxy-api --login --claude --no-browser
# 或 Gemini OAuth (免费)
./cli-proxy-api --login --no-browser
host: "127.0.0.1"
port: 8317
api-keys:
- "用 openssl rand -hex 32 生成"
your-api-key-3,网上公开,不换 = 全世界都能用你的 Claude 配额。
curl http://127.0.0.1:8317/v1/messages \
-H "Content-Type: application/json" \
-H "x-api-key: 你的key" \
-H "anthropic-version: 2023-06-01" \
-H "User-Agent: claude-cli/2.1.44 (external, sdk-cli)" \
-d '{"model":"claude-sonnet-4-5-20250929","max_tokens":50,"messages":[{"role":"user","content":"hi"}]}'
User-Agent: claude-cli/... 这个 header 关键 — CLIProxyAPI 看到非 Claude CLI 的客户端会注入 ~1358 token 的"伪装提示",干扰 system prompt。带上这个 header 它就放行。
TG 搜 @BotFather,发 /newbot,起名,拿 token。
@BotFather → /mybots → 你的 bot → Bot Settings → Group Privacy → Turn off。
建 TG 群 → 启用 Topics → 创建 "Daily Standup" topic → 加 bot,给 admin 权限。
用 @RawDataBot 在你群里发一条消息,获取 chat.id、message_thread_id、每个成员的 from.id。
下面这段是 bot 的核心 — 客户端初始化 + Claude 调用 + Telegram 处理。能跑。
python3 -m venv venv
source venv/bin/activate
pip install python-telegram-bot anthropic apscheduler python-dotenv
from anthropic import Anthropic
import os
# base_url 指向 CLIProxyAPI
# User-Agent 让 proxy 跳过 cloak
claude = Anthropic(
base_url=os.getenv("CLAUDE_API_BASE_URL", "http://127.0.0.1:8317"),
api_key=os.getenv("CLAUDE_API_KEY"),
default_headers={
"User-Agent": "claude-cli/2.1.44 (external, sdk-cli)"
}
)
CONTEXT = """
你是一个 5 人小团队的教练 bot。团队在做 0 → 1 产品,
目标 4 周内拿到第一个付费客户。
团队角色:
- 1 名 CEO (兼供应链)
- 3 名工程师 (后端 / 移动 / 前端)
- 1 名 BD (唯一对外销售)
你的任务:
1. 看到 standup,给"懂业务"的反馈
2. 识别反复出现的 blocker
3. 不浮夸吹捧,不冷漠数据
"""
def generate_summary(checkins):
prompt = f"今日 standup:\n{format_checkins(checkins)}\n\n生成 150 字小结。"
message = claude.messages.create(
model="claude-sonnet-4-5-20250929",
max_tokens=400,
system=CONTEXT,
messages=[{"role": "user", "content": prompt}]
)
return message.content[0].text
from apscheduler.schedulers.asyncio import AsyncIOScheduler
scheduler = AsyncIOScheduler(timezone="Europe/Berlin")
scheduler.add_job(send_reminder, "cron", day_of_week="mon-fri", hour=18, args=[bot])
scheduler.add_job(send_daily_summary, "cron", hour=20, args=[bot])
scheduler.add_job(send_weekly_retro, "cron", day_of_week="fri", hour=17, args=[bot])
scheduler.start()
# message_thread_id 必须带,否则发到 General topic
async def send_to_topic(bot, text):
await bot.send_message(
chat_id=GROUP_CHAT_ID,
message_thread_id=STANDUP_TOPIC_ID,
text=text,
parse_mode="HTML"
)
本地能跑只是开始。部署成 systemd service,让它 7x24 在线、崩了自动重启。
[Unit]
Description=Daily Standup Bot
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/standup-bot
ExecStart=/opt/standup-bot/venv/bin/python /opt/standup-bot/bot.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable standup-bot
sudo systemctl start standup-bot
sudo journalctl -u standup-bot -f
| 项 | 费用 | 说明 |
|---|---|---|
| VPS (Hetzner CX11) | ~$5 | 1 vCPU + 2GB |
| Claude API | ~$2-5 | 每天 2 次 Sonnet 调用 |
| Telegram | 0 | 免费 |
| 合计 | ~$10/月 |
bot 的灵魂不是代码,是 system prompt。同一段代码 + 不同 prompt = 完全不同的 bot。
prompt = "总结这些团队消息: " + checkins
Claude 写得像 ChatGPT 的默认回答 — 通用、安全、没记忆。
给 Claude 完整背景: 团队规模、阶段、KPI、成员角色、行业黑话、语言风格。Claude 会用团队内部语言、记得 KPI、识别 blocker。
这就是 Anthropic 圈说的 "context engineering" — 你 90% 的优化精力应该放在 system prompt,不是模型。
Daily standup 只是开始。同一套架构,换 prompt 和数据源,能搭很多东西。
这些不是 best practice 列表 — 是我亲身踩过、改过的真实问题。
最早 bot 我想偷懒,不开服务器,直接用 GitHub Actions 的 schedule cron 跑。
看起来完美 — 免费、零运维、yaml 一行搞定。
# 我以为这就行了
on:
schedule:
- cron: '0 18 * * 1-5' # 每天 18:00,我以为
实际上: GitHub Actions 的 scheduled workflow 不保证准时。 官方文档明说"may be delayed during periods of high load"。 实测漂移 20-40 分钟很常见,偶尔会跳过整次执行。
# Hetzner Cloud €4.5/月 的 VPS
# apscheduler 触发精度 < 1 秒
scheduler = AsyncIOScheduler(timezone="Europe/Berlin")
scheduler.add_job(send_reminder, "cron",
day_of_week="mon-fri", hour=18, minute=0)
scheduler.start()
这种方案的成本: €4.5/月 = €54/年。
获得: 毫秒级准时 + 100% 可用率 + 顺便能跑 VPN / blog / API 网关。
用的是 Hetzner Cloud (CX11) — 德国机房,EU 时区延迟低,适合 bot 跑欧洲业务时间。
安装后默认 key 是 your-api-key-3,网上文档里就有,不换 = 全世界都能用你的 Claude 配额。
第 03 章已经讲过,这里强调一次 — 这是新手最容易漏的安全坑。
第 03 章讲过,但值得重复:不带 User-Agent: claude-cli/... 时,
CLIProxyAPI 注入 ~1358 token 的"伪装提示",会干扰你的 system prompt 让 Claude 行为偏移。
第一次 debug 这个花了我半天。
你在 Topic 里写代码测试很顺,部署后 bot 发到了 General(默认主频道)。
原因: send_message 时没传 message_thread_id。
这是 Telegram Topics 功能的"隐藏陷阱" — API 不会报错,只是默默发错地方。
第 04 章讲过。但说实话,我第一次部署完发现 bot 收不到打卡时,排查了 1 小时 才意识到是 BotFather 里的 privacy 设置。记下来,以后部署前永远先关 group privacy。