团队内部 · 新人入职 · DM 发送链路

抖音 DM 发送 Onboarding

从 0 到自己跑通一条已审消息的全流程:环境搭建 + 日常 SOP + 故障排查 + 红线。预计 1.5 小时。

更新于 2026-05-06 路径:iPhone + WebDriverAgent + 抖音 App 团队内部使用,请勿外传
📌
这是给谁看的? 刚加入 Akke、需要承担"DM 审核 + 发送"工序的同事。读完后你能独立跑:从 Akke 后台审核已通过的 DM 草稿 → 在你的 Mac + iPhone 上把消息真的发出去。

读完前请准备:一台你自己的 Mac、一台 iPhone(13 / 14 / 15 / Pro 都行)、一根原装数据线、一个你自己的 Apple ID。
🤖
嫌看文档慢? 这份教程有一个对应的 "AI 代跑版" markdown 文件 —— 找现任 Owner 要 akke-wda-dm-playbook.md,把它喂给你 Mac 上的 Claude Code,AI 会带你逐步执行命令,遇到必须人做的环节会停下问你。推荐做法:先扫一遍本页心里有数 → 再开 Claude Code 喂 .md 实际操作。
📖 目录
① 这条 DM 链路在干什么 ② 邀请清单(找现任 Owner 拉你进哪些平台) ③ 硬件 + Apple ID 清单 ④ 一次性环境搭建(A 主线 · 1.5 小时) ⑤ 日常开盘 SOP(B 主线 · 5 分钟) ⑥ 故障排查(按症状 → 修法) ⑦ 红线 · 不要踩 ⑧ 一页速查卡

1这条 DM 链路在干什么

Akke 的 DM 发送是一条"先审后发"的流水线,你的工作发生在最后两环

抓评论 → AI 评分 → AI 起草 DM
   ↓
你在 Akke 后台审核(通过 / 编辑 / 拒绝)  ← 你做这一步
   ↓
被通过的 DM 落入 Supabase message_queue 表(状态 approved)
   ↓
你 Mac 上跑 dm_send_v3.py 拉取 approved 行   ← 你做这一步
   ↓
脚本通过 WebDriverAgent 操控你的 iPhone 抖音 App 发送
   ↓
回写 sent / failed 状态

关键认知:

2邀请清单

动手装环境前先把这些账号开好。所有邀请都找现任项目 Owner(在 Lark "Akke 智能获客系统群" 里 @ 一下即可)。

平台 等级 用途 邀请方做什么
Akke 应用账号
akke.upio.ai
必备 登录 dashboard 审核 DM 草稿、看 message_queue 状态 Owner 进 /team 邀请你的邮箱,给 Operator 角色
worker .env
(凭据文件)
必备 本地 dm_send_v3 脚本访问 Supabase 取 approved 行需要这些密钥 Owner 通过 1Password / Lark 私密会话SUPABASE_URL / SUPABASE_SERVICE_ROLE_KEY / FLY_WORKER_SECRET 给你。不要发到群里。
GitHub 仓库
akke
必备 clone 项目代码(dm_send_v3.py 等脚本在这里) Owner 在仓库 Settings → Collaborators 加你的 GitHub 账号
Supabase 项目
app.supabase.com
强烈建议 出问题时直接查 SQL(如 message_queue 卡了哪条、conversations 状态机为啥不动) Owner 进 Project Settings → Team 邀请你的邮箱
Vercel 团队
vercel.com
可选 看前端构建日志、Cron 执行历史。日常发 DM 用不到。 邀请 + 关键一步见下方警告框
⚠️
Vercel 邀请的隐藏坑(如果你需要这个权限):
Vercel 邀请邮箱通过 ≠ 你 push 代码后 deploy 能通过。Vercel 校验的是 commit author 的 GitHub login,不是邮箱。
你需要做:登入 Vercel 后访问 vercel.com/account/login-connections,把你的 GitHub 账号绑定进去。否则你 push 后 Vercel 会拒绝部署,errorLink 是 team-configuration
检查清单 —— 全打勾再继续:
  • Akke 邮箱邀请已收 + 能登录 akke.upio.ai
  • 拿到 worker .env 内容(SUPABASE_URL / SUPABASE_SERVICE_ROLE_KEY / FLY_WORKER_SECRET)
  • GitHub 仓库已能访问 + 能 clone
  • (建议)Supabase 项目能登录

3硬件 + Apple ID 清单

要求 说明
Mac macOS 14+,建议 16GB 内存 跑 Xcode 编译 + Python WDA 客户端 + Akke worker。Intel / Apple Silicon 都行
iPhone iPhone 12 及以上,iOS 17+ 抖音 App 跑 WDA 自动化的真机。建议专门一台用于工作,不要混你日常生活用的
数据线 原装或 MFi 认证 USB 连接 Mac↔iPhone 全程要插着,不能拔
Apple ID 自己的 Apple ID(任何区都行) 用来在 Xcode 里登录 Personal Team(免费个人开发者)。不要用公司共享 ID
抖音账号 已登录 iPhone 抖音 App Owner 给你分配一个工作号;自己日常号不要用来跑 Akke
💡
Apple ID 个人开发者 vs 公司账号:我们用的是免费的 "Personal Team"(任何 Apple ID 默认都能开)。这有一个限制 —— 编译的 WDA 证书只能用 7 天,过期后要重新 build & install 一次(约 5 分钟)。等团队规模大了再升级到付费 Apple Developer Program ($99/年,证书 1 年期)。

4一次性环境搭建(A 主线)

下面 10 步是第一次开搞前要走一遍的,预计 1-1.5 小时(Xcode 下载占大头)。每步独立,做完一步打 ✓ 再下一步。

第 1 步

装 Xcode + 命令行工具

Mac App Store 搜索 "Xcode" → 下载(约 12 GB,需要 1-2 小时网速看人)→ 装好后必须打开一次接受协议

然后终端执行:

xcode-select --install
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
xcode-select -p   # 输出 /Applications/Xcode.app/... 即就绪
第 2 步

Apple ID 登录 Xcode + 开 Personal Team

  1. Xcode 打开 → 顶部菜单 Xcode → Settings → Accounts → 点 "+" 加你的 Apple ID
  2. 登录后会自动生成一个 "Personal Team"(团队 ID 是 10 位字符)
  3. 团队 ID 记下来(后面 sed 改 bundle ID 时要用到)

查 Team ID 的快捷方式:

security find-certificate -a -p ~/Library/Keychains/login.keychain-db \
  | openssl x509 -noout -subject 2>/dev/null \
  | grep -o 'OU=[A-Z0-9]\{10\}' | head -1
# 输出:OU=NQC9WL9445  ← Team ID 是 NQC9WL9445
⚠️
Team ID 是证书的 OU 字段,不是 CN 括号里那串。容易混。
第 3 步

clone WebDriverAgent 仓库 + 改 bundle ID

cd ~
git clone https://github.com/appium/WebDriverAgent.git
cd WebDriverAgent

# 把 Facebook 默认 bundle ID 改成你自己的(用你名字的拼音/缩写)
sed -i '' 's/com.facebook.WebDriverAgentRunner/com.<你名>.WebDriverAgentRunner/g' \
  WebDriverAgent.xcodeproj/project.pbxproj

<你名> 替换成英文小写名字(例:com.kara.WebDriverAgentRunner)。Personal Team 不能用别人占过的 bundle ID,必须改

第 4 步

编译 WDA

cd ~/WebDriverAgent
xcodebuild build-for-testing \
  -project WebDriverAgent.xcodeproj \
  -scheme WebDriverAgentRunner \
  -destination 'generic/platform=iOS' \
  CODE_SIGNING_ALLOWED=NO

编译结果会在 ~/Library/Developer/Xcode/DerivedData/WebDriverAgent-* 下。

构建后 xctestrun 文件里的 bundle ID 也要改一次

sed -i '' 's/com.facebook.WebDriverAgentRunner/com.<你名>.WebDriverAgentRunner/g' \
  ~/Library/Developer/Xcode/DerivedData/WebDriverAgent-*/Build/Products/*.xctestrun
报 "iOS 26.4 Platform Support: not installed"?

新 iOS 上常见。不影响编译,只要你加了 CODE_SIGNING_ALLOWED=NOgeneric/platform=iOS 就能跳过 platform 检查继续。

第 5 步

把 WDA 安装到 iPhone

用数据线连上 iPhone(信任电脑),先取你的 UDID:

system_profiler SPUSBDataType | grep -A 4 "iPhone" | grep "Serial Number"

把 UDID 记下来(40 位字符),然后:

UDID=00008110-001A44421447801E   # 换成你的

# 找编译产物
APP=$(find ~/Library/Developer/Xcode/DerivedData/WebDriverAgent-* \
  -name "WebDriverAgentRunner-Runner.app" | head -1)

# 安装
xcrun devicectl device install app --device $UDID "$APP"
第 6 步

iPhone 上信任开发者证书

iPhone 第一次跑 WDA 会弹 "Untrusted Developer",必须手动信任:

  1. iPhone → 设置 → 通用 → VPN 与设备管理
  2. 找到 "开发者 App" 一栏 → 点你的 Apple ID
  3. "信任 com.<你名>.WebDriverAgentRunner" → 弹窗再次确认 → 信任
第 7 步

iPhone 自动锁定改 "永不"

iPhone → 设置 → 显示与亮度 → 自动锁定 → 永不

🔒
这一步不能跳。 Personal Team 没有解锁权限,屏幕一黑所有 WDA 命令会立即 timeout,发送任务直接挂掉。"永不"+ 把 iPhone 摆桌上是唯一可行方案。
第 8 步

装 pymobiledevice3

iOS 17+ 必须用 pymobiledevice3(旧的 tidevice 已经不能用了):

pip3 install --user 'pymobiledevice3>=9.12.0'
pymobiledevice3 --version  # 验证装好
第 9 步

clone Akke 仓库 + 装依赖

cd ~
git clone git@github.com:<Akke 仓库地址> Akke
cd Akke/worker
pip3 install -r requirements.txt
playwright install chromium  # 备用,目前 DM 不走 playwright 但其他工具会用
第 10 步

把 .env 放到 worker 目录

把现任 Owner 通过 1Password 给你的 worker .env 内容,保存到:

~/Akke/worker/.env

内容应该至少包含:

SUPABASE_URL=https://<xxx>.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJ...
FLY_WORKER_SECRET=<长字符串>
🔐
SUPABASE_SERVICE_ROLE_KEY 能绕过所有租户隔离访问全库数据。不要 commit、不要发群、不要截图分享。
🎉
环境搭建完成。下一节是日常开盘 SOP(每天上工跑一遍即可)。

5日常开盘 SOP(B 主线)

每天开始发 DM 之前跑下面 7 步,全程 5 分钟。

第 1 步

启动 RSD 隧道(需要 sudo)

开终端 1,跑:

sudo pymobiledevice3 remote tunneld -d

这条命令需要前台保持运行,不要关。让它一直跑。

第 2 步

取 RSD 隧道地址

新开终端 2

curl -s http://127.0.0.1:49151/ | python3 -c "
import sys, json
d = json.load(sys.stdin)
v = list(d.values())[0]
print(v['rsd_address'], v['rsd_port'])
"

会输出类似 fd68:295b:b075::1 55320(IPv6 地址 + 端口),抄下来

第 3 步

启动 WDA xctest runner

终端 2 继续跑(替换上一步抄的地址 + 你自己的 bundle ID):

pymobiledevice3 developer dvt xcuitest \
  --rsd fd68:295b:b075::1 55320 \
  com.<你名>.WebDriverAgentRunner.xctrunner

注意:bundle ID 末尾 .xctrunner 是固定后缀,不能省。这个终端也要保持前台。

第 4 步

转发端口 8100

新开终端 3

pymobiledevice3 usbmux forward 8100 8100

这条会把 iPhone 的 WDA 端口映射到 Mac 的 localhost:8100

第 5 步

验活

新开终端 4

curl http://localhost:8100/status

返回 JSON 含 "sessionId" 字段就 OK。如果 timeout 或 connection refused 跳第 6 节"故障排查"。

第 6 步

iPhone 端暖场

  1. 解锁 iPhone,确保屏幕亮(设置过"永不"那一步保持)
  2. 打开抖音 App
  3. 切到 "我" 标签 → 这一步是必须的,cold context(直接跳搜索/发现)会触发风控验证码
  4. 返回首页推荐流停留 30 秒(看几条视频,给账号一个"今天活了"的信号)
第 7 步

跑 dm_send_v3

终端 4

cd ~/Akke/worker
python3 dm_send_v3.py --max 5

--max 5本批最多发 5 条。新人头几次跑建议 --max 3 摸熟手感。

终端会打印每条候选的进度,类似:

[1/5] 候选: 榴莲 (sec_uid: MS4w...) intent=95
  → 暖场 OK
  → 跳转 profile OK
  → 点击私信 OK
  → 输入文案 OK
  → 发送 SENT ✓
  间隔 120s(随机 90-180s)
[2/5] ...
⏱️
每条 DM 大约 30 秒,加上 90-180s 随机间隔,跑完 5 条 ≈ 12-18 分钟。跑的过程中 iPhone 必须保持解锁、不能切到其他 App。可以离开桌子,但别动机器。

收工

跑完后回各个终端按 Ctrl+C:终端 1 (tunneld) → 终端 2 (xcuitest) → 终端 3 (forward)。或者一把杀干净:

sudo pkill -f "remote tunneld"
pkill -f xcuitest
pkill -f "usbmux forward"

6故障排查

下面 8 类是已知坑。按症状对照修法

1. curl localhost:8100/status timeout 或 connection refused

三步链有一环挂了。按顺序检查

  1. 终端 1 (tunneld) 还在跑吗?没在跑重启它
  2. 终端 2 (xcuitest) 还在跑吗?挂了重启
  3. 终端 3 (forward) 还在跑吗?挂了重启
  4. iPhone 的 USB 连接还在吗?拔了重插
2. 跑着跑着所有 WDA 命令都 timeout

多半是 iPhone 屏幕黑了。Personal Team 没有解锁权限,屏幕一锁所有 XCTest 命令会立即挂起。

修法:

3. 跑了 1 小时左右开始报 "connection was invalidated"

xcodebuild test runner 跑超过 ~1h 会被 testmanagerd 主动断连(与证书无关,是苹果内部超时)。

修法:单批 ≤ 8 条 DM,超过拆成多次跑,每次重启 xcuitest 终端。

4. 一条文案被切成 5-6 条独立 DM 发出去了

抖音 iOS App 的输入框(Draft.js)把每个换行符当 Enter(=立即发送)。如果 prompt 写出多段文案,send_keys 会触发风控且永久消耗对方配额。

修法:用最新的 dm_send_v3.py(已加 \n 折叠安全网)。不要回退到 v1 / v2 版本。

5. 控制台报 status_code=7173

对方关闭了陌生人私信。这是正常拦截,不是你的问题。脚本会自动 mark_failed,跳下一条。

6. 控制台报 status_code=22102 或 7911

账号触发风控(22102 是观察期,7911 是速率软封)。

修法:

7. iPhone 弹出滑块 / 旋转图片验证码

抖音偶尔抽查。脚本会等待,你手动滑一下完成验证,然后回到终端按回车继续。验证码本身不计风险分,正常通过即可。

8. 证书过期 / 7 天后 WDA 装不上

Personal Team 签名只有 7 天有效期。每周二(或者你自己定的时间)跑一次重签:

  1. 重做第 4 步 编译
  2. 重做第 5 步 安装
  3. iPhone 上重做第 6 步 信任证书

大约 5 分钟。

7红线 · 不要踩

🚫
下面五条是过去半年实战踩出来的硬规则,每一条都对应至少一次账号被风控的事故

8一页速查卡

📋 日常开盘 5 分钟 · 抄了就能跑

# 终端 1
sudo pymobiledevice3 remote tunneld -d

# 终端 2 — 取 RSD 地址
curl -s http://127.0.0.1:49151/ | python3 -c "import sys,json;d=json.load(sys.stdin);v=list(d.values())[0];print(v['rsd_address'],v['rsd_port'])"

# 终端 2 — 启 xctest(用上面输出的地址)
pymobiledevice3 developer dvt xcuitest \
  --rsd <ip> <port> com.<你名>.WebDriverAgentRunner.xctrunner

# 终端 3
pymobiledevice3 usbmux forward 8100 8100

# 终端 4 — 验活
curl http://localhost:8100/status

# iPhone:解锁 → 抖音 App → 切「我」 → 回首页停 30s

# 终端 4 — 发
cd ~/Akke/worker && python3 dm_send_v3.py --max 5

# 收工
sudo pkill -f "remote tunneld"; pkill -f xcuitest; pkill -f "usbmux forward"

🆘 错误码速查

7173对方关私信,正常拦截,跳下一条
7462同一对象已发过、对方未回复,配额用完
7911账号速率软封,停用 24h
22102账号观察期,停用 24-72h,换号
curl 8100 timeout三步链断了一环,按"故障排查 1"重启
所有命令 timeoutiPhone 屏幕黑了,立即解锁
connection invalidatedWDA 跑超 1h,单批 ≤ 8 条 + 重启