Three TikTok Minis skills for Codex and Claude Code, with the cold-start playbook and five benchmark accounts through 88776-1 (2026-09-30). install.sh links them into ~/.codex/skills and ~/.claude/skills. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
147 lines
10 KiB
Markdown
147 lines
10 KiB
Markdown
---
|
||
name: swads-delivery-watch
|
||
description: 按广告(素材)盯一个 TikTok 小程序账户:每条广告 15 分钟一段的分段 ROAS(与演程账本曲线同一份数据)看赚钱素材是否在连续走低,外加点击率、当天 ROAS、上一小时亏不亏、计划日预算用量;每 10 分钟一轮,只经 swads MCP 网关读数与写平台(关单条广告/加预算/停计划),每次写平台前先征求运营意见。运营手动 /swads-delivery-watch 触发,不自动加载。
|
||
disable-model-invocation: true
|
||
---
|
||
|
||
# 盯盘 Delivery Watch
|
||
|
||
> 演程里每 10 分钟无人值守的那条车道只跑一条规则 `worst_ad`:消耗 ≥ 3 的广告里点击率与
|
||
> ROAS 综合排名最差、且两项都不高于中位数的那条,提议暂停,运营在 `/zh/executions` 签字后
|
||
> 才写平台。这个手动盯盘是另一套更细的判据(下表),按**广告**判,还看分段走势与预算用量。
|
||
> 两边判据不同,读数可能不一样,别拿一边去对另一边;**底层数据是同一份**(见下)。
|
||
|
||
一轮 = 读一个账户当天每条广告的数和 15 分钟分段,按五条规则判,把要说的说给运营,
|
||
写平台的事先问再动。每 10 分钟一轮,直到运营说停。
|
||
|
||
## 数据:和演程账本同一份
|
||
|
||
三样读数,全是指标同步(约 5 分钟一次)落下来的,演程账本读的也是它们:
|
||
|
||
| 读什么 | 工具 | 给什么 |
|
||
|---|---|---|
|
||
| 计划与预算 | `campaign_list` | 计划名、`external_campaign_id`、`operation_status`、`budget` |
|
||
| 每条广告今天的数 | `runtime_campaign_breakdown(external_campaign_ids=[…])` | 账本展开那一层:`groups[].ads[]` 的 `external_id`、`name`、`status`、`windows.today`(spend / impressions / clicks / native_d0_revenue) |
|
||
| 每条广告的分段 | `runtime_ad_intraday(external_campaign_ids=[…])` | 默认 15 分钟一段:`slices[]` 的 `local_start`、`spend`、`revenue`、`roas`、`cumulative_roas`、`open` |
|
||
|
||
分段就是演程账本广告行上那条曲线、弹窗里「15 分钟」那一档,同一张表、同一套切法
|
||
(`shared/contracts/ad-intraday-slices.json`)。**不要**自己存快照相减,也不要直读 TikTok 小时报表
|
||
来算 —— 那是另一份数,会和账本对不上。
|
||
|
||
读法的要点:
|
||
|
||
- 两个带 `external_campaign_ids` 的工具都是**一次传全部**在投计划(同一账户最多 100 个),别按计划逐个调。
|
||
- 分段 `open=true` 是还没走完的那一段,数还会长,**不参与判趋势**。
|
||
- D0 收入回传有延迟:最近一两段的 ROAS 通常偏低、之后会补上。所以趋势只看已走完的段,
|
||
且要"连续"才算,不因一段低就喊。
|
||
- 分段收入只有小程序账户有;App 账户 `roas` 为空 —— 这时说一句"该账户没有分段收入",
|
||
只判按天的规则。
|
||
- 两轮之间 `latest_reading_at` 没变,就说"同步还没来",别当成 0 消耗。
|
||
|
||
## 先问运营两件事,别猜
|
||
|
||
1. **账户**(`external_account_id`)。说不清就 `intake_list_accounts` 列给他选。
|
||
2. **阈值要不要改**。默认值见下表;运营没说的按默认。分段默认 15 分钟,运营要更细可改 5。
|
||
|
||
| 规则 | 默认判据 | 对象 |
|
||
|---|---|---|
|
||
| 赚钱素材在走低 | 今日累计 ROAS > 1,且最近 **3 段已走完**的分段 ROAS 逐段下降,最后一段 < 1 | 每条广告 |
|
||
| 素材上一小时亏钱 | 上一个整点小时(4 段 15 分钟相加)消耗 ≥ 10 USD 且这一小时 ROAS < 1 | 每条广告 |
|
||
| 素材 ROAS 亏 | 当天消耗 ≥ 10 USD 且当天 ROAS < 1 | 每条广告 |
|
||
| 素材点击率低 | 当天消耗 ≥ 10 USD 且 CTR < 18% | 每条广告 |
|
||
| 预算快用完 | 计划当天 ROAS > 1 且消耗到日预算 80%、95% | 每条计划(预算在计划上) |
|
||
|
||
第一条最要紧:素材有衰减曲线,当天 ROAS 被上午的好时段撑着,最近在亏的那段会一点点把之前
|
||
赚的吐回去,按天、按小时的口径都要等吐得差不多了才会报警。连续下降一旦出现就建议关停。
|
||
报这条时同时给**利润垫**(今天 D0 收入 − 消耗)和按最近一段的亏速还能撑多久。
|
||
|
||
ROAS 一律指 D0 收入(小程序内购 + 广告变现)/ 消耗,就是账本 D0 ROAS 与策源出价的口径。
|
||
只盯 `SW-ADS-` 开头的计划下的广告:客户自己在后台建的计划,不报也不动。
|
||
已暂停的广告(`status` 为 `AD_STATUS_DISABLE` 等)不看:报表里暂停前的行还在,不能当在投。
|
||
|
||
## 每一轮的顺序
|
||
|
||
1. **计划清单** `campaign_list(external_account_id=A, page_size=100)`:拿每条计划的
|
||
`campaign_id`、`external_campaign_id`、`campaign_name`、`operation_status`、`budget`。
|
||
`operation_status != ENABLE` 或名字不以 `SW-ADS-` 开头的,它下面的广告都跳过。
|
||
第一轮前 `account_sync` 一次,让计划与广告状态是新的;之后不必每轮同步。
|
||
2. **每条广告今天的数** `runtime_campaign_breakdown(external_account_id=A, external_campaign_ids=[第 1 步
|
||
留下的计划])`:返回 `campaigns{计划id: {groups[].ads[]}}`,每条广告的 `external_id`、`name`、`status`、
|
||
`windows.today`。CTR = clicks / impressions,ROAS = native_d0_revenue / spend;
|
||
计划当天 = 同计划广告相加后再相除,对照第 1 步的 `budget`。
|
||
3. **每条广告的分段** `runtime_ad_intraday(external_account_id=A, external_campaign_ids=[同上])`
|
||
(默认 `slice_minutes=15`、最近 8 段;看上一小时要至少 5 段,可传 `last_slices=8` 以上):
|
||
`ads[]` 按 `external_ad_id` 对上第 2 步的 `external_id`;`today_spend` / `today_revenue_d0` /
|
||
`today_roas` 是今天到最新一次读数的累计。
|
||
- 走低:去掉 `open=true` 的段,看最后 3 段 `roas` 是否逐段变小且最后一段 < 1,同时 `today_roas` > 1。
|
||
- 上一小时:`local_start` 落在"当前小时 − 1"(账户时区)的 4 段,spend、revenue 各自相加再相除;
|
||
这 4 段有一段还是 `open` 就这一小时不判。
|
||
4. **判定**,按上表。
|
||
5. **汇报**(见下)。写平台的建议附在对应那行后面,等运营答复。
|
||
6. 第一轮报完,用 `/loop 10m <这一轮的描述>` 排每 10 分钟一轮(Claude Code 会拦掉前台
|
||
`sleep 600`)。不要后台 sleep、不要 Monitor:无人值守的会话里后台任务的通知回不来。
|
||
|
||
兜底:`runtime_ad_intraday` 报错或整户没有分段(刚上线、App 账户)时,这一轮只判按天的三条
|
||
(点击率、ROAS 亏、预算),说明分段缺了;真要按小时看再用 `runtime_hourly_metrics(level="ad")`
|
||
(直读 TikTok,和账本不是同一份数,报的时候注明)。
|
||
|
||
Smart+ 计划里,TikTok 后台和建广告时回的是另一个号(`smart_plus_ad_id`,如 `…838545842`),
|
||
账本与分段里的 `external_id` / `external_ad_id` 是它下面的投放广告号(如 `…841350417`),两个都是同一条
|
||
`Ad N`;运营拿后台号问时,用 `campaign_detail` 里 `tiktok_ad_refs` 的顺序(`ad-…-N`)对上 `Ad N`。
|
||
后台号要取**最早那次** `execution_runs`(建计划那次)的 `tiktok_ad_refs`:之后的推送(追加广告)
|
||
会把 `ad-…-N` 改写成报表号。追加的广告(`ad-<hex>`)没有数就是还没花钱。
|
||
|
||
## 不重复报
|
||
|
||
同一对象、同一规则、同一"次"只报一次:
|
||
|
||
- 赚钱素材走低:按(广告, 最后一段的 `local_start`)记;下一段又创新低再报,回到 1 以上后再跌再报。
|
||
- 素材小时亏钱:按(广告, 日期, 小时)记;每个新的整点小时重新判。
|
||
- 预算 80% / 95%:按计划各报一次;预算被改过(数值变了)重新记。
|
||
- 点击率低 / ROAS 亏(按天):按广告首次报;之后只在数值恶化一档(消耗又翻倍、或 ROAS 再跌 0.1)时再报,
|
||
回到线上又跌回来再报一次。
|
||
|
||
会话里维护一张"已报清单",每轮先查再说。
|
||
|
||
## 写平台:先问,再动,动完读回
|
||
|
||
规则都只产生**建议**,默认建议是关那条广告,不是停整条计划 —— 除非同一计划下在花钱的广告全都亏。
|
||
运营一句"关"、"停"、"加到 N"才动。动作对应的工具:
|
||
|
||
| 运营说 | 调用 | 之后 |
|
||
|---|---|---|
|
||
| 关这条广告(素材) | `campaign_set_ad_delivery(campaign_id, external_ad_id, status="stopped", external_account_id=A)` | 响应里 `remote_status`;`external_ad_id` 就是账本/分段里的广告号 |
|
||
| 停这条计划 / 打开 | `campaign_set_delivery(campaign_id, status="stopped"/"active", external_account_id=A)` | `campaign_detail` 读回 `operation_status` |
|
||
| 预算加到 N | `campaign_set_budget(campaign_id, daily_budget=N, external_account_id=A)` | 响应 `changed`、`previous_daily_budget`;工具已把新预算写回本地账本,**不用** `account_sync` |
|
||
|
||
- `campaign_id` 是 SW Ads 的(`campaign-…`),由 `external_campaign_id` 在第 1 步清单里查。
|
||
- 一次只动运营点名的那些,不"顺手"多关一条。
|
||
- 运营说"亏的都关"这类批量话,先把要关的清单(广告名 + id + 数)列出来让他看一眼,他说"好"再逐条调。
|
||
- 加预算是花钱更快的那一步,无论运营之前怎么说,每次都单独确认金额。
|
||
- 工具报错(409 not linked / 404 ad not found / TikTok refused)原文抄给运营,不重试绕过。
|
||
|
||
## 汇报格式
|
||
|
||
每轮只报有变化的;一行一条,先说结论再给数。广告写成"剧名 Ad N(后台 ad id)":
|
||
运营在 TikTok 后台看到、拿来问的是 `smart_plus_ad_id`,账本里的投放广告号运营对不上。
|
||
每条要报的广告先按计划 `campaign_detail` 取一次 `tiktok_ad_refs`(`ad-…-N` → `ad_id`),
|
||
会话里缓存,报后台号;写平台仍传账本里的广告号(网关自己换号)。
|
||
|
||
```
|
||
赚钱素材在走低 Dead at Ten Ad 4(1877280689574033):15 分钟分段 1.21 → 0.98 → 0.64;今天 58.20 / ROAS 1.09,利润垫 +5.2,按最近一段亏速约 40 分钟吐完 → 建议关这条广告,等你确认
|
||
16 点这一小时亏钱 Solar Collapse Ad 4(1877280689574033):消耗 12.40 回收 9.10 ROAS 0.73;今天 58.20 / 1.12 → 建议关这条广告
|
||
素材 ROAS 亏 My Husband Wants Me Dead Ad 4(1877280841350417):今天消耗 14.30 ROAS 0.62 → 建议关这条广告
|
||
素材点击率低 Covenant Of Shadows Ad 6(1877280990677473):今天消耗 11.02 CTR 1.1% → 建议关这条广告
|
||
预算快用完 Solar Collapse(1877280665755921):今天 412/500(82%) ROAS 1.31 → 要不要加?
|
||
数据截至 16:05(账户时区,最近一次同步);最近一两段的回收可能还没回传全。
|
||
```
|
||
|
||
什么都没触发就说"一轮无异常,数据截至 HH:MM",别列全表。运营问"现在什么情况"再按计划分组给全表
|
||
(每条广告:今天消耗 / CTR / ROAS / 最近 4 段分段 ROAS)。
|
||
|
||
## 边界
|
||
|
||
- 只用 MCP 工具:不读服务源码、不改仓库、不 SSH、不碰凭据。工具缺能力就写进汇报,交给运营。
|
||
- 不擅自改阈值、不擅自"优化"出价与国家。
|
||
- 同一时间只盯运营点名的账户;别顺带查别的户。
|