1. 为什么 Vibe Coding 需要一套“骨架”而不是一句提示词
DeepSeek Harness 开源之后,很多人第一反应是去看它的 Agent Runtime 怎么实现,但我更关注的是它把内部工程 SOP 一起放出来了。这件事的意义在于:Vibe Coding 如果只是“让模型自由发挥写代码”,那它顶多是个高级补全工具;只有当仓库里存在规则、知识、协议、决策记录和质量门禁这五类资产时,Coding Agent 才可能承担持续交付。
我试过把需求直接丢给 Agent 让它“看看相关代码然后改”,结果通常是它打开名字最像的文件,改完跑一下局部测试就宣布完成。问题不在模型能力,而在于仓库没有告诉它:谁拥有这项行为、当前系统怎么装配、哪些动作属于高风险、什么证据才算验证通过。DeepSeek Harness 的做法是把这些约束拆成不同职责的仓库资产,每个资产把 Agent 导向下一步,而不是指望它记住一整本规范。
这篇文章面向想用 Coding Agent 做持续交付的团队,给出一套可复现的骨架:AGENTS.md 怎么写、质量门禁怎么配、TaoToken 统一 Key/API 通道怎么接入,最后附上本地跑通和门禁触发的验证动作。你可以把它当成一个最小可用的起点,再按自己团队的事实往里填。
2. TaoToken 前置:统一 Key 与 API 通道
在搭骨架之前,先把模型调用通道固定下来。Coding Agent 的流水线里,模型请求会散落在多个环节:Agent 主循环、代码审查 Skill、文档同步检查、甚至门禁失败后的自动修复。如果每个环节各自配一套 Key 和 Base URL,后面排查问题会非常痛苦。
TaoToken 在这里的角色是提供一个统一的 API 通道,让 Agent 骨架里的所有模型调用走同一个入口。官网地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api (这个不加 UTM)。
你需要先拿到 API Key。进入控制台创建:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,然后在 API Keys 页面生成密钥:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。生成后建议直接写进环境变量,不要硬编码进仓库。
export TAOTOKEN_API_KEY="sk-你的密钥" export TAOTOKEN_BASE_URL="https://taotoken.net/api"如果你用的是 Claude Code 这类工具,接入文档里有对应的配置方式:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。Claude Code 专用说明在 https://taotoken.net/ClaudeCodeAnthropic?utm_source=taotoken_aicg_blog_end&utm_content=ClaudeCodeAnthropic&utm_campaign=rewrite 。
注意:Key 只放在环境变量或本地密钥管理里,不要提交到 Git。门禁脚本里如果需要读取,用
process.env.TAOTOKEN_API_KEY,并在 CI 里配置为 secret。
通道固定之后,Agent 骨架里的模型调用就可以统一走一个封装,后面换模型或调参数只改一处。
3. 可复制配置:AGENTS.md 骨架与质量门禁
这一节是全文的核心。我把它拆成三块:根 AGENTS.md、目录级 AGENTS.md、以及质量门禁脚本。
3.1 根 AGENTS.md:任务分发器而不是项目简介
根 AGENTS.md 的第一段不应该写“本项目是做什么的”,而应该写“你不能违反什么,以及下一步去哪里”。下面是一个可以直接改的骨架:
# AGENTS.md ## 系统定位 本项目基于 <你的框架>,核心原则是 <一句话不变量,例如:一切能力都是插件>。 修改 `packages/` 前必须阅读 `docs/architecture.md`。 文档修改遵从 `docs/AGENTS.md`。 ## 仓库布局 - `core/`:Session、Prompt、Tool、Agent、Loop 的产品主干 - `llm/`、`shell/`、`fs/`、`subagent/`:各自拥有独立能力 - `.agents/`:工作流与决策记录 - `scripts/`:门禁与生成器 - `examples/`:可运行组合,不是可复用实现 ## 全局不变量 - 项目处于预发布阶段:优先正确的基础结构,而不是兼容旧格式的补丁 - 可以重命名和重组,但必须同步更新引用 - 旧磁盘格式可以直接拒绝,不写 deprecated alias 和双格式解析 ## 命令与密钥边界 - 模型调用统一走 `TAOTOKEN_BASE_URL`,Key 从 `TAOTOKEN_API_KEY` 读取 - 禁止在源码、测试、文档中硬编码任何密钥 ## 下一步路由 - 生命周期、并发、子进程、teardown 规则:先读 `docs/defensive-patterns.md` - 推送前检查:匹配 `.agents/skills/dsh-pre-push-checks` - 非平凡决策:在 `.agents/notes/` 新增或更新记录这段骨架的关键在于“路由”而不是“罗列”。每条规则都很短,但指向更具体的拥有者。根文件保持在每个会话都值得加载的体积,细节下沉到目录规则和 Skill。
3.2 目录级 AGENTS.md:约束随作用域收缩
进入packages/后,规则应该变得更具体。下面是一个 Package 级骨架:
# packages/AGENTS.md ## 本目录所有权 本目录下的每个 Package 拥有自己的行为、测试入口和失败模式。 修改前先确认行为归属,不要跨 Package 直接改别人的内部实现。 ## 高风险约束 - 产品可见插件必须有真实组合测试,手工 `ctx.plugin(...)` 的 unit test 不足以证明装配正确 - Service Definition 要服务所有 Consumer,不能让单个 UI 或 Tool 的需求污染公共 Service - 一个异步操作由一个生命周期控制器拥有,分散的 ready/cancel/dispose 状态必须收拢 - 权限、配置、公开操作的限制必须在真正执行操作的位置实施,不能只在 UI 或 Prompt 中隐藏入口 ## 测试入口 - Package 行为:owning Vitest 文件或聚焦测试 - 构建配置或发布路径:build、hygiene、built-artifact smoke这几条分别阻止了几种典型错误:只在局部 mock 中验证、把最近调用方的需求升格为公共抽象、为“看起来完整”新增状态机、把访问控制做成可绕过的展示逻辑。
3.3 质量门禁:把文字要求变成非零退出
Coding Agent 对可执行 Gate 的遵守程度,远高于对纯文字要求的遵守程度。所以门禁的核心不是“请遵守规范”,而是“违反时命令必须返回非零”。下面是一个scripts/run-gates.ts的简化骨架:
type Gate = { id: string; command: string; dependsOn?: string[]; allowFailure?: boolean; }; const gates: Gate[] = [ { id: "ci-static", command: "pnpm run lint && pnpm run typecheck" }, { id: "ci-coverage", command: "pnpm run test -- --coverage", dependsOn: ["ci-static"] }, { id: "ci-snapshot", command: "pnpm run test:snapshot", dependsOn: ["ci-static"] }, { id: "ci-artifacts", command: "pnpm run build && pnpm run smoke", dependsOn: ["ci-static"] }, { id: "doc-sync", command: "pnpm run doc-sync", dependsOn: ["ci-static"] }, ]; async function runGate(gate: Gate): Promise<boolean> { const result = await exec(gate.command); if (result.code !== 0 && !gate.allowFailure) { console.error(`[gate:${gate.id}] failed`); return false; } return true; }配套的lefthook.yml保持克制,pre-commit 只做 staged lint、空白检查、归档 Note 校验;pre-push 只跑增量 typecheck。完整测试、coverage、snapshot、build 交给 CI,避免 Agent 被慢反馈拖垮。
pre-commit: commands: lint-staged: run: pnpm exec lint-staged whitespace: run: pnpm run check:whitespace pre-push: commands: typecheck: run: pnpm run typecheck:incremental3.4 决策记忆:Agent Note 的最小格式
非平凡变更需要在同一个 PR 里新增或更新至少一个 Agent Note。路径编码生命周期和类别:
.agents/notes/{lifecycle}/{class}/yyyy-mm-dd-topic-title.mdproposed/保存待评审方案,implemented/保存已落地决策,rejected/保存被否决但仍有提醒价值的方案,archived/保存冻结历史。已实现记录的正文结构建议固定为:
## Problem ## Decision ## Alternatives considered ## Consequences其中Alternatives considered必须存在。它让未来 Agent 知道某个看起来合理的方案曾经被讨论过、因何失败,避免下一次会话重新发明旧方案。
4. 验证请求:本地跑通与门禁触发
配置写完之后,必须验证两件事:模型通道能通,门禁能真的失败。
4.1 验证 TaoToken 通道
先用一个最小请求确认 Key 和 Base URL 正确:
curl -s https://taotoken.net/api/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-chat", "messages": [{"role": "user", "content": "只回复 ok"}] }'返回里能看到choices[0].message.content就说明通道正常。如果你想先在网页里确认模型行为,可以用模型对话入口:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite 。
4.2 验证门禁会失败
门禁最容易犯的错是“永远绿”。故意引入一个类型错误,然后跑:
pnpm run typecheck echo "exit code: $?"如果退出码不是 0,说明 Gate 真的在检查。再跑一次完整门禁:
pnpm exec tsx scripts/run-gates.ts ci-static观察输出里是否打印了[gate:ci-static] failed。这一步确认了“文字要求”已经变成“可执行的非零退出”。
4.3 验证 Agent 会读取 AGENTS.md
在仓库根目录放一个测试任务,让 Agent 修改packages/下的某个文件,观察它是否先读了docs/architecture.md。如果它直接改代码,说明根 AGENTS.md 的路由写得不够明确,需要把“修改 packages/ 前必须阅读”这句话放到更靠前的位置。
4.4 验证决策记录被触发
提交一个改变行为的变更,检查 PR 里是否自动要求新增 Agent Note。可以在 CI 里加一条检查:
if git diff --name-only origin/main | grep -q '^packages/'; then if ! git diff --name-only origin/main | grep -q '^\.agents/notes/'; then echo "非平凡变更需要 Agent Note" exit 1 fi fi这条检查跑通后,决策记忆就不再依赖人的自觉。
5. 本篇常见错排查
5.1 AGENTS.md 写成了项目简介
最常见的错是把根 AGENTS.md 写成“本项目是做什么的”。Agent 读完知道项目背景,但不知道下一步去哪。修正方法是把第一段改成路由:每条规则指向更具体的拥有者,而不是重复细节。
5.2 门禁只跑局部测试
只跑 owning Vitest 文件,不跑真实组合测试,会导致 Loader 和实际装配的问题漏掉。产品可见插件必须有真实组合测试,手工ctx.plugin(...)的 unit test 不足以证明装配正确。
5.3 为了变绿而放宽阈值
Agent 很容易用--passWithNoTests、降低 coverage 阈值、或把--coverage.include缩窄到不再覆盖受影响文件。这些行为必须在 Skill 里明确禁止,并在 Review 时检查。
5.4 决策记录写成工作日志
Agent Note 不是施工清单。提案用 Problem / Proposal / Alternatives considered / Acceptance criteria / Risks;已实现记录改写为 Problem / Decision / Alternatives considered / Consequences。合并时要把“将要做什么”变成“现在实际是什么”。
5.5 模型调用散落各处
如果 Agent 主循环、审查 Skill、文档同步各配一套 Key,排查问题会非常痛苦。统一走TAOTOKEN_BASE_URL和TAOTOKEN_API_KEY,换模型只改一处。
5.6 门禁依赖图缺失
把质量检查写成一条长 Shell 命令,前面失败会截断后面输出,Agent 和 Reviewer 分不清哪项证据失败。用依赖图组织 Gate,每项检查保留自己的 id、输出和失败原因。
6. 长期编码与 Agent 场景的下一步
如果你只是偶尔用 Agent 改几个文件,上面的骨架可能显得重。但只要团队开始让 Coding Agent 承担持续交付,规则、知识、协议、决策记录、质量门禁这五类资产就会变成刚需。它们不能互相替代:规则缩小搜索空间,文档提供当前事实,Skill 约束高风险动作,Agent Note 保存长期决策,Gate 独立验证结果。
对于长期跑编码任务和 Agent 流水线的团队,建议把模型调用通道也固定下来。Coding Plan 适合需要持续、稳定调用额度的场景:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。接入细节和参数说明在文档里:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。
落地顺序建议从最小开始:先建根 AGENTS.md、docs/architecture.md和 Issue 验收条件模板;再为最重要的领域补docs/subsystems/;然后为关键用户旅程建最小的测试或 E2E Gate;当团队反复遇到同一种高风险任务时,再沉淀为 Skill;当某项设计会被未来重新讨论时,再创建 Agent Note。这样每一步都有可验证的产出,而不是一次性搭一个没人维护的大架子。