一步一步扒开问题,最后发现“做网站”这件事一股脑塞给一个 Agent 会爆。
Idea2Site 最后变成了一套 skills,这个形态是一路试出来的。
它更像是在反复遇到问题之后,一步一步被拆出来的。
如果用一句话概括这个演进过程,大概就是:
从“让 Agent 写网页”,变成“让 Agent 跑一条有质量门禁的建站流水线”。
1. 最朴素的方案:一个 Agent 直接做完整站
最开始最容易想到的方式就是一股脑全交给一个 Agent:
用户输入需求
↓
一个大 Agent 理解需求
↓
生成网站文件
↓
告诉用户完成
这套流程很直接,也很符合很多人对 AI 建站的想象。说实话,我一开始也觉得这条路可以先试一下。
但是一旦真的用起来,就会发现它很不稳定,而且这种不稳定会在几步之后一起爆出来。
比如用户说:
我想做一个个人博客,风格安静一点,适合写技术笔记,最好以后能发布。
一个大 Agent 需要同时决定:
- 什么叫安静?
- 是技术博客还是个人主页?
- 首页应该放什么?
- 是否需要关于页?
- 是否需要项目页?
- 文章页长什么样?
- CSS 怎么组织?
- 图片放在哪里?
- 路径直接打开是否稳定?
- 发布到哪里?
这里每一个问题单独看都不难,但组合在一起就很容易让模型变得短视。
它会先写一个漂亮首页,然后忘记文章详情页; 或者写了文章详情页,但是导航还是指向不存在的路径; 或者路径用 /assets/style.css,本地 HTTP 看起来没问题,但 GitHub Pages 子路径下直接坏; 或者生成一堆 demo 内容,最后没有任何地方记录哪些是 placeholder。
这时候我就意识到,核心问题在任务本身没有拆开。Agent 在一个超长 prompt 里同时管审美、结构、内容、路径和发布,最后一定会顾此失彼。
2. 第一轮拆分:把“建站”拆成几类任务
后来我把用户口中的“做一个博客”拆了一下,发现它其实至少包含五类任务。
第一类是 方向选择。
也就是在还没写代码之前,先回答:
这个站到底应该是什么气质?
它是研究主页、技术博客、作品集、数字花园,还是个人档案?
第二类是 视觉参考研究。
只有“安静”“技术感”“自然”这些词还不够。Agent 需要看到真实网站,提取可实现的布局、字体、颜色、内容密度和交互风格。
第三类是 静态网站生成。
这一步才是真正写 HTML/CSS/JS。它要决定页面结构、导航、文章模板、项目列表、移动端布局等,这里面也有一堆容易翻车的小细节。
第四类是 内容落地。
用户的 bio、项目、链接、文章、Obsidian 笔记、图片、公式都要进站,而且要进入正确的位置。
第五类是 质量检查与发布。
它要检查路径、乱码、占位符、隐私、断链、浏览器表现和部署设置。
所以如果把它画成一条流程,大概是这样:
Idea
↓
Theme Search
↓
Style References
↓
Static Build / Style Recreation
↓
Personalization
↓
Post Import
↓
Review
↓
Publish
这时候我觉得,最自然的做法就是把这些阶段拆成不同 skill。每个 skill 负责自己最清楚的一块,让 prompt 的负担降下来。
3. 第二轮拆分:不同 skill 负责不同类型的错误
拆 skill 的另一个原因是错误定位,这个在实际跑的时候非常明显。
如果最终网站不好看,问题可能出在:
- 主题方向本来就选错了;
- 参考网站找得太泛;
- 生成时没有抓住设计特征;
- CSS 实现能力不够;
- 用户内容太长但没有适配布局。
如果最终网站发布不了,问题可能出在:
- 路径用了 root-absolute;
- deploy root 选错;
- 发布目录里没有
index.html; - GitHub Pages 子路径没有考虑;
- 私密文件混进了 site 目录。
如果把所有逻辑放在一个 Agent 里,失败之后很难知道应该修哪里。
拆成 skill 之后,每个问题都能更自然地回到对应模块。这样线上效果差的时候,我们至少知道该从哪里开始查。
| 问题 | 对应 skill |
|---|---|
| 方向太泛 | search-blog-theme |
| 参考不够具体 | find-style-references |
| 原创站结构不完整 | make-personal-site |
| 复刻不像参考网站 | copy-website-style |
| 用户身份还是 placeholder | personalize-site |
| 文章没导进去或格式坏了 | add-blog-posts |
| 某个区域需要微调 | edit-site-part |
| 路径、乱码、隐私、断链 | review-static-site |
| 部署设置和平台选择 | publish-static-site |
这让整个系统变得更像一个工程流水线,少一点巨大 prompt 的玄学输出。
每一步都有自己的 success gate,避免依赖“模型觉得做完了”。这一点我觉得很重要,因为 Agent 最容易出现的情况就是“说完成了,但其实漏了一堆东西”。
4. 第三轮拆分:实现 skill 和编排 skill 分离
到这里其实还有一个问题:
用户通常并不知道自己该调用哪个 skill。
用户很少这样说:
请先调用 search-blog-theme,再调用 find-style-references,再调用 make-personal-site。
用户通常会说:
帮我做一个个人博客。
所以还需要一个编排层。
这就是 from-idea-to-personal-site 和 build-personal-site 的作用。
这两个 skill 看起来都像路由器,但职责不完全一样。
from-idea-to-personal-site 是用户面对的端到端入口。它负责从一个模糊 idea 一路走到本地 validated site,甚至继续走到发布。
它关注的是完整流程:
明确终点
选择方向
找参考
创建/复刻网站
个性化
导入文章
审查
发布或准备发布
最终交接
而 build-personal-site 更像一个低层协调器。当当前问题已经进入中途状态,重点变成“现在这个状态下一步该走哪个 skill”时,它负责做路由。
比如:
- 已有站点,替换个人信息;
- 已有站点,加文章;
- 已有站点,检查发布状态;
- 某一步失败,需要路由到最小负责模块修复。
所以这两个编排 skill 的关系大概是:
from-idea-to-personal-site:面向用户完整目标
build-personal-site:面向内部阶段路由
这个拆分很重要。
因为端到端 skill 需要关心“最终有没有交付”,而低层路由 skill 需要关心“当前这一步应该找谁”。
5. 整体架构
最后的架构可以分成五层。
5.1 方向发现层
负责把用户模糊审美变成可执行方向。
search-blog-theme
find-style-references
search-blog-theme 负责提出 3-5 个主题方向,比如极简笔记、研究主页、数字花园、个人操作系统、档案式博客等。
find-style-references 负责把选定方向落到真实参考网站上,提取设计 brief。
5.2 建站执行层
负责真正生成站点。
make-personal-site
copy-website-style
make-personal-site 处理原创静态站。
copy-website-style 处理“参考这个网站做一个气质接近的版本”。
两者共同点是都输出纯静态 HTML/CSS/JS,都强调页面相对路径、UTF-8、EDITING.md 和浏览器验证。
区别是:
make-personal-site:从方向生成原创站
copy-website-style:从具体参考站重建风格和交互
5.3 内容落地层
负责让网站变成用户自己的。
personalize-site
add-blog-posts
personalize-site 替换身份、bio、项目、链接、metadata、头像、demo 文案。
add-blog-posts 导入文章、Markdown、Obsidian、Word、旧 HTML、图片、公式、内部链接等。
一个负责“人是谁”,一个负责“写了什么”。
5.4 局部迭代与质量层
负责修细节和做门禁。
edit-site-part
review-static-site
edit-site-part 负责小范围修改,整站重做会回到建站层。
review-static-site 是硬 QA,检查路径、页面类型、编码、隐私、占位符、浏览器渲染、移动端等。
5.5 发布层
负责把已经验证过的静态站准备或发布出去。
publish-static-site
它会先确认:
- deploy root 是否正确;
index.html是否在顶层;- 是否跑过 review;
- 是否有隐私文件;
- 平台设置怎么填;
- 是否明确授权远程操作。
6. Contract 和 Gate 的作用
每个 skill 里都有一个非常关键的结构:
Inputs
Outputs
Boundaries
Success gate
If gate fails
我觉得这是整个项目里最工程化的一点。
Inputs 说明这个 skill 需要什么。
Outputs 说明它应该产出什么。
Boundaries 说明它的处理范围在哪里。
Success gate 说明什么叫做真的完成。
If gate fails 说明失败后应该怎么修。
这其实是在给 Agent 写工作协议。
比如 make-personal-site 的边界是原创静态建站;发布、大型文章迁移、高保真复刻会回到对应 skill。
如果用户要发文章,就应该交给 add-blog-posts。 如果用户要复刻某个网站,就应该交给 copy-website-style。 如果用户要部署,就应该交给 publish-static-site。
这样可以避免一个 skill 越做越大,最后变成什么都管但什么都不精。
7. 为什么一定要有 review-static-site
在这套架构里,review-static-site 是一个很核心的门禁。
因为网站生成只是中间结果,通过审查后才接近交付。
一个站点看起来没问题,不代表它真的能交付。至少要检查:
- HTML/CSS/JS/JSON/Markdown/SVG 是否 UTF-8 可读;
- 是否有 mojibake;
- HTML 是否有
<meta charset="utf-8">; href、src、srcset、CSSurl(...)是否指向存在的本地资源;- 是否误用了
/assets/...这类 root-absolute 本地路径; - 是否残留
TODO、placeholder、your name; - 是否有
.env、私钥、token、本机绝对路径; - 是否至少有预期页面类型;
- 是否有
EDITING.md。
这些检查很多都被固化到了 static_site_check.py 里。
这说明 Idea2Site 同时用 prompt 约束 Agent,并把一部分质量要求写成了确定性检查。
我觉得这是非常必要的。
因为 prompt 容易漏,脚本会稳定执行。
8. 最终的工作流
最后完整流程大概是这样:
用户输入
↓
from-idea-to-personal-site 判断终点
↓
search-blog-theme 选择方向
↓
find-style-references 找真实参考并生成 brief
↓
make-personal-site 或 copy-website-style 生成站点
↓
personalize-site 替换用户信息
↓
add-blog-posts 导入文章
↓
review-static-site 做质量门禁
↓
publish-static-site 准备或执行发布
当然实际运行时按需选择步骤。
如果用户已经有参考站,就跳过主题搜索; 如果用户只是要加文章,就直接走 add-blog-posts -> review-static-site; 如果用户只是改一个按钮,就走 edit-site-part; 如果用户只是问怎么发布,就先 review,再 publish。
这就是 skill suite 相比单个大 skill 的价值:
它会根据当前状态选择最短可靠路径。
9. 小结
这个项目的架构演进,其实就是从“生成”走向“交付”。
生成页面依赖模型写代码。
交付网站需要模型知道:
- 什么时候先研究方向;
- 什么时候该找真实参考;
- 什么时候该原创;
- 什么时候该复刻;
- 什么时候该导入内容;
- 什么时候做局部修改;
- 什么时候必须审查;
- 什么时候才可以发布。
把这些判断拆成 skill,再用 contract 和 gate 串起来,Idea2Site 才从一个普通的 AI 建站想法,变成一套可以长期维护的 Agent 工作流。
这也是我觉得这个项目值得整理成项目博客的原因。
它是一个关于 Agent 如何把模糊任务工程化 的例子。