关于 building-workflows
这是一个通过 MCP 编写、测试、发布和监控 PostHog 工作流图的技能,强调遵循图结构规范,并要求在启用或发布前取得明确确认。
主要功能
- 01编写符合结构规范的工作流图
- 02创建草稿并逐步测试执行
- 03修改图结构和邮件内容
- 04审阅影响后发布暂存更改
- 05监控运行、日志和修订记录
适用场景
- 01构建并测试消息工作流
- 02修改线上工作流而不立即上线
- 03排查工作流步骤失败或跳过
MCP 相关
通过 PostHog MCP 工具创建、测试、编辑、发布、调度和监控工作流。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ posthog/ ai-plugin --skill building-workflows安装后在 Claude Code 中输入/building-workflows确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/graph-schema.mdlifecycle-and-debugging.mdonboarding.md详细介绍
构建工作流
PostHog 工作流是一个有向图:由 操作节点(actions)构成的列表,通过 边(edges)连接,并且恰好有一个用于启动每次运行的 trigger 节点。你需要将此图编写为 JSON,并通过 MCP 发送。始终将其称为“工作流”。“Hog flow”是内部代码名称(HogFlow),不是面向用户的术语。
最常见的失败原因是图 JSON 的结构有误。后端会将 actions/config 作为宽松的 JSON 存储,但可视化编辑器会按照严格的架构解析每个节点,因此格式错误的节点虽然能够保存,却会导致整个工作流的编辑器视图出错。在编写或编辑任何图之前,请先阅读 references/graph-schema.md。这是必须遵守的规范;不要只根据这些示例自行推断节点结构。
创建第一个消息工作流之前
当用户要求设置工作流或消息功能,或要求在可能尚未启用发送功能的项目中创建电子邮件、SMS 或推送工作流时,请先调用 workflows-setup-status,再编写任何内容。它会指出哪些设置步骤尚未完成,并提供应用中各步骤的链接。引导用户完成未完成的步骤,设置发送规则,然后再提供建议的工作流。请阅读 references/onboarding.md,了解流程和建议采用的默认设置。
对于仅向 Slack 发布消息或调用 Webhook 的自动化,可跳过此步骤:它们无需设置电子邮件。如果 workflows-setup-status 不可用,请直接进入后续生命周期。
生命周期
按以下阶段完成工作流。不要直接跳到启用步骤。
- 编排图。 按照 references/graph-schema.md 构建
actions+edges。对于任何function节点,不要猜测模板:使用cdp-function-templates-list列出当前目录,并使用cdp-function-templates-retrieve查看其必需输入。 - 创建为草稿。 使用
workflows-create。每个工作流创建时都是draft;此时不会执行。 - 测试运行。
workflows-test-run每次只运行一个步骤。从第一步开始(省略current_action_id,或将其指向触发器),并使用示例globals({event, person, groups}),其结构应与触发器的真实载荷一致:event触发器需要符合其筛选条件的事件;internal-event触发器需要名称列在其filters.events中的事件(对于 Slack 触发器,需要包含 Slack 属性包的$slack_message_received事件),且不需要 person(参见 references/graph-schema.md)。结果为status=skipped表示此载荷不会触发该触发器:如果载荷是你构造的,就修正它,使其符合触发器的条件;如果载荷来自真实的过往运行(workflows-get-invocation),则有问题的是触发器的筛选条件,而非载荷。结果中包含下一步的 ID(nextActionId)。将其作为current_action_id传回并再次运行,逐步执行直至结束。跳过delay节点,直接跳到其后的操作(不会模拟延迟)。除非设置mock_async_functions=false,否则异步副作用(HTTP/电子邮件/SMS/推送)会被模拟。阅读每一步的跟踪记录,确认执行路径。 - 迭代时查看日志。
workflows-logs会显示每一步的执行跟踪记录(级别从 DEBUG 到 ERROR)。通过这些记录可以了解某一步为何被跳过、发生分支或出错。 - 编辑后重新测试。 使用
workflows-patch-graph修补图(参见编辑草稿)。每次编辑都会使之前的测试失效——继续之前,请重新运行受影响的路径。对于草稿工作流,编辑会直接生效;对于已启用的工作流,编辑会暂存为草稿(参见更改运行中的工作流)。 - 启用(需要用户明确同意)。
workflows-enable会将其切换为active,此后,event/webhook/manual 触发器会在有符合条件的活动时触发。从那时起,工作流将在真实用户身上运行;每次变更都必须经过“草稿 → 测试 → 发布”流程才能生效——因此,请先完成测试,再取得用户明确同意后启用。不要擅自启用。 - 派发(仅限批次/定时工作流)。
batch或schedule工作流不会仅因启用而触发。使用workflows-run-batch发送一次性广播,或使用workflows-schedule-create设置周期性定时任务。batch触发器会向一组用户派发任务,因此为其设置定时任务时需要先通过workflows-blast-radius预览,并提供确认令牌;schedule触发器则在每次定时发生时运行一次,不针对用户群,因此可直接设置定时任务。使用workflows-get确认status=='active',并且其只读字段schedules中有一个处于启用状态的条目。 - 监控。 逐层深入查看:从
workflows-global-stats(哪些工作流运行失败)到workflows-stats(单个工作流的趋势),再到workflows-list-invocations(哪些用户遇到了失败),然后是workflows-get-invocation(触发载荷),最后查看workflows-logs(出错的步骤)。
完整工具目录按任务分类,见:references/lifecycle-and-debugging.md。
编辑草稿
打补丁,不要替换。 使用 workflows-patch-graph 编辑草稿:它接受一小组有序操作,这些操作通过 ID 定位(update_action、add_action、remove_action、add_edge、remove_edge、replace_action_edges)。update_action 会深度合并补丁,因此修改一封邮件的主题只需几行,而不是整个图。操作会在服务端以原子方式应用(读取、按顺序应用、验证,仅在有效时保存),响应会回显完整的更新后图,因此下次编辑前无需重新获取。这让每次往返的数据量都很小,无需重新传输每个操作和边。
workflows-update 仅用于更新图补丁无法表达的内容:顶层字段,例如 name、description、exit_condition、conversion、trigger_masking 和 variables。它会直接拒绝 actions/edges——部分列表会悄悄丢弃其中省略的每个步骤——因此所有图更改都必须通过 workflows-patch-graph 完成。
任何补丁应用后,都要重新测试你更改的路径(第 3 步)。补丁通过结构验证,并不代表路由方向正确。
邮件内容也遵循同样的规则。
function_email 步骤中的邮件应使用 workflows-patch-action-email 编辑:它采用与模板补丁相同的按 ID 定位的设计操作,另外还支持对主题、预标题、正文和收件人进行 email_patch 合并;HTML 会在服务端重新渲染,因此始终与设计一致。
编辑邮件内容时,优先使用它,而不是 workflows-patch-graph 的 update_action——通过 update_action 更改 design 会导致已存储的 html 过时。
应使用 workflows-patch-email-template 编辑库模板,而不是 workflows-update-email-template(后者会重新发送完整的设计 JSON)。
使用 designing-email-templates 技能编写和编辑邮件设计。
更改运行中的工作流
编辑活动工作流会暂存一份草稿,而不是更改正在运行的配置:发布之前,任何更改都不会影响真实用户。按以下流程操作:
- 编辑。 对活动工作流调用
workflows-patch-graph(或使用workflows-update修改内容字段)会将更改写入草稿——首次编辑会将实时图复制到草稿中,之后的编辑会在此基础上叠加。workflows-get会在draft中显示暂存的草稿;实时配置仍保存在actions/edges中。元数据(名称、描述)会立即应用到实时配置。 - 测试草稿。 使用
use_draft=true调用workflows-test-run,会执行暂存的草稿,而不是实时配置。更改了哪些路径,就重新测试哪些路径。 - 谨慎发布。 调用
workflows-publish时不带confirm,会返回in_flight_runs、confirm_token和impact摘要:对每个已删除步骤,说明大约有多少人停留在此处,以及他们会转到哪个保留步骤(moves_to)或退出;empty_variables列出可能在用户已越过新生产步骤、随后到达变量引用时显示为空的变量(这是结构性警告——即使所有进行中的用户都仍在生产步骤之前,也可能触发);schedule_conflicts列出覆盖草稿中已移除变量的计划。向用户展示影响摘要并取得其同意,然后再次调用,并设置confirm=true和对应的confirm_token。如果返回 409,表示预览后草稿已更改;如果返回 400,表示令牌已过期(15 分钟)——无论哪种情况,都应重新预览并再次确认。发布时会重新验证所有内容,因此无效草稿会被拒绝,实时配置不会受到影响。 - 或者放弃。
workflows-discard-draft会丢弃暂存的草稿。
进行中的运行会遵循实时配置:发布后,流程进行到一半的用户会从新版本中的当前步骤继续。已通过的步骤不会重新运行;停留在发布时被删除的步骤上的用户会跳到下一个保留步骤(若无后续步骤则退出),与影响预览中的报告完全一致。
时间安排的更改会逐步应用于停留中的运行,而不会立即生效。发布缩短后的延迟(或移动后的等待时段)会通过限流扫描重新安排停留在该处的运行。已接近预定唤醒时间的运行会保留原先较早的唤醒时间;只有扫描将唤醒时间提前的运行会受到影响,这些运行会分散安排,且唤醒时间不会早于发布后几分钟(也不会晚于原定时间)。发布后短时间内仍有运行停留在该处是正常情况——请向用户说明这一点,不要重新发布或将其视为失败。
回滚
每次更改实时内容,都会向工作流的修订历史追加一份快照。workflows-list-revisions 会列出各个版本(按时间从新到旧);workflows-get-revision 会返回某个版本的完整内容。要回滚(或向前恢复),workflows-restore-revision 会将该版本的内容复制到草稿中——不会触及实时配置——之后按正常发布流程操作:使用 use_draft=true 进行测试、预览并确认。预览会显示此次回滚对进行中用户的确切影响,与任何一次发布相同。
如果已有打开的草稿,恢复操作会返回 409;请发布或丢弃该草稿,或者传入 overwrite=true 将其替换。回滚无法撤销以下两件事:较新版本运行期间,已经移动或退出的运行会保持原位(其副作用已经发生);发布缩短延迟后,停留中的运行的唤醒时间可能已被提前——回滚不会再将这些时间推迟回去。
服务端负责管理的内容,切勿发送
服务端会编译并管理以下内容。手动编写这些内容是导致工作流损坏的最快方法:
- 任何过滤器、触发器、条件、转换或屏蔽规则中的
bytecode。由服务端根据人类可读的properties/hash编译。省略它;发送filters: {...},而不是 bytecode。 - 顶层的
trigger。根据actions中的trigger操作_派生_而来。只读。添加触发器节点来设置触发器,不要设置此字段。 billable_action_types、version、id、created_*。由系统计算或管理。
最简示例
事件触发,等待 1 天,发送邮件,然后退出。注意:恰好一个 trigger,每个非退出节点都有一条出边,且 edges 中引用的 id 保持一致;不会发送 bytecode。
{
"name": "Nudge after signup",
"description": "One day after signup, send a reminder.",
"exit_condition": "exit_only_at_end",
"actions": [
{
"id": "trigger_node",
"name": "Signed up",
"type": "trigger",
"config": {
"type": "event",
"filters": { "events": [{ "id": "user signed up", "name": "user signed up", "type": "events", "order": 0 }] }
}
},
{
"id": "delay_1",
"name": "Wait 1 day",
"type": "delay",
"config": { "delay_duration": "1d" }
},
{
"id": "email_1",
"name": "Reminder email",
"type": "function_email",
"config": {
"template_id": "template-email",
"template_uuid": "<uuid returned by workflows-create-email-template>",
"message_category_type": "marketing",
"inputs": {
"email": {
"value": {
"to": { "email": "{person.properties.email}", "name": "" },
"from": { "email": "[email protected]", "name": "Example" }
}
}
}
}
},
{
"id": "exit_node",
"name": "Exit",
"type": "exit",
"config": { "reason": "Done" }
}
],
"edges": [
{ "from": "trigger_node", "to": "delay_1", "type": "continue" },
{ "from": "delay_1", "to": "email_1", "type": "continue" },
{ "from": "email_1", "to": "exit_node", "type": "continue" }
]
}
邮件正文来自模板库,而非手写的 html:
- 优先复用。 使用
workflows-list-email-templates列出模板库,并选择合适的模板。滴灌营销活动通常会让每个邮件步骤都引用同一个基础模板(例如带品牌标识的公告模板)。 - 仅在没有合适模板时才创建。 使用
designing-email-templates技能,以设计为先创建新模板:编写design,省略html(服务端会根据设计生成 html)。 - 引用模板。 如上所示,将模板的 UUID 填入每个步骤的
config.template_uuid。保存时会将模板的主题、文本、html 和设计快照到步骤中。 - 分别定制每个步骤。 使用
workflows-patch-action-email设计操作进行修改——每个步骤的快照都会独立编辑,因此,使用一个基础模板的 5 个步骤可以分别拥有各自的内容。
快照是单向的:之后编辑模板库中的模板,不会更改已引用它的步骤;修改步骤也不会影响模板库中的模板。如果用户以为编辑模板会同步到工作流,请纠正这一点——步骤保留的是各自的副本,每个步骤都需要通过 workflows-patch-action-email 单独更新。
务必在模板中为设计提供真实的纯文本 text:屏蔽富内容的客户端只会显示 text,因此像“占位符”这样的填充文字会直接进入真实收件箱。
必须告知用户的硬性限制,不要试图绕过
- 不支持行为定向。 无法将“在过去 M 天内至少执行 N 次事件 X”表达为触发器或批次/计划受众。如果用户提出此类需求,应拒绝并说明原因;不要用有问题的过滤器近似实现。(后端会直接拒绝批次受众中的行为群组。)
- 批次受众针对的是_一个人是谁_,而不是他们做过什么。 仅支持个人属性和/或静态/基于属性的群组。批次受众中的事件/操作过滤器会被静默丢弃,因此必须拒绝此类配置。
- 优先重新评估受众。 对于批次,内联的个人属性条件或动态(基于过滤器的)群组会在用户符合条件时重新评估;静态群组是固定列表,仅在明确指定一组人时使用。