给 Agent 一句想法,或者一份已经整理好的材料,让它帮我写成博客,这是这套流程最初的目标。但文章写进 Markdown 后,还有封面、正文插图、组件排版、图片上传和页面检查。把这些环节留在对话里临时交代,每次写作都得重新说明一遍。

现在,我把它们收进项目内的 blog-writer skill。它负责串起写作过程,具体的生图和上传则交给已有工具。配置这套流程时,最有用的几个决定,是区分封面与正文插图的处理方式、给详细规则找到固定位置,以及把图片回填和页面预览也算进完成条件。

先把一篇文章走完

目前的主线是:整理材料,完成正文与排版,再处理正文插图和封面,最后检查生成的页面。

写作主线与正文插图、文章封面两条图片处理路径
写作主线与正文插图、文章封面两条图片处理路径

只有一个主题时,先把要回答的问题和提纲确定下来;材料比较完整时,就围绕主要论点重组,保留有用的事实、代码和出处。标题、描述和正文结构定稿后,配图才有可靠的依据。

这里还涉及一个很具体的细节:封面程序目前只读取文章的标题和描述,不读取整篇正文。所以描述需要准确概括内容,写得太空,封面也很难贴合主题。

文章字段沿用 scaffolds/post.md。标签优先选择站内已有的 tags,已有文章则保留 abbrlink,避免改写内容时连访问地址一起变了。草稿也可以走写作和正文配图流程,封面留到转成正式文章后再处理。

封面试过两条路,最后回到 API

封面原本就是通过程序调用 OpenAI API 生成的。后来,我也试过让程序调用 Codex,再配合封面 skill 完成生图。

对比之后,我更喜欢 API 生成的图片,而且这次使用里,Codex 生成封面的速度明显慢了很多。对于脚本里的单篇处理和批量补图,我还是希望沿用 API 这条路径。

因此,现在的默认规则很明确:封面统一由现有程序调用 API 生成。Agent 帮我写文章时,也使用这个入口。Codex 分支继续保留,需要时显式选择。

手动操作只要运行:

1
npm run cover

菜单里可以选择后端、生成预览,再上传回填;也可以直接执行一键流程。写作中的 Agent 使用对应的非交互入口,处理当前这篇文章。

封面批量处理的配置

API 后端默认生成并发为 4,通过 COVER_GENERATE_CONCURRENCY 调整。

Codex 后端默认每组处理 6 篇文章,共用一次临时会话,组间串行。COVER_CODEX_BATCH_SIZE 支持 1–30;6 是默认值,可以根据需要调整。同组已有有效缓存的文章会跳过生图。

批量流程先保存本轮生成结果,再进入上传阶段。上传成功的文章正常回填和清理,失败项保留缓存供重试。

正文插图先回答“这张图解释什么”

正文插图更依赖文章内容。我使用宝玉的 baoyu-article-illustrator 来分析结构、选择配图位置,并确定类型、风格和配色[1]宝玉 skills参考资料。

比如这篇文章要讲清两条图片处理路径,以及它们如何汇入上传、校验和回填过程,流程图就很合适。其他内容可能需要展示组成关系、对比方案,或者解释某个难以用文字讲清的过程。

我给正文配图设了至少一张的下限,具体数量仍要看文章中有多少值得单独解释的信息点。配图方案需要说明位置、作用和数量依据,这样才能判断每张图是否有必要。

生成前会保存大纲和完整提示词。默认先使用当前 Agent 的原生生图能力;不可用时,按项目偏好进入 baoyu-image-gen 的 API 备用分支。只有走到备用分支,才需要读取它的 skill 和配置。

这也保留了边写边安排插图的便利:先根据正文想清楚画什么,再把完整提示词交给工具。API 备用分支的默认画质是 normal,文字较多的流程图或架构图单独使用 2k;原生工具则使用当前环境提供的参数。

配图方案通常先确认。想直接采用推荐方案时,可以在请求中写明“直接生成,不用确认”。

把规则放回项目,入口保持简短

流程确定后,我把写作入口放在 .agents/skills/blog-writer/SKILL.md,详细规则放进五份参考资料:

1
2
3
4
5
6
7
8
.agents/skills/blog-writer/
├── SKILL.md
└── references/
├── writing.md
├── components.md
├── cover.md
├── illustrations.md
└── validation.md
参考资料主要解决的问题
writing.md材料怎么组织,文风和文章字段如何处理
components.md当前项目有哪些可用组件,应该怎样写
cover.md什么时候处理封面,调用哪个入口
illustrations.md正文配图怎样衔接宝玉 skill 和上传工具
validation.md完成前需要检查哪些内容与页面效果

这样划分,主要是为了让每项规则有明确的维护位置。文风集中在写作资料里,验证阶段引用它检查;模型和画质放在生图偏好中;上传、清理和重试的细节由工具文档维护。

读取也跟着任务走。只改正文,就先看写作资料;需要特殊排版,再看组件写法;进入正文配图时,再加载相应的 skill。详细参数留在实际使用的环节查阅,入口负责指明下一步去哪里。

排版沿用博客已有的能力

博客使用本地 Butterfly 主题和 hexo-butterfly-tag-plugins-plus。它们提供了提示块、标签页、折叠、题注和资料引用等能力,具体语法已经整理进项目参考资料。插件介绍中的示例也帮助我核对了这些组件的用途[2]Tag Plugins Plus 使用介绍参考资料。

我的选择原则是看内容需要:普通解释、步骤和对照关系,用 Markdown 就能表达;多个输入方式适合放进标签页;完整配置可以折叠;重要提醒用提示块;正文图片需要题注时使用 image 标签。

例如,本文把批量参数放在折叠块里,主线可以继续往下读,需要调整参数时再展开。文末的两种调用方式则放在标签页中,方便按手头的材料选择。

组件是否合适,最终还是要看页面。标签写对了,并不代表样式资源、窄屏布局和交互效果也都正常。

图片上传后,还要确认读到的是新图

封面与正文插图使用不同的生成路径,上传后的完成条件相同:CDN 返回的图片通过校验,文章中也已经回填对应链接。

这篇文章配图时,CDN 就曾在图片上传后短暂返回 404。工具按设定继续读取同一个地址,等到完整哈希一致后才回填。这个环节很有必要:OSS 上传成功,只能说明对象已经保存,还需要确认读者最终访问的地址能返回正确内容。

本地图片只作中转。封面保存在 .cover-cache/,正文插图的大纲、提示词、参考资料、原图和清单统一放在 .illustrations-cache/<abbrlink>/。OSS 对象按文章标识组织:

1
2
3
ding-BlogDemo/img/posts/covers/<abbrlink>.webp
ding-BlogDemo/img/posts/illustrations/<abbrlink>/01.webp
ding-BlogDemo/img/posts/illustrations/<abbrlink>/02.webp

封面直接用 abbrlink 命名,正文插图在文章目录下按编号保存。替换部分插图时保留原编号,链接再附上内容版本参数,便于区分同名图片的更新。

工具读取最终 CDN 地址,核对完整 SHA-256,通过后才回填 cover 或正文图片链接。回填成功,再删除对应的本地图片和中间文件。上传、校验或回填失败时,缓存会留下来供重试;正文插图的清理过程如果中断,也有完成记录支持继续处理。

这些恢复细节交给工具后,写作时就可以把注意力放在文章和图片本身。

最后回到页面上看一遍

正文和图片就绪后,我会先构建,再打开本地页面:

1
2
npm run build
npm run server

草稿对应使用 npm run build -- --draft 和 npm run server -- --draft。

这一步会检查文字与代码是否完整、图片是否清楚、题注和参考资料是否正确,还要实际切换标签页、展开折叠块,并检查窄屏布局。像引用提示这样的细节,只有看过页面,才容易发现它有没有影响正文阅读。

当前流程以本地验证完成为默认终点,线上发布和部署另行执行。写完后可以先预览,再决定什么时候发布。

现在怎么调用

日常写作从 blog-writer 这一个入口开始,根据手头材料说明想写什么:

1
2
3
用 $blog-writer 写一篇博客,介绍我这个项目的图片处理流程。
先根据仓库实现组织文章,完成排版、正文插图、封面和本地验证。
正文配图采用推荐方案,直接生成,不用确认。
1
2
3
4
5
6
7
用 $blog-writer 把下面的材料整理成本项目博客。
保留材料中的事实、代码和来源,按内容安排组件与正文插图。
完成封面、图片上传回填和本地验证。
正文配图采用推荐方案,直接生成,不用确认。

材料:
……

只想写提纲、先存草稿,或者暂时不配图,也可以直接说明范围。具体执行细节已经留在项目里,每次写作时,主要交代文章内容和这次要完成到哪一步就够了。

参考资料