name: zzhub-publish description: 编排 zzhub-pipeline 状态机完成内容发布。当用户需要发布微信公众号文章或图文消息、创建草稿、或管理发布任务时使用。覆盖完整的 prepare→render→publish 流程。
zzhub-publish — 内容发布 Agent
zzhub-pipeline 状态机的编排层。CLI 通过 --view agent 输出告诉你要做什么,本 skill 覆盖具体怎么做,特别是需要 AI 判断的环节(写稿、审核、修订)。
前置信息
开始前先确认 workspace 路径。按优先级尝试:
- 问用户:"workspace 路径是什么?"
- 检查环境变量
ZZHUB_PIPELINE_WORKSPACE_ROOT - 执行
zzhub-pipeline config --key paths.workspaceRoot读取配置中的默认值
后续示例中用 {workspace} 表示 workspace 路径。
全局命令:zzhub-pipeline(或简写 zzp),安装后即可在任何目录执行。
核心循环
严格按以下顺序执行,不许跳过或打乱:
- 查找任务:
zzhub-pipeline find-run --workspace {workspace} --active --view agent - 检查状态:
zzhub-pipeline status --state {state_path} --view agent - 执行
next_action.action指定的动作(见下方各处理器) - 重复 直到
next_action.action为complete
如果 find-run 返回空,先创建任务(见下方"任务创建")。
动作处理器
从 status --view agent 输出中读取 next_action,按匹配的处理器执行:
cli 执行器
直接执行 ## Suggested Command 下的命令(已经是 zzhub-pipeline 格式),完成后重新 status。
适用动作:prepare、prepare-finalize、render、publish
worker 执行器 — attach-body(写稿)
任务需要正文内容。next_action.params 指明模式:
- worker_mode=write:从零写一篇新文章。任务中的
intent_text描述了用户想要的内容。 - worker_mode=write-from-materials:
source_materials_path有上游素材。先读完再写。 - worker_mode=research-then-write / research-then-write-from-materials:先调研再写稿。用网络搜索收集事实信息,然后动笔。
重要:当 params.spawn 为 true 时(绝大多数情况),主 Agent 禁止直接写稿。 主 Agent 的职责是构建写作 Brief,然后 spawn sub-agent 在干净上下文中完成写作:
主 Agent 根据
intent_text、worker_mode和用户原始需求构建写作 Brief,包含:- 文章主题、目标读者、字数要求
- 需要覆盖的核心要点和角度
- 语气和风格要求(见下方写稿质量要求)
- Markdown 格式规范(见下方)
- 标题要求:标题占整篇文章 60% 的权重,必须反复打磨。好标题的标准:有悬念、有冲突感、让人产生"这说的是什么?"的好奇心、读完标题就想点进来
- 标题关键词:产出标题的同时,从标题中挑选 1-2 个关键词(必须是标题中实际出现的词),用于生成文字封面图时高亮显示。选择标准:最有冲击力、最能概括文章核心、读者一眼就能被吸引的词。例如标题"那天晚上我用 AI 发了第一篇文章"中,关键词可选"AI"或"第一篇文章"
使用
Agent工具 spawn sub-agent(类型选择general-purpose),prompt 中只包含写作 Brief 和格式规范。不要把主对话中的无关上下文、CLI 输出、状态机细节带入 sub-agent。 Sub-agent 只需要知道"写什么"和"怎么写",不需要知道 zzhub-pipeline 的存在。Sub-agent 完成写作后返回正文。主 Agent 检查正文是否符合格式要求(有无
##标题、段落是否简短等),同时从正文末尾提取封面高亮关键词(去掉**封面高亮关键词**:标记后得到逗号分隔的关键词列表)。然后通过以下命令交稿:
zzhub-pipeline attach-body --state {state_path} --body-text "{正文内容(去掉关键词行的纯净正文)}"
如果正文很长,先写到临时文件,然后用 --body {file_path} 代替。
重要: 后续执行 prepare 时,必须把提取到的关键词通过 --highlight-words 传入,这样 render 生成文字封面图时才会高亮这些词:
zzhub-pipeline prepare --state {state_path} --highlight-words "关键词1,关键词2"
如果 sub-agent 没有输出关键词或关键词格式异常,prepare 时会自动从标题中提取(fallback 行为),但人工选的关键词通常效果更好。
写稿格式要求(必须在 sub-agent prompt 中明确给出):
- 使用
## 章节名二级标题划分章节(公众号正文不用#一级标题) - 使用
**粗体**强调关键词、关键数据、重点句 - 使用
-或1.组织列表和要点 - 使用
>引用重要内容或金句 - 段落简短,适合手机阅读(每段 2-4 句)
- 章节之间用空行分隔,适当使用分割线
写稿质量要求(必须在 sub-agent prompt 中明确给出):
- 标题占整篇文章 60% 的权重,花最多时间打磨标题。标题要有悬念、冲突感或陌生感,让人产生好奇心。避免平淡的陈述句,尝试用问题、对比、反常识或具体场景作为标题。
- 写作角度要有陌生感——把读者熟悉的事物用全新的视角呈现出来。比如讲一个工具不要列功能,而是讲"那天晚上我发了第一篇 AI 帮我排版的文章,封面是自动生成的"。
- 用讲故事的风格组织内容——有场景、有冲突、有转折、有解决。先描述一个痛点时刻,再引出工具如何改变这个局面,让读者产生"这说的就是我"的代入感。
- 有具体的细节和观点,避免空洞的套话。
- 有个人语气和风格,不要写得像教科书或官方通稿。
- 必须在正文末尾单独一行输出封面高亮关键词,格式为:
**封面高亮关键词**: 关键词1, 关键词2。这些关键词必须来自标题中实际出现的词,选 1-2 个最有冲击力的。
worker 执行器 — review-content(审核)
主 Agent 应 spawn sub-agent 进行独立审核,保持审核的客观性并避免主上下文污染。
主 Agent 构建审核 Brief:读取
source_body_path(或formatted_body_path,如果存在)的正文,连同以下审核标准一起交给 sub-agent。使用
Agent工具 spawn sub-agent(类型选择general-purpose),prompt 中只包含正文内容和审核标准,不包含主对话上下文。Sub-agent 返回审核结论(passed / needs_revision)和具体反馈。
审核标准(写入 sub-agent prompt):
- AI 味检测:是否读起来像 AI 生成?警惕:过于流畅的过渡句、空洞的总结、无意义的最高级形容词、公式化的结构、缺乏具体细节或个人声音。
- 标题质量(60% 权重):标题是否有悬念、冲突感或陌生感?是否让人产生好奇心?还是平淡的陈述句?好标题应该让人看完就想点进来。同时避免标题党。
- 陌生感与讲故事:文章是否用讲故事的方式展开?是否有场景、冲突、转折?是否把熟悉的事物用新鲜的角度呈现出来?还是平铺直叙地罗列功能?
- 事实准确性:文章中的说法、日期、人名、技术细节是否准确?标记任何看起来有问题的内容。
- 微信适配:格式是否适合微信阅读?段落是否简短?是否有微信无法渲染的 markdown?字数是否合适(文章 800-3000 字)?
- Markdown 结构:是否正确使用了
##标题划分章节?是否有**粗体**强调重点?列表和引用格式是否恰当?
主 Agent 根据 sub-agent 返回的结论执行:
- 通过 → 执行:
zzhub-pipeline review --state {state_path} --status passed - 需要修改 → 执行:
zzhub-pipeline review --state {state_path} --status needs_revision --feedback "具体修改建议..."
反馈必须具体可操作,用中文写,明确指出需要修改的具体段落。
worker 执行器 — revise-content(修订)
next_action.params.feedback 中包含修改意见。主 Agent 构建修订 Brief(原文 + 修改意见 + 格式要求),spawn sub-agent 在干净上下文中执行修订。
- 主 Agent 读取
source_body_path的正文,与feedback一起构建修订 Brief。 - 使用
Agent工具 spawn sub-agent(类型选择general-purpose),prompt 中只包含原文、修改意见、格式要求。 - Sub-agent 返回修改后的正文。主 Agent 检查修改是否覆盖了所有反馈点,然后交稿:
zzhub-pipeline attach-body --state {state_path} --body-text "{修改后的正文}"
交稿后重新 status。下一步通常会是 review-content(重新审核)。
await-input 执行器
任务需要用户输入(如图片素材)。required_inputs 列出了需要什么。向用户询问,然后把用户提供的值替换到 {images_json_path} 等占位符中,执行建议的命令。
适用动作:attach-body-images
repair 执行器
执行建议的 checkpoint 命令进行诊断,根据输出判断。如果任务已失败且无法恢复,告知用户并建议 reset --mode full。
适用动作:reset-or-repair、resolve-handoff
complete 执行器
向用户报告最终状态:标题、路由、发布结果(如有)。任务完成。
适用动作:complete
任务创建
当 find-run 返回空时,先创建任务。询问用户想发布什么内容,然后:
zzhub-pipeline init \
--workspace {workspace} \
--task-kind publish \
--content-form article \
--targets wechat \
--content-origin user \
--intent-text "{用户的中文需求描述}"
账号映射:
- "大号" / "早早集市" / "default" → 默认账号
- "小号" / "古一" / "ancientone" → 使用
--account ancientone
图文消息(图片合集)用 --content-form newspic --requires-render。
可选参数:
--existing-draft-media-id MEDIA_ID— 更新已有草稿而非新建--note-id NOTE_ID— 关联 Nezus note,发布成功后自动回调通知
init 执行后 CLI 会输出 state_path。将其传给 status --view agent 继续循环。
Handoff 入口(ingest-handoff)
当人类或外部系统已准备好 body 文件,通过 JSON 交接:
zzhub-pipeline ingest-handoff --file {handoff.json 的路径}
新建任务的 handoff JSON 必须包含 user_intent_text(用于路由解析):
{
"workflow_handoff": {
"mode": "new",
"content_form": "article",
"body_path": "/abs/path/body.md",
"target_account": "default",
"title": "文章标题",
"user_intent_text": "发公众号文章给大号,标题是..."
}
}
ingest 后 body 已自动挂载。运行 status --view agent 从 CLI 指示的位置继续——通常是 prepare(元数据完整时)或 review-content(review_policy 为 trust_user 时)。
错误恢复
CLI 命令失败时:
- 仔细阅读错误信息
- 大部分错误可修复:文件缺失、状态异常、Chrome 未安装
- 修复问题后重新执行同一命令
- 如果错误持续或含义不明,运行
zzhub-pipeline checkpoint --state {state_path}诊断 - 绝对不要直接修改
workflow-state.json
草稿箱管理
任务创建或发布前,可以用以下命令查看或删除微信草稿箱中的草稿:
# 列出最近 20 篇草稿(账号不传时使用 wx.defaultAccount 默认值)
zzhub-pipeline wx-drafts --limit 10
# 获取某篇草稿的完整内容(含 HTML)
zzhub-pipeline wx-drafts --media-id MEDIA_ID
# 删除一篇草稿
zzhub-pipeline wx-draft-delete --media-id MEDIA_ID
--account 参数可选,默认使用配置中的 wx.defaultAccount。指定账号:--account ancientone。
发布完成后,如果需要清理草稿箱(例如更新已有草稿后想删掉旧版本),用 wx-drafts 查到旧版 media_id,然后 wx-draft-delete 删除。
多账号/多平台发布
init 时指定多目标
# 多目标(逗号分隔 route@account 格式)
zzp init --workspace ws \
--targets "wechat-article@default,wechat-article@ancientone,blog@default" \
--task-kind publish --content-form article --content-origin user
# 无 @ 时使用 --account 值
zzp init --workspace ws --targets "wechat-article,blog" --account ancientone
单目标时 publish_targets 为空(向后兼容)。多目标时写入 publish_targets,publish 阶段一次性并行发布。
事后追加发布(republish)
任务完成后(mode=done),追加发布到其他账号/平台:
# 简写:同路由不同账号
zzp republish --state {state_path} --account ancientone
# 多目标
zzp republish --state {state_path} --targets "wechat-article@ancientone,blog@default"
# 混合
zzp republish --state {state_path} --account ancientone --targets "blog@default"
前置条件:
asset_path存在(产物已生成)content_review.status = passed
行为:
- 并行执行所有新 targets
- 幂等:已成功的 route+account 自动跳过
- mode 保持 done,结果追加到
publish.results[] - 有失败时返回错误详情