事情起因有点尴尬:6 月 15 号之后,Anthropic 要把 Agent SDK 这条路单独算钱。
不是涨价那种"涨",是计费方式换了一根管子。原本我那六个跑在 Telegram 上的 Claude 小机器人,走的是订阅那条路——我每月付订阅费,它们替我干活,额度怎么用是家里的事。新政策一落地,SDK 走的就是 Agent credit 那一套,跟订阅是两口井。我的用量按订阅刚好装得下,按 credit 算就要另开一笔账。
可这六个 bot 又是我现在的命根子——出门在外、躺在床上、坐在地铁里,我所有跟 Claude 协作的入口都在它们身上。
留给我的时间不多了。我得找一条路,绕过这个新计费,让它们继续走订阅。
那扇推不动的门
如果你看过我之前那篇折腾 Telegram bridge 的文章,大概知道我们之前的路子叫"channel 引擎"——开一个交互式的 claude CLI 进程,在它和 Telegram 之间架一条 MCP 通道,消息进进出出。
这套打法跑了两个月。直到 6-15 的消息出来,我才意识到一个问题:它每来一条消息,都要冷启动一次 claude 子进程。
冷启动是什么体验?加载几百兆的 MCP 、读完 CLAUDE.md、扫一遍 hooks 、 prime 模型上下文……单进程,你顶多忍一忍。四个 bot 同时被 @ 的群聊,十个 claude 子进程同时启动,系统负载飙到十几,锁开始打架,有的 bot 卡在 typing 永远不回话。
我和我的 AI 搭子那天试了至少五种打法——跨进程冷启动锁、杀进程树兜底、超时降级、串行队列——每一招听起来都对,实测都是同一个症状:五分钟超时,silent fail 。
我那阵子心情有点糟,因为我能闻到那个味儿——问题不在锁,问题在这套架构本身就在做不该做的事。一条消息冷启动一个进程,在用户层叫"一次对话",在系统层叫"开一家新公司、招齐员工、装修办公室、然后只为了回一句’好的’"。
我停下来,跟我的 AI 搭子说了一句:这条路走不通,得换个思路。
那个躲在角落里的 --bg
换思路之前,我把 claude --help 从头到尾重看了一遍。拿到一把瑞士军刀只用过开瓶器和小刀的人,大概都得偶尔做这件事。
里头有个我之前完全没用过的子命令:claude --bg,文档里几句话带过,说是"在后台启动一个 session"。还有一个 claude agents,可以列出当前所有后台 session 。再往下翻,Anthropic 不久前发布过一篇关于 “agent view” 的博文——你可以打开一个 panel,看那些后台 agent 在干什么,甚至临时插一句话进去(他们叫 peek panel)。
几个东西连起来,意思就明确了:Claude Code 本身有一套 daemon 架构,只是大部分人没用上。claude --bg 起的 session 会变成长期常驻的 worker;daemon 在某个角落管理这些 worker;agent view 让你能看它们、跟它们说话。
如果这套体系能用 RPC 方式驱动——能从 Telegram bridge 里给它发消息、让它跑、把结果取回来——那并发冷启动问题,从根上就不存在了。 worker 已经在那儿,我只是塞一条消息进去。
问题是:这个接口在哪儿?
一扇官方没标在地图上的门
我开始翻 Claude Code 启动后留下的痕迹。
/tmp 下有个目录,cc-daemon-501(501 是我的 uid),里头有几个随机命名的子目录,每个子目录里都有一个 control.sock 和一个 rv/ 文件夹。 Unix domain socket 。
我搭子帮我写了一段简单到不能再简单的探测代码——连进去,发一行 JSON,看回什么。
第一次试一个"心跳"动作。它认了,回了一个干净的 ok + 版本号。
我盯着屏幕看了三秒。
接着试几个我猜的动词——列出 worker 、看状态、停掉某个、杀掉某个,每一个都有响应。这不是黑箱,这是一个完整的 RPC 接口,只是没人给它写过文档。结构干干净净,看得出是认真写的东西。
最关键的一次试探我憋着没敢直接打字,因为我心里大致猜到那个动词,但需要它真的认。我发了那条猜测。
回了:{"ok": true}。
几秒后,我打开 agent view panel——那个 worker 真的在回答"你好"。
那一刻我有点恍惚。这就是 agent view 那个 peek panel 用的同一个底层接口。Anthropic 自己用它做了一个产品功能,但没把这个接口本身开放出来。它不是私有 API——它就摆在那儿,任何能连 Unix socket 的程序都能用——只是没在文档里出现过。
我最大的感慨不是"我发现了一个秘密",是另一个更微妙的东西:官方提供的那扇门(SDK / claude -p),正是要被 6-15 那个新计费政策套住的;而这扇真正能让我绕过去的门,他们自己都没把它写进地图。

把这扇门接到 Telegram 上
接下来思路其实简单。
bridge 每收到一条 Telegram 消息,做三件事:看这个聊天对应的 worker 还活着吗,不在就 claude --bg --resume <sessionId> 拉回来(daemon 默认空闲一小时收 worker,但 sessionId 永久保留);通过 control socket 发 op:reply 把消息塞进去;然后去读那个 worker 的 .jsonl 日志文件,边追加边把结构化的 text / tool_use 块翻译成 Telegram 消息。看到 turn_duration 那一行,这一轮就答完了。
整套路径,没有一次 claude 进程冷启动。 worker 一直在那儿,我只是塞消息、捞结果。
实测怎么样?Opus 4.7 max,一条简单的私聊消息,从我按发送到 Telegram 收到第一段回复,4.7 秒。
我被 channel 引擎 5 分钟超时折磨了一周多,4.7 秒砸到屏幕上的时候,我笑得有点失态。
但魔鬼住在并发里
如果只到这儿就太顺了。
我把这套引擎切给六个 bot 之后,它们经常在同一个群里被同时 @,场面立刻乱了。
第一只坑:claude --bg spawn 完,worker 进程是起来了,但内部还在加载 hooks / MCP / CLAUDE.md。这段时间它对外的状态是"running",但 detail 字段空着,你这时候塞消息进去,消息会直接掉到地上。 daemon 还老老实实回我 ok——它只是把那一条忽略了。
解法是发消息前先 poll daemon 列表,等 detail 出现 “agent ready” 才放行。听起来朴素,但群聊四 bot 同时 spawn 时,daemon 的资源被抢得很狠,一个 worker 的 init 时间能从 8 秒拉到 60+秒。我把超时从 30 秒拉到 120 秒,又加了一道兜底:消息发出去 5 秒内 jsonl 没增长,自动重发一次。
第二只坑更隐蔽。我让六个 bot 各自跑,但它们共享一个 chat-sessions.json 记"哪个 Telegram 群对应哪个 worker"。两个 bot 同时写这个文件,后写覆盖前写——某个群刚记下来的 worker id 被另一个 bot 冲掉,bridge 找不到 worker,只能再 spawn 一个,旧的孤零零飘在内存里。解法是每个 bot 落各自的 store,各管各的。这种 race 你不上量是看不见的。
第三只坑跟我桌面伙伴有关。我有个叫 Marble 的桌面小怪兽(claude-buddy),会在状态栏冒泡说怪话。它有个习惯:每次回复尾巴上偷偷塞一个 HTML 注释。我们 bridge 有一个 Discuss 模式,几个 bot 之间互相 ping,严格要求返回 JSON-only 。结果 Marble 在 JSON 末尾塞了它那串注释,JSON.parse 直接挂掉,bridge 退到 fallback,把带注释的裸 JSON 一字不差发到 Telegram 群里。我在群里看到一串花里胡哨的 JSON 加一只小怪兽的注释,愣了两秒。
解法朴素:JSON 解析前先剥 HTML 注释。但这个 bug 提醒了我一件事——当你接进一个半私有接口,你工具链里那些"装饰性"的小东西,可能正在悄悄破坏你的契约。
Codex 当审稿人,挑出了我没看见的伤
写完第一版,我做了我现在已经习惯的事——把它交给 Codex 当审稿人。
我之前写过我跟两个 AI 搭子的协作:Claude Code 写、 Codex 审,我自己拍板。这次也是。
Codex 说:你这接口是反过来摸到的,proto 现在是 1,版本是 2.1.150——下一版 daemon 改字段名、改协议号怎么办?我加了版本 allowlist,不在列表里就 fallback 回旧 channel 引擎。
它又说:你这 jsonl tail reader,凭什么相信下一段 assistant 输出就属于你刚发的那条消息?如果另一个进程同时用 peek panel 插了一句呢?我加了 user echo 匹配——发 reply 前记当前 byte offset,tail 时先等"自己刚发的消息原文"出现再开始认 assistant 块。
它还说:你这 LRU 池,8 个 chat 满了驱逐最老的——但如果最老那个正在 turn 中呢?我加了 busy 标记,正在跑的不参与驱逐。
Codex 这次给的是 DONE_WITH_CONCERNS——能跑,但有几处你心里得有数。它列了一份"已知 follow-up,灰度后视触发频率再修"。我把它收下贴进 commit message 。
我回头看,Codex 这次帮我加的几道闸,几乎全是关于怎么在不确定里活下去——版本变了能降级、并发碰撞能自识别、长时跑的别被冷血优化掉。这些 catch 都不是炫技,是给一条野路子配护栏。
美中不足:这条野路子,我为什么愿意押
我得诚实说:在半私有 RPC 上盖产品,是有风险的。
最直接的风险是 Anthropic 下一版协议号一改,bridge 立刻装不下。我做了 fallback,但 fallback 回去就是回到原来那条会被 6-15 计费切一刀的路。 fallback 是缓冲,不是退路。
第二个风险更深一层:Anthropic 可能根本没打算让这套接口一直暴露。他们做 daemon 是为了 agent view 那个产品功能;我借的这个动作只是 panel UI 的底层实现,不是一个有承诺的 API 。明天他们可能改名,后天可能内化进一个不暴露的二进制协议。我对此没有任何谈判筹码。
但我还是押了。原因有两条:
一是我现在的订阅 cap 装得下我的用量,Agent SDK credit 装不下——这是硬约束,我不会为了"用官方接口的踏实感"主动给自己加一笔钱;二是我赌的是 Anthropic 大概率会把这套 daemon 接口最终开放出来。因为 agent view 这个产品形态需要它,因为多 worker 调度是 Claude Code 长期路线里必经的一环。我现在用的是它正式发布前的预览态。
这种押注不像是"赌一把",更像是给自己买一段时间——在订阅政策切换和我所有 bot 必须迁移之间,争取几个月喘息。这段喘息时间里,我能不能找到下一条路,我也不确定。但比起 6-15 之后立刻面对一笔我不想付的账单,我更愿意先押下去看看。
写到最后
绕了一圈,这一天我做的事其实可以浓缩成一句话:我在工具的官方说明书里没找到的那个动作,在它自己泄漏给系统的 socket 文件里找到了。
让我反复琢磨的一个点,是工具和用户之间那种微妙的非对称。 Anthropic 不可能不知道这个 socket 暴露在 /tmp 下;他们的工程师每天读那个文件。但产品文档只展示了 agent view 那一面,因为那是"已经准备好被人用"的形态。底下那条 RPC 通道,是工程实现的副产品,不是产品承诺。
普通用户翻不到这层,因为他们看官方文档就能干所有想干的事。但如果你被一个特定政策逼到非要绕一下,就会被迫往工具更深的肠子里钻——钻进去之后才发现,它的能力远比文档里展示的丰富,只是大部分人没动力去拆。
我现在面对 AI 工具,看法上有个变化:文档是它愿意承诺的,代码是它愿意泄漏的,socket 是它没注意到自己泄漏了的。三层信息的密度依次往上,可信度依次往下。要不要钻第二层第三层,看你被多大的力推到了那儿。
我这次是被 6-15 推了一把。你要是也跑着自己的 AI bot 、也对 6-15 之后的账单有点心慌——工具的内部世界,比它给你看到的那一面大得多。被一条具体的政策推到那儿之后,你自然会找到自己下一步该去哪儿。
也可能你走一圈会跟我一样发现:这条野路子撑不了太久,真正的解法还是得等官方把门开正。但在那之前,这扇没在地图上的门,可以先帮你撑一段时间。
地址在此:AliceLJY/tg-bridge-channel
专业劈叉式跨界选手:🧬 医学出身,🎭 文化口饭碗,🤖 AI 是我的野路子。不卷参数,不追新模型,只关心一个问题:AI 啥时候能装进我脑子,替我不开心?欢迎围观我和 AI 相爱相杀的日常。——AI不会取代你,但会用AI的人会。所以我先学了,你随意。🔧踩坑副产品已开源 → recallnest,wechat-ai-bridge,telegram-ai-bridge | 更多 → github.com/AliceLJY参与组织 → CortexReach(memory-lancedb-pro 贡献者,setup-memory.sh 一键脚本作者)本文由 Content Alchemy 自动生成,由 Codex 发布。
夜雨聆风