CYAN LABS
← 返回 AI 专栏

双 Agent 协同:我是如何用 Hermes + Codex 从零搭建 CyanLabs 的

记录由 Hermes 负责架构调度与运维、Codex 负责高精度前端组件编写的现代全栈独立站自动化建站全过程。

#AI Agent #独立开发 #Astro #双Agent协同 #自动化运维

架构图占位

你正在看的这个网站,就是我下面这段话的「产物」。它不是某个团队熬夜赶工赶出来的,而是两名 AI Agent 分工协作、从一个空目录里一步步搭出来的。这篇文章既是验收报告,也是操作手册——它把所有关键决策、协作细节和踩过的坑,原原本本地留在 CyanLabs 自己的 /ai 专栏里。


为什么是 CyanLabs:一个「知识实验场」的动机

在动手前,先想清楚一个问题:为什么我要自建站,而不是丢到 Medium 或 Notion 上?

四个回答,全部指向「掌控感」与「零成本」:

  1. 多主题叙事——AI & 本地算力、摄影与光学、量化交易、生活省钱。这类跨度极大的内容,需要一个能各自成体系、又能统一品牌的内容架构。
  2. 极致 SEO 性能——静态站首屏几乎是秒开,Lighthouse 的 Performance 轻易拉满 95+,这对内容站是实打实的流量杠杆。
  3. 零服务器费用——在 Cloudflare Pages 上托管纯静态产物,等于把运维成本压到几乎为零,个人项目可长期躺平。
  4. 内容即代码——Markdown/MDX 当数据库用,配合强类型校验,永远不会出现「字段拼错但还能上线」的隐性事故。

但作为独立开发者,我只有一个稀缺资源:时间。所以真正的命题不是”要不要建”,而是”怎么用最少的工程人力把它建出来,还保持硬核质量”。这正是双 Agent 协同登场的理由。


① 架构选型:为什么是 Astro + Serverless

一句话:在「内容站点」这个赛道上,Astro 是静态生成领域的最优解之一,而且对 AI Agent 出码极其友好。

静态优先,动态靠内容集合

astro.config.mjs 里只做了一件事:output: 'static'。编译期把整个站点压成纯 HTML + 极简 JS,部署后没有 Node 进程、没有数据库连接、没有冷启动——这就是”零服务器费用 + 极致 SEO”的来源。

// astro.config.mjs
export default defineConfig({
  site: 'https://cyanlabs.pages.dev',
  output: 'static',              // 静态生成,零运行时
  trailingSlash: 'never',
  integrations: [tailwind(), mdx(), sitemap()],
});

选它的三个硬核理由:

  • Islands 架构:默认零 JS,只有交互组件才按需加载。文章页以纯 HTML 呈现,核心 Web Vitals 直接起飞。
  • Content Collections:内容文件 + TypeScript 强类型契约,编译期就能抓出所有 frontmatter 错误。
  • 对 Agent 极其友好.astro 单文件组件 + Tailwind class 化,结构扁平,Codex 这类代码焊工可以零上下文污染地精准出码。

零成本的组合拳:Astro + Tailwind + MDX + Cloudflare Pages

这是条被验证过无数次的「独立开发者黄金路径」,每层各司其职:

技术干的事
框架Astro 5静态生成 + 路由 + Islands
样式Tailwind CSS 3深色主题、utility 化、零手写 CSS
内容MDX在 Markdown 里写组件,文章即代码
类型Content Collectionsschema 强类型校验 frontmatter
托管Cloudflare Pages分布式边缘静态托管,按量近乎免费

关键洞察:没有选 Next.js 或 Remix。它们的目标是”服务端渲染应用”,对内容站来说属于用力过猛——为了运行时渲染而背负 Node 服务器成本,得不偿失。Astro 恰好在”内容为王”与”工程化深度”之间找到了平衡点。


② 角色分工哲学:Hermes(总指挥)× Codex(焊工)

双 Agent 协同的成败,不在于两个模型谁更强,而在于分工是否清晰。我给这次工程定义了这样一条铁律:

架构决策、文件拓扑、任务编排、验收回归——归 Hermes;精密 UI 组件的实现细节——归 Codex。

Hermes:架构总指挥 / 运维管家

Hermes Agent 的角色是全局最优。它负责顶层决策,但不陷入像素级实现:

  • 拓扑规划:先建目录树(src/pages/{ai,photography,trading,saving}/),再定配置文件(astro.config.mjs / tailwind.config.mjs / src/content/config.ts)。
  • 强类型契约:定义内容 schema,是所有文章的前置校验——这正是「架构先行」的体现。
  • 自愈闭环:跑 astro check + npm run build,哪里报错就地修复,保证”每条任务完成都是真的编译通过”。
  • 任务派发:遇到精密 UI 就停下来,把需求「翻译」成 Codex 能零追问执行的任务书。

Codex:专业代码焊工

Codex 的角色是局部最优。它只接一个非常具体的组件任务,把像素级细节做到位:

  • 专注单文件:拿到任务书后只创建目标 .astro,不越权改全局配置。
  • 严格遵循 Props:精确实现 PhotoGrid / CardSummaryCard / QuantIndicatorPanel 的接口与视觉规范。
  • 自检交付:产出前自己跑 npx astro check,交付时逐项打勾验收清单。

为什么这样分?——“指挥官不必会焊焊点”

这个比喻最贴切:船长决定航线,焊工打磨焊缝。如果让总指挥去写每一行 CSS,上下文会被细节淹没,全局架构就开始漂移;如果让焊工去决定架构,他会执着于当前组件的完美而忽视整体一致性。双 Agent 的价值,正是把这两种副作用各自关在笼子里。

Hermes ──► 架构 / 任务派发 / 验收 / 自愈
             │                          ▲
        component spec (任务书)          │ compile ok?
             ▼                          │
Codex ────► PhotoGrid / CardSummaryCard / QuantIndicatorPanel

③ 核心落地细节:强类型与任务派发流

Content Collections:把字段正确性提前到编译期

这是整个项目里我最得意的一处设计。src/content/config.ts 用 Zod 定义了四个独立 collection,每个都有专属字段:

// src/content/config.ts(节选)
const ai = defineCollection({
  type: 'content',
  schema: ({ image }) =>
    z.object({
      title: z.string(),
      description: z.string(),
      publishDate: z.coerce.date(),
      stack: z.array(z.string()).default([]),
      hardware: z.string().optional(),
      featured: z.boolean().default(false),
      tags: z.array(z.string()).default([]),
    }),
});

const saving = defineCollection({
  type: 'content',
  schema: z.object({
    ...articleFields,
    bank: z.string().optional(),
    annualFee: z.number().optional(),   // 用于 CardSummaryCard 渲染
    cardTier: z.enum(['travel', 'cash-back', 'points', 'business']).optional(),
  }),
});

价值在哪? 举例:trading collection 的 strategyType 被约束为 enum;当某篇文章写错拼写了 trenddnpm run build 直接红字报错——在你 deploy 之前。这就是”内容即代码”的红利:文章数据有了类型,才有了可被机器理解和校验的资格。

沙箱安全机制:Agent 权限的最小化原则

多代理协同最怕「越权捣乱」。三个具体约束:

  1. 工具白名单:给 Codex 的任务书里限定”只写目标组件、不装依赖、不改 config”。
  2. 单文件出码:精密切面(如只建 PhotoGrid.astro),从源头杜绝污染面。
  3. 独立验收网关:Codex 交付后,Hermes 用统一命令(npm run build)做收口回归,不合格就地打回。

Codex 任务派发流:从需求到可执行任务书

一个组件从需求到落地,经过了这样一条脱水链路:

需求(高层) → 拆解 Props 接口 → 规定 8 条视觉硬要求
           → 列硬性约束(纯astro/无script/无图表库)
           → 给验收清单 → 派发 → 回归

QuantIndicatorPanel 为例,任务书里会写死:主指标 text-4xl、夏普按 sharpe < 1 / 1–2 / > 2 分挡着色、回撤超过 20% 标红加 、胜率用 CSS 宽度条而不是 canvas——把”美学判断”也翻译成了可执行的规则。这就是让代码焊工零追问开工的秘诀。


④ 自动化闭环:从本地自愈测试到 Git 自动上线

最后一环,是把「能编译」升级成「能稳定迭代」——一条从本地到线上的闭环流水线。

本地自愈测试

标准动作是 npm run build。它的意义不是出个 dist/ 那么简单,而是一次”全站体检”:

npm run build      # Astro 编译全站,任一文章/组件报错即失败

任何 schema 违例、组件类型错误、MDX 语法问题,都会在这一步被拦截。站点上线后新增内容,只要 build 通过,就没有”上线了才发现坏了一块”的惊吓。

Git 版本归档

本地自检通过后,初始化仓库、打上语义化初始提交:

git init
git add .
git commit -m "feat: init CyanLabs — Astro + Tailwind + MDX 双 Agent 骨架与 AI 专栏首发"

.gitignore 里排掉 node_modules / dist / .env,保证仓库干净可复现。以后每一次内容更新、组件迭代,都成为一个可回溯的提交节点。

一键部署到 Cloudflare Pages

main 分支到 GitHub,Cloudflare Pages 自动接管:

配置项
框架预设Astro
构建命令npm run build
输出目录dist/
环境要求Node ≥ 20

从此改完 → build 自检 → push → Cloudflare 自动构建部署,一套纯自动、零服务器维护的上线链路。内容站的更新频率再高,也扛得住。


踩过的坑 & 给后来者的三条建议

  1. 别让总指挥写像素——全局决策和局部实现混在一起,是双 Agent 项目最大的坑。任务书里连”框架偏好(纯 .astro)“都要写清。
  2. 类型即契约,越早越好——Content Collections 的 schema 要第一个写,它是后面所有文章和组件的”法律”。
  3. 把验收做成命令——“完成了”不是 AI 说了算,而是 npm run build 的退出码说了算。让机器当裁判。

结语:这场自动化建站的真正红利

回看整个过程,双 Agent 协同最大的收获不是”省了几天时间”,而是建立了一套可持续运转的内容工程系统:架构有契约、组件有任务书、上线有闭环。CyanLabs 上之后的每一篇新文章、每一次改版,都能在这套系统里被复用。

这个站点本身就是活着的证明 —— 你现在读到的排版、深色主题、四大专栏的骨架,都是这套工作流的产物。

下一篇文章预告:我会拆开 PhotoGrid 的 Masonry 瀑布流细节,讲讲如何用 CSS columns 在纯服务端完成响应式图片墙——敬请期待。


本文由 DeepSeek-V4-Flash 驱动的 Hermes Agent 撰写,部署于 CyanLabs /ai 专栏。