SYSTEM DESIGN · 2026-05-26

Claude Code 怎么"指挥"云电脑发抖音私信

整套系统其实没有"指挥"。云电脑藏在很深的网络里、外面找不到,所以反过来——它自己每分钟来公告板取活儿。理解这一点,整张图就通了。

触发节奏 · 每 5 分钟 单账号节奏 · ≥ 45 分钟一条 单账号日上限 · 18 条 横向扩展 · 1 台云电脑 = 1 个抖音号

一句话画面

把它当成一家 "远程帮你发抖音私信的代发公司"。 公司里有 8 个角色:闹钟、派单员、共享公告板、N 间远程办公室,每间办公室里坐着小助理、动手的人、还有一双 AI 视力,桌上摆着一台开着抖音电脑版的电脑。 全公司没有任何一根电话线直接打进远程办公室——所有信息都通过公告板中转。这是整套系统能在 NAT、IP 漂移、风控之下稳定运转的根因。

全景图 — 一张图看清整个公司

① 闹钟 每 5 分钟响一次 叫派单员起床 ② 派单员(云端) 翻每个抖音号的小本本 • 上次发消息 < 45 分钟 → 跳过 • 今天已发 ≥ 18 条 → 跳过 • 都通过 → 从候选池挑一人,写一张派单 贴派单 ③ 共享公告板 — 公司中央的一面墙 [小张号] 联系王女士 "看到您主页很喜欢,请问做装修吗" 待办 [小李号] 联系陈先生 "看您家在装修,方便聊几句吗" 已发 规则: • 谁都能看,谁都能贴 • 一张便签只能被一个人撕下来 • 撕下来 15 分钟没回 → 自动贴回去 这意味着:同一个人不会被两台云电脑同时发 真名:Supabase dispatch_queue 表 ④ 远程办公室 #1(云电脑,绑定"小张号") 小助理 每 60s 去公告板 撕指给本办公室的便签 动手的人 鼠标 + 键盘模拟真人 9 步搜索→匹配→粘贴→发 AI 视力 看一眼对方主页 ≥ 95% 才放行 ⑦ 桌上的抖音电脑版(普通客户端) 动手的人按完键盘 → 抖音客户端把消息 通过抖音自己的网络发往对方 (这一步是抖音内部,我们看不见也管不到) ⑧ 抖音 服务器 推送给对方 本机系统层(不走网络) 远程办公室 #2 绑定"小李号" 结构同 #1 远程办公室 #N 每台 = 一个号 独立 IP 每 60s 撕一张 干完贴回执
绿色 = 云电脑主动来取 / 回写 · 紫色 = 派单员往公告板贴 · 公司里没有任何一根线从外面直接打进云电脑

8 个角色 — 谁是谁的"真名"

① 闹钟Vercel Cron · */5 * * * *

没有任何业务判断,唯一职责是"每 5 分钟敲一下派单员"。Vercel 平台内部触发,不消耗任何对外网络。

② 派单员/api/cron/cloud-pc-dispatch · runDispatch()

跑在 Vercel 的一段代码。看每个抖音号"上次发是几点"、"今天发了多少条",节奏不到就跳过。最后把通过的人挑出来,往公告板贴一张便签。

③ 共享公告板Supabase Postgres · dispatch_queue 表

整套系统的交汇点。一张表,存所有派单。云端写入 + 云电脑读取走的是同一张表的两面,谁都不需要"找到"对方。"撕单子 15 分钟不回自动还回"这个机制由数据库里一个 RPC 函数保证。

④ 小助理wuying_poll_agent.py · 常驻 60s 循环

跑在每台云电脑里的 Python 进程,开机自启。一直待在办公室里,每分钟去公告板看一眼。它只认识带本办公室 ID 的便签(一张抖音号 = 一台云电脑 = 一个 account_id)。

⑤ 动手的人douyin_dm.py · pyautogui + pyperclip

真正模拟真人发消息的脚本。9 步固定动作:点搜索框 → 粘抖音号 → 等结果 → 点"用户" tab → 双因子匹配 → 点进主页 → 找私信按钮(双击兜底) → 粘贴消息 → 回车。每步之间留 1~3 秒像真人。

⑥ AI 视力Claude Vision · screenshot → API

进入对方主页后强制停一下,把屏幕截图发给 Claude,让 AI 看:"这个昵称和我手上工作单写的,是同一个人吗?"相似度 ≥ 95% 才继续。抖音搜索结果同名号一抓一大把,这是最后一道防认错人的关卡。

⑦ 桌上的抖音电脑版抖音 PC v7.8.0 客户端

就是普通用户装的抖音电脑版,登录着"小张号"。在它眼里没有自动化——它收到的是一连串"用户按了鼠标 / 用户敲了键盘"的系统事件,和真人操作完全一样。

⑧ 抖音服务器抖音 IM API(黑盒)

客户端按 ⌨️ 把消息送过来,抖音服务器收下,推给对方账号。这一步完全是抖音内部,我们看不见、不可控——也正因此,没有办法绕过客户端用 API 发,必须有一台真电脑装真客户端。

信息通道详解 — 每一跳到底是谁找谁

把每一跳的"谁主动 / 用什么方式 / 带什么东西"列出来:

从谁到谁 方向 用什么方式 带什么
1 闹钟 → 派单员
Vercel Cron → Vercel Function
平台内部 云端内部触发
HTTPS + Bearer CRON_SECRET
只是个"叫醒"信号
无业务 payload
2 派单员 → 公告板
Vercel Function → Supabase
写入 数据库写入
HTTPS · PostgREST
插入一行 pending 便签
(account_id, target, content)
3 云电脑 → 公告板
poll_agent → claim_dispatch RPC
主动取 云电脑主动来抢锁
HTTPS · supabase-py RPC
"撕下来" ≤ 3 张属于本办公室的便签
原子操作 + 15min 死锁回收
4 小助理 → 动手的人
poll_agent → douyin_dm.py
本机 子进程 + CSV 文件
subprocess.run
一份 contacts.csv
(_dispatch_id, sec_uid, content)
5 动手的人 → 抖音客户端
douyin_dm.py → 抖音 PC
本机 不走网络 OS 层模拟键鼠
SendInput · 剪贴板
9 步动作序列
点击坐标 + Ctrl+V + Enter
6 动手的人 ⇄ AI 视力
screenshot → Anthropic API
双向 调用 Claude
HTTPS · Vision API
主页截图 + 期望昵称
返回 0~1 匹配分
7 云电脑 → 公告板
poll_agent → complete_dispatch RPC
回写 数据库 RPC
HTTPS · supabase-py
"这张便签干完了 / 失败了"
+ mark_lead_contacted 永久去重
8 抖音客户端 → 抖音服务器 抖音自家协议
HTTPS · 我们看不见
消息内容
由抖音 IM 路由
看这张表的关键:跳 3 和跳 7 都是「云电脑主动来」。Vercel 那边永远不知道哪台云电脑在线、IP 是什么、有没有重启。它只管往公告板贴。云电脑那边就算重启 5 次、IP 换了 8 次,也照样能继续工作——因为锁回收和便签都还在公告板上。

应急通道 — 公告板卡住时手动补一条

平常这家公司是全自动的。但有时候我(Claude Code,在 Mac 上)需要亲自跳进去看看——比如新版部署后第一条 DM 现场验证、或者公告板卡住了想手动塞一条。这条小后门是这样的:

我(Mac 上的 Claude) 写一句"把这条发给 X" 带一个共享暗号 Cloudflare 中转站 给云电脑一个临时门牌 trycloudflare.com 临时网址 云电脑里的接线员 cloud_pc_server :8765 一直挂着等指令 动手的人 同主链路 HTTPS + X-Secret QUIC 反向隧道 为什么要中转站? 云电脑藏在 NAT 后面,外面找不到它 → 让云电脑"从里面伸一根线挂在中转站门口" 最后一公里同主链路
红色 = 推送方向 · 这条路是反过来的:云电脑主动"伸线"建反向隧道,外部请求顺着隧道倒灌回来
这条通道的边界:临时网址每次云电脑重启都换;只在联调 / 队列卡住时人工用。生产 DM 还是走公告板那条主链路——后门没有节奏闸、也不写公告板,绕过去 = 同一个人有可能被两台云电脑同时发,请谨慎。

为什么这么设计 — 几个"看上去多此一举"的解释

为什么派单员不直接告诉云电脑"该干活了"?非要走公告板?
云电脑藏在很深的网络里(在阿里 IDC 的 NAT 后面),外面根本找不到它。要么云电脑出公网门牌号(贵 + 风控会盯)、要么反过来"让云电脑自己来取"。我们选了第二种。代价是有 60 秒延迟,收益是云电脑可以随便重启 / 漂移 / 加台数,外部完全无感。
为什么一张便签只能撕一次,还要 15 分钟自动贴回去?
同一个抖音用户不能被两个号同时联系——对方一眼就能看出"为什么两个无关账号都来骚扰我",立刻举报。15 分钟自动贴回是兜底:万一一台云电脑撕了便签后突然断电 / 重启,便签会自己回到公告板,让另一台继续。两种情况都用数据库的"原子操作"保证不会出错。
为什么派单员要看"上次几点发的"再决定派不派?
真人不可能每 3 分钟连发 20 条私信。节奏太密 = 抖音风控当场判定机器人,账号封禁。45 分钟 + 随机抖动模仿真人节奏;每天 18 条上限对应"运营白班 8 小时手动发"的速率。这两个数字不是拍脑袋——是 5/21 PoC 实测下来的安全区。
动手的人为什么不直接调抖音 API,非要点鼠标?
抖音不开放发私信的 API(开放过的早就被滥用了)。能用的"通道"只有真人客户端。所以让一台云电脑装真客户端、登真号、由脚本模拟键鼠"像真人一样"操作。这也是为什么必须用云电脑——本地 Mac 装抖音电脑版也行,但风控会看 IP,多账号同 IP = 必封。云电脑给每个号配独立 IP。
为什么进对方主页后还要让 AI 视力再看一眼?
抖音搜索结果按抖音号搜,看似精确,但同昵称号一抓一大把——搜"王女士"出来 25 个。第一道我们用"昵称 + 抖音号"两个字段一起对,但偶尔 UI 上抖音号渲染慢、被截断、识别错位。截图给 Claude 看一眼"屏幕上这个人和工作单写的是同一个吗"是最后一道保险,相似度 < 95% 整单立即跳过,不发。
为什么把"小助理"和"动手的人"拆成两个进程?
这两件事关注点完全不同。小助理是个稳定的轮询循环,需要长时间稳定运行 + 跟数据库通信。动手的人是高风险的 UI 操作脚本,可能因为抖音弹窗 / 网络抖动 / 元素加载慢而卡死。拆开之后,动手的人卡死或崩溃,小助理可以单独干掉它、重新调起;小助理本身也能被外部脚本(比如运营手动跑 dispatch-leads.ts)复用。

相关文档

15 · CLOUD PC 上手指南 — 从零到第一条 DM 的 30 分钟流程 · 07 · DM 投递与引导加微 — 整条 DM 链路的产品视角 · 03 · 双链路防风控 — 节奏闸 / 视力校验在防风控体系里的位置 · 02 · 系统架构详解 — Akke 三段式架构全景