Agent Skill 与网站生成
从“做一个 Agent”到“做一个 Skill”:一次网页生成项目的架构转向
复盘从独立 Agent 转向可复用 Skill 后,边界、批准 Gate 与交付质量的变化。
先说结论
我最初选择 Agent,是因为“从简历生成个人网站”看起来像一个需要长流程编排的任务:要解析文件、提取事实、等待确认、生成页面、重试失败步骤、保存版本,最后还要发布结果。
后来我把它做成了一个包含后端、前端、状态图、数据库和制品存储的系统。但在实际迭代中,最难解决的问题并不是流程能不能跑完,而是生成的网站为什么总有相似的骨架,以及为了支持这条流程需要维护多少运行时设施。
因此我把项目的核心交付物从“一个在线 Agent 应用”改成了“一个由宿主 Agent 执行的 Skill”。这个决定并不意味着 Agent 没有价值,而是把两个问题拆开:
宿主环境负责执行、文件、浏览器、命令和会话上下文
Skill 负责内容边界、设计判断、用户确认和质量验收
这更适合当前项目的阶段和目标。
一开始,为什么 Agent 看起来是正确答案
简历到网站不是一次性文本生成。它至少包含以下输入、转换和反馈:
简历 / JD / 作品材料
↓
文件解析与事实提取
↓
内容诊断与岗位匹配
↓
视觉方向与站点规划
↓
页面和 Section 生成
↓
浏览器预览与用户确认
↓
修复、重试、动效和发布
其中有几个特征很像 Agent 工作流:
- 输入材料可能不完整,需要追问;
- 用户可能拒绝某个阶段的结果,需要回到前一步;
- 多个 Section 可以并行生成;
- 失败的调用需要重试,但不能覆盖已经确认的版本;
- 每次生成都需要留下状态和制品记录。
原始方案因此采用了 FastAPI、React、LangGraph、数据库和对象存储。后端暴露运行 API,前端展示进度和确认 Gate,图负责节点之间的路由,持久化层保存运行状态和生成制品。
所以,Agent 方案解决的第一个问题是“复杂任务如何可靠地走完”。这一点没有错。
随着功能增加,原始 Agent 的边界逐渐清晰起来。它不只是调用模型,还需要承担一整套平台职责:
| 部分 | 需要解决的问题 |
|---|---|
| API 服务 | 接收简历、启动运行、恢复 Gate、返回预览 |
| 工作流图 | 管理节点、条件分支、中断和循环 |
| 状态持久化 | 保存每次运行的阶段、决策和 checkpoint |
| 制品存储 | 保存 PDF、结构化内容、HTML 和版本快照 |
| 前端工作台 | 展示进度、预览页面和用户确认入口 |
| 任务控制 | 并发生成 Section、限制并发、重试失败调用 |
| 发布链路 | 只发布完整且通过审查的页面 |
这类系统的价值在于可恢复性和可审计性,但代价也很明确:只要 Agent 需要跨请求保持状态,就不能只把它当成一个无状态的 HTTP 接口。
第一个真正的问题:页面为什么越来越像模板
平台运行起来后,我遇到的核心问题发生了变化:流程可以运行,不代表结果足够有个性。
早期生成链路为了稳定,采用了结构化内容模型和确定性渲染器。一个典型的 Section 生成过程是:
LLM 输出 JSON
↓
Pydantic / Schema 校验
↓
确定性 Renderer
↓
HTML + CSS
这个设计有明显优点:
- 不容易输出无法运行的 HTML;
- 可以统一处理链接、可访问性和响应式规则;
- 生成失败时可以使用确定性回退;
- 内容事实和页面结构更容易验证。
但它也把页面差异限制在了较小范围内。原始渲染系统按内容类型分发到固定的 HTML 结构,样式再通过 Design Token 和 Section Variant 进行变化。于是不同页面可能只是换了字体、颜色、圆角、阴影和少量排列方式,信息架构和 DOM 关系却没有改变。
可以把它抽象成:
固定内容类型
+ 固定 Section 结构
+ 有限 Variant
+ 设计 Token 替换
= 稳定但相似的页面
这不是说确定性渲染器本身错误。它提供的是质量下限,而不是多样性的全部来源。问题在于,我一度让“安全的渲染骨架”承担了“创造页面构图”的职责。
为什么增加更多 Variant 没有彻底解决问题
当页面相似时,最容易想到的办法是继续增加模板和 Variant。但这会遇到一个边界:
模板数量增加 ≠ 设计空间真正扩大
如果每个 Variant 仍然对应固定的 DOM、固定的信息顺序和固定的视觉角色,那么系统只是从更多模板中选择一个。它能减少重复,却不一定能产生真正不同的叙事结构。
真正影响页面个性的,通常还包括:
- 哪段内容是视觉主角;
- 哪些项目应该被放大,哪些应该收束;
- 页面阅读节奏如何从安静过渡到强调;
- 作品是纵向阅读、横向浏览还是分屏叙事;
- 动效是导航工具、内容解释还是纯装饰;
- 移动端如何重新组织而不是简单缩小桌面布局。
这些问题无法只靠换一组 CSS 变量解决。
第二个问题:审美判断不适合被拆成过多固定节点
我还观察到一个交互层面的矛盾。用户很少一开始就能准确填写完整设计参数,他们更可能在看到页面后说:
- 这个首屏太普通;
- 项目内容应该更突出;
- 这组颜色和我的方向不匹配;
- 动效可以更有节奏,但不要影响阅读;
- 移动端不要把桌面端的结构直接压扁。
这类反馈通常是在视觉对象出现之后才产生的。它们不是稳定的表单字段,而是基于上下文的判断。
如果每一次反馈都必须映射到一个新的后端节点、状态字段和 API 分支,工作流会变得越来越复杂。系统保存了很多状态,却不一定更懂用户真正想改什么。
这让我重新区分了两种“可结构化”的内容:
| 适合固定结构 | 更适合 Skill 指导下的判断 |
|---|---|
| 事实字段和证据 ID | 视觉主角是什么 |
| 文件格式和校验结果 | 页面应该形成什么节奏 |
| 版本号和快照路径 | 哪种构图最符合当前内容 |
| 构建命令和错误码 | 动效是否服务于叙事 |
前一类适合脚本和 Schema,后一类需要上下文、对话和视觉反馈。
第三个问题:运行成本和使用成本都在上升
前两个问题分别影响结果和交互,但还有一个更现实的约束:这套 Agent 平台对个人项目来说越来越重。
运行成本不只是服务器费用
为了让一个运行可以暂停、恢复、重试和发布,系统需要同时维护多种组件:
API 服务
+ 工作流运行时
+ 数据库 / checkpoint
+ 对象存储
+ 队列与并发控制
+ 日志、监控和鉴权
+ 模型调用费用
每个组件单独看都合理,但组合起来后,开发者需要处理的事情已经从“生成一个网站”变成了“运营一个小型 SaaS”。状态表要迁移,制品要清理,任务要观测,失败要重试,部署环境还要保证数据库、文件存储和服务版本彼此兼容。
对于高频、多用户、长时间运行的服务,这些投入可能是必要的;对于一个主要用来验证内容流程和视觉方法的个人工具,它们却会成为持续负担。
模型调用会被流程放大
复杂 Agent 往往不是一次模型调用就结束。解析、诊断、风格推荐、站点规划、Section 并发生成、失败重试、动效和审查都可能触发模型请求。
当一个阶段被拒绝后,系统可能需要重新生成该阶段及其下游产物。如果没有严格的缓存、幂等和增量更新,用户的一次修改意见可能会变成多轮重复调用。
这并不意味着 Agent 必然昂贵,而是说明:
节点越多、循环越多、自动重试越积极,潜在调用次数越多
因此,工作流的可靠性和模型使用成本之间存在真实的权衡。为了保证体验而保留自动重试,会增加调用预算;为了降低调用次数而减少重试,又可能把更多失败处理交给用户。
用户也要承担“流程成本”
平台成本之外,还有使用成本。用户需要理解:
- 当前处于哪个阶段;
- 这次确认会影响哪些下游结果;
- 拒绝后是局部重试还是整段回退;
- 哪些输入需要重新上传;
- 为什么浏览器预览、聊天反馈和发布按钮分布在不同位置。
当 Gate、状态和版本越来越多,系统虽然更可审计,却不一定更容易使用。用户面对的不是“帮我做一个网站”,而是一套需要学习的工作台。
这让我意识到,可靠性不能只看后端有没有保存状态,也要看用户是否能理解当前状态,以及完成一次网站制作需要付出多少额外操作。
为什么 Skill 能降低这部分负担
转向 Skill 后,宿主环境已经提供的能力可以直接复用:文件读取、命令执行、浏览器展示、会话上下文、版本控制和对话确认不需要在项目里重新实现一遍。
Skill 仍然会调用模型,也仍然可能需要浏览器和本地构建工具,因此它不是“零成本方案”。它降低的主要是三类成本:
| 成本 | 在线 Agent 平台 | Skill 方案 |
|---|---|---|
| 运行时维护 | 自己维护 API、状态和存储 | 交给宿主环境与工作区 |
| 使用入口 | 需要学习独立工作台和 Gate | 直接通过对话和现有工具执行 |
| 流程迭代 | 修改后端图、前端和数据库契约 | 修改 Skill 文档、脚本和资源 |
这是一种成本转移,而不是成本消失。需要规模化服务时,Skill 不能替代队列、鉴权和持久化;但在当前阶段,它避免了过早建设这些设施。
转向 Skill:改变的是交付边界
Skill 并不是把 Agent 变成一段更长的 Prompt。它是一种把专业工作方法打包成目录的方式:目录里可以有 SKILL.md、参考文档、脚本和资源,Agent 在任务匹配后按需加载它们。
这与原来的在线 Agent 平台有一个重要区别:Skill 本身不是一套必须持续运行的服务。它把执行交给宿主环境,自己负责在特定任务中提供判断框架、边界条件和可复用资料。
对我的项目而言,新的分工变成了:
简历事实与 JD 匹配 → Skill 内的内容工作流
结构、字体、配色和动效选择 → Skill 内的设计流程
浏览器展示与命令执行 → 宿主 Agent 的能力
网站源代码和构建验证 → 当前工作区与本地脚本
版本回退与发布 → Git / 工作区 / 用户确认
这不是放弃工程约束,而是把约束放到更合适的层级。
Skill 如何重新处理网页生成
转向 Skill 后,我没有保留“输入简历、直接吐出网页”的单步模式,而是把过程拆成内容和设计两条相互衔接的路径。
内容先建立事实边界
Skill 先读取简历和可选 JD,建立事实、证据和待确认问题。岗位匹配单独记录:
hard_requirementcore_capabilitybonus_signal
每个匹配结果还要说明:
- 支持它的 fact ID;
- 对应的 evidence ID;
- 简历位置;
- 匹配理由;
strong_match、partial_match、transferable或unmatched状态。
未匹配要求不能被自动补写成简历事实。这一步看起来与视觉无关,但它决定了网站到底在表达谁,以及应该把什么内容放到视觉中心。
设计再从多个方向开始
网站设计阶段不再只选择一个风格配方,而是依次讨论:
- 整体结构;
- 字体系统;
- 配色系统;
- 媒体处理;
- 主动效;
- 副动效。
每个类别都可以先让用户决定是否打开浏览器进行视觉比较,浏览器只负责展示,最终选择仍然由对话中的明确确认产生。
最后才进入一次性生成
完成设计确认后,Skill 先生成 TODO plan,再等待批准,随后根据用户选择使用当前会话单 Agent 或经过明确授权的多 Agent 并行。网站生成是一体化事务,之后通过构建、截图、视觉审查和局部修复完成交付。
因此,新的流程更接近:
事实确认
↓
设计选择
↓
浏览器视觉比较
↓
需求确认
↓
TODO plan 批准
↓
执行方式明确选择
↓
一次性生成网站
↓
截图审查与局部修复
Skill 解决了什么,没解决什么
针对前面三个问题,转向 Skill 后,项目获得了几个直接收益:
- 不需要为每次任务启动独立后端、数据库和对象存储;
- 设计方法可以随着对话和项目经验迭代;
- 浏览器、文件、命令和 Git 能力由宿主环境复用;
- 内容事实、JD 匹配和视觉选择可以放在同一条可读流程中;
- 设计资源可以按需加载,而不是全部固化在运行时服务里。
但它也有明确边界:
- Skill 不提供多租户、队列、计费和服务端监控;
- Skill 的视觉质量仍然依赖模型判断、用户反馈和截图验证;
- 如果需要长期运行、无人值守和大规模并发,独立 Agent 平台仍然更合适;
- 如果宿主环境缺少浏览器或命令执行能力,Skill 的某些阶段需要降级。
换句话说,Skill 降低的是平台建设和部署维护成本,不是所有计算成本,也不是所有产品化成本。
Agent 和 Skill 不是替代关系
现在回头看,最初的 Agent 方案依然有价值。它适合下面这类目标:
- 多用户在线服务;
- 长时间运行的工作流;
- 任务队列和并发控制;
- 统一的审计记录;
- 服务端自动重试和恢复;
- 固定 API 对外提供能力。
Skill 更适合下面这类目标:
- 在已有 Agent 宿主中复用专业流程;
- 用文档、脚本和参考资料沉淀方法;
- 让用户通过对话参与设计决策;
- 快速验证工作流和视觉方向;
- 避免为一个个人或小规模工具提前建设完整平台。
可以用一句话区分它们:
Agent 是运行时产品;Skill 是可加载的工作方法。
当项目从“验证方法”进入“服务化运营”,两者甚至可以重新组合:Skill 负责定义内容和设计策略,Agent Runtime 负责调度、权限、持久化和规模化执行。
总结
从 Agent 转向 Skill,表面上是从后端服务转向文件夹中的 SKILL.md 和资源目录,实质上是从“构建一个系统来控制所有步骤”,转向“沉淀一套方法,让宿主 Agent 在正确的时机做正确的判断”。
原始 Agent 方案让我看见了复杂任务的状态、恢复、并发和部署代价;Skill 方案则让我把注意力重新放回内容真实性、设计选择、浏览器反馈和最终网站质量。
这个决定并不适用于所有项目。需要稳定服务、规模化运行和强审计能力时,Agent 平台仍然值得建设。只是对于当前这个网页生成项目,先把设计方法和质量边界做成可复用 Skill,比先搭好一套长期运行基础设施更符合真实需求。