我是怎样使用 AI Agent 写代码的
<blockquote><p>该内容由 RSS 渲染生成,最佳阅读体验请前往:<a href="https://blog.grtsinry43.com/posts/coding-with-ai-agent">https://blog.grtsinry43.com/posts/coding-with-ai-agent</a></p></blockquote><blockquote>
<p>从 AI 辅助编码、Vibe Coding,到现在的混合开发工作流</p>
</blockquote>
<blockquote>
<p>TL;DR?复制下面这段提示词给你的 Agent,让它结合全文帮你优化自己的 AI 编程工作流:</p>
<pre><code class="language-md">这是一篇关于 AI Agent 编程工作流的经验总结:
https://blog.grtsinry43.com/posts/coding-with-ai-agent
请先完整阅读文章,再结合我当前的项目和使用习惯,帮我检查并优化自己的 AI 编程工作流。
重点分析:
1. 我现在使用 Agent 的流程中,哪些步骤缺失、重复或不合理;
2. 怎样根据任务复杂度区分直接执行、简单规划和深度设计;
3. 我的 CLAUDE.md、AGENTS.md、Skills、MCP 和 Hooks 应该怎样组织;
4. 怎样管理上下文、Compact、Handoff、项目文档和长期记忆;
5. 怎样合理使用主 Agent、Subagent 和不同能力、不同成本的模型;
6. 怎样改进编码、Debug、测试、Review 和验收流程;
7. 怎样减少无效 Token 消耗、过度思考和无意义的工具调用;
8. 怎样控制权限、修改范围和第三方 Skill、MCP 带来的安全风险;
9. 哪些工作适合交给 AI,哪些工作应该由我亲自完成或主导;
10. 最终为我整理出一套可以实际执行的分级工作流。
不要直接套用文章中的方案。请先询问我的技术栈、常用工具、项目规模、预算、权限要求和当前痛点,再根据我的实际情况进行调整。
输出时请包含:
- 当前工作流的问题;
- 建议保留和删除的部分;
- 优化后的完整流程;
- 推荐的规则文件结构;
- 推荐的 Skill、MCP 和模型分工;
- 一份适合我直接放进项目中的协作规范草稿。
</code></pre>
</blockquote>
<h2>写在前面</h2>
<p>都已经 2026 年了,我的网站里居然还没有几篇真正讲 AI 的文章,这件事多少有点抽象。</p>
<p>别人早就开始 all in AI,用 AI 接手越来越多的工作,我到现在才认真写这个话题。其实我很早就想写一篇 AI 编程入门教程,在学校的时候便建好了草稿,只是一直没有时间完善。那篇文章现在还在路上,之后应该会单独发布。我可能还会再写一篇模型横评,专门讲国内外模型、Agent 工具和各种订阅的体验。</p>
<p>这一篇,我想先讲自己的经验。文章里大概有两条线。</p>
<p>一条比较具体,讲我现在怎样配置模型、管理上下文、使用 Skill、MCP、Subagent 和文档,以及怎样让 AI 编码、Debug、测试和 Review。</p>
<p>另一条是我自己的变化。我从最初的 AI 辅助编码,逐渐进入大量 Vibe Coding,又慢慢形成了现在这种 AI 与手写并行的工作方式。</p>
<p>因为白天还要上班,晚上真正能用来写东西的时间并不算多。最近我也在调整作息,不知道是天气还是病毒的原因,这几天身体稍微有些不舒服,所以大概只能晚上抽出两个小时来写。</p>
<p>文章的大部分内容由我先口述,再让 GPT-5.6 帮我二次整理。我已经明确要求它尽可能保留我的口吻、主体思想和原本的表达方式。它主要负责修正口误、语音识别错误和不太通顺的句子。</p>
<p>大概就是这样,真的精力有限,是我第一个开始用 AI 写的文章,忘本了555。</p>
<hr>
<h2>我是从什么时候开始使用 Agent 的</h2>
<p>还是先从自己的经历讲起。</p>
<p>我真正开始频繁使用 AI 编程工具,应该是在实习之后,也就是我受伤的那段时间。那时候我开始使用 Claude Code,不过走的是第三方渠道。现在回头看,我甚至无法完全确定当时接入的 Claude 到底是不是真的。</p>
<p>我主要用它写自己的项目,包括一个 Android 项目,也做过一些其他尝试。大概从九月、十月开始,我便一直在用。到了十月、十一月接触 Codex 之后,后面的使用方式也慢慢延续下来。关于那段时间的经历和感受,我之前在另一篇文章里也讲过一些。</p>
<p>::: link-card href="/posts/from-think-to-code-in-2025/" title="从想法到实践:在无序的生活里,试图用代码敲出一点秩序" desc="" newtab="true"</p>
<p>:::</p>
<p>至于我什么时候开始有意识地优化工作流,应该是在今年年初。</p>
<p>当时我使用的是 Claude Code 官方订阅。用了一段时间之后,我发现 Token 消耗得实在太快,于是开始想方设法优化整个流程。后来也算阴差阳错,我看了很多教程,自己又做过一些 AI 方向的项目,慢慢积累下不少经验。</p>
<p>从三四月份回到学校开始,我已经比较熟练地使用这些 Agent 编程工具了。之后的几个月里,我一直在高强度体验各种模型和产品。</p>
<p>Claude Code 官方的 Pro 订阅我用过,也借朋友的 Max 订阅体验过;OpenAI 的 Plus 和 Business 用过;Cursor、OpenCode Go、MiniMax、MiMo、火山引擎 Coding Plan、Poe、OpenRouter 也都陆续试过。DeepSeek 更多按照 API 用量付费,之前通过教育认证拿到的 Gemini 学生订阅现在也还在。</p>
<p>::: link-card href="/posts/token-addiction/" title="我患上了 token 的瘾" desc="作为第一批被“纯 Vibe”工作流彻底卷入的开发者,我感到了一种前所未有的失语。" newtab="true"</p>
<p>:::</p>
<p>有朋友形容我是:</p>
<blockquote>
<p>哪个 AI 都吃一口。</p>
</blockquote>
<p>这么说倒也没错,我确实基本都试了一遍。</p>
<p>具体的模型体验和订阅选择,我会留到之后的入门文章和模型横评里。这一篇主要讲这些实践最后怎样变成了我的工作流。</p>
<hr>
<h2>我的主力工具</h2>
<p>我目前使用最多的 Agentic Coding 工具还是 Claude Code。</p>
<p>它是一款命令行形态的工具。在我看来,它目前依然属于 Agent 编码工具里非常成熟的一档。当然,它也有一个很明显的问题:太费 Token。</p>
<p>Claude Code 的界面运行在终端里,模型输出速度特别快时,TUI 偶尔会暴露出一些性能问题。不过正常使用时,这不算什么大问题。</p>
<p>真正重要的是,它的工作流程已经比较成熟,我自己也最熟悉这套交互方式。所以直到现在,Claude Code 仍然是我的主力工具。</p>
<p>除了 Claude Code,我用得比较多的还有 Cursor。Cursor 里的一些模型给我的感觉是便宜、快,同时效果也不错,多少有点碰到了“不可能三角”。它们响应很快,能力又足够完成大多数日常任务,所以我也会经常使用。</p>
<p>Codex 当然也在我的工作流里。之前我还尝试过把 GPT 系列模型接入 Claude Code。有人反馈,同一个模型放进 Claude Code 以后会比在其他 Agent 工具里更好用。我自己的体验没有那么明显,最终效果可能还是更取决于模型本身。</p>
<p>不过,Agent 工具的设计当然也很重要。至少从我的使用感受来看,Claude Code 确实好用。</p>
<p>国内外还有很多其他选择,比如 MiMo Code、OpenCode 等。我之前认真使用过一段时间 OpenCode,它的功能比较丰富,TUI 体验也不错,整体定位很明显,就是在对标 Claude Code。</p>
<p><img src="/uploads/pictures/2026-07-15-16:43:46-00.png" alt="image.png"></p>
<p>我的建议是,工具可以多试,但没有必要一直来回切换。找到一两个自己最习惯的主力工具,再围绕它们完善工作流,通常比不停追逐新产品更重要。</p>
<hr>
<h2>不要迷信上下文窗口</h2>
<p>我使用这些工具时,最先关注的问题之一是上下文管理。</p>
<p>无论一个模型宣传的 Context Window 有多大,实际使用时,我都不建议一直堆到接近上限。</p>
<p><img src="/uploads/pictures/2026-07-15-16:44:38-94.png" alt="image.png"></p>
<p>比如,一个模型拥有 1M 的上下文窗口,使用到 20%,其实就已经积累了大约 200k Tokens。按照我的经验,到这个阶段,上下文便可能开始涣散。模型仍然能够看到前面的内容,却不一定还能稳定抓住其中最重要的约束。</p>
<p>如果一个模型本身只有 200k 上下文,那么积累到这个量级时,基本已经接近用满。GLM、DeepSeek 等模型也会遇到相似的问题,上下文增加到一定程度以后,效果会逐渐下降。</p>
<p>所以,我通常会在使用到一定比例时(经验是 25% 到 35%)进行 Compact,必要时直接 Clear,重新开启会话。</p>
<p>很多人会觉得,上下文越多,模型知道的东西越多,效果理应越好。实际使用中并非如此。旧日志、无关的工具输出、已经放弃的方案和重复讨论不断积累,一方面会增加成本,另一方面也会干扰模型判断。</p>
<p>上下文不是仓库,不能什么都往里面塞。</p>
<hr>
<h2>让不同模型承担不同角色</h2>
<p>另一个重要问题,是不同模型应该怎样配合。</p>
<p>现在有不少模型可以直接担任主模型,但我通常不会让一个模型包办所有工作。Claude Code、Cursor 这些工具里都有类似 Subagent 的能力,我觉得应该充分利用。</p>
<p>我一般会让多个 Subagent 分别阅读、搜索和分析代码,或者把一些已经明确的实现任务交给它们,最后由主模型统一检查和验收。</p>
<p>能力更强的模型适合负责理解任务、判断架构、制定方案和最终验收;速度更快、价格更低的模型可以负责扫描代码、搜索文件,以及完成边界清晰的实现。</p>
<p>如果预算比较充足,也可以一直使用强模型,只是在不同任务里调整 Reasoning Effort。国产模型同样可以按照类似方式组合。我有时会把它们统一接入 Claude Code,再根据能力和成本,映射到 Opus、Sonnet、Haiku 对应的角色上。</p>
<p>具体哪个模型必须映射到哪个名字并不重要。真正重要的是形成分层:关键判断交给更可靠的模型,搜索和执行交给更快、更便宜的模型;简单任务不浪费昂贵模型,重要决策也不交给只适合快速执行的小模型。</p>
<p>不过,模型能力越来越强以后,也不能无脑叠加复杂流程。</p>
<p>像 Superpowers、OpenSpec 这类强调 Brainstorm、Spec 和完整规划的 Skill,本身当然有价值,我身边也有同事在用。但如果模型本身已经具备很强的推理能力(比如 Claude Fable 5,GPT 5.6 Sol),再把 Reasoning Effort 调到 High,同时套上一整套要求它不断质疑和反复确认的 Skill,很容易出现过度思考。</p>
<p>模型会一直分析、一直反问、一直完善方案,就是迟迟不动手。最后未必得到明显更好的结果,时间和 Token 却消耗了很多。</p>
<p>所以,我更习惯按照任务复杂度决定流程。简单任务直接完成,中等任务先做简短分析,真正涉及架构和大范围修改的任务,再进入完整的设计过程。</p>
<p>困难任务当然需要深入思考。问题出现在一套流程被无差别地套到所有任务上。</p>
<p>Skill 应该补充模型和任务的短板,而不是机械地增加步骤。</p>
<hr>
<h2>人和 AI 之间,需要一套固定的协作关系</h2>
<p>现在有各种插件、Skills、Spec、Plan 和 Brainstorm 工具。这些东西都可以尝试,但最终有没有用,还是取决于它们是否符合自己的工作方式。</p>
<p>我自己写过一个规范人与 AI 协作的 Skill,之前也开源过。它会按照任务复杂度,选择不同的执行流程。</p>
<p><a href="https://github.com/grtsinry43/agent-skills/blob/main/skills/grt-collaborating/SKILL.md">https://github.com/grtsinry43/agent-skills/blob/main/skills/grt-collaborating/SKILL.md</a></p>
<p>简单修改,比如调整样式、修改文本或者完成一个边界清楚的小功能,不需要大量前期规划,直接动手即可。</p>
<p>涉及较大功能或架构变化时,我通常会先和 AI 讨论。先把需求、影响范围、实现方案和潜在问题理清楚,再进入编码。</p>
<p>如果是大型项目或者关键设计,流程还会继续细分,包含需求梳理、代码探索、方案设计、任务拆分、实现、测试和验收。</p>
<p>如果正好习惯这套方式,可以直接使用我的 Skill;如果不习惯,也可以复制里面的文本,再按照自己的习惯修改。</p>
<p>这里真正重要的是,人和 AI 之间最好形成一套稳定的协作节奏。</p>
<p>AI 默认的工作方式不一定符合我们的习惯。有时候,你只想先讨论一下,它却上来就开始改代码;有时候,你明确让它快速完成一个小改动,它又不停追问一些不需要确认的细节。这两种情况都很痛苦。</p>
<p>所以,最好提前约定什么时候可以直接修改,什么时候必须先讨论,什么时候需要完整规划,写完以后怎样汇报,以及哪些地方必须由人确认。</p>
<p>让 AI 知道应该怎样与你协作,比单独把某一次提示词写得特别长更重要。</p>
<hr>
<h2>Skill:让一个人“自愿蒸馏”自己</h2>
<p>既然说到了 Skill,那就专门讲讲它。</p>
<p>之前我在文章里写过一句话:</p>
<blockquote>
<p>Skill 可以让一个人自愿蒸馏自己。</p>
</blockquote>
<p>过去,当我们拿到一个项目或者一份文档时,通常只能看到最终的设计、代码,以及作者具体做过什么。至于他为什么这样设计、平时怎样思考、积累过哪些经验,往往没有被真正提炼出来。</p>
<p>Skill 有些不同。</p>
<p>它相当于一个人主动把自己的经验、想法和工作方式整理出来,写进一个 Markdown 文档。稍微夸张一点说,当你拿到这份 Markdown 时,就像拿到了这个人的一部分思想。</p>
<p>这个说法确实有些夸张,但 Skill 的价值就在这里。它把原本只存在于个人经验里的东西,变成一套可以被 AI 读取、遵循和复用的工作方式。</p>
<p>现在寻找 Skill 的地方也很多,比如相关的 Marketplace、skills.sh,以及各种可以通过命令快速安装 Skill 的工具。安装以后,还能把它们软链接到 Claude Code、Codex、OpenCode 等不同 Agent 工具中统一使用。</p>
<p>我比较推荐的组合,是一个负责协作方式的主 Skill,再搭配若干领域 Skill。</p>
<p>主 Skill 规定什么时候讨论、什么时候规划、什么时候编码,以及最后怎样验收。领域 Skill 则负责某个具体技术方向的知识和最佳实践。前端项目可以加载 Web Best Practices,React Router 项目可以加载对应的框架 Skill,后端项目则加载语言和框架相关规范。Debug 时也可以使用专门的排查 Skill。</p>
<p>GitHub 上还有不少开发者公开了非常个人化的 Skill。比如,有些 Skill 会要求 AI 一直向你提问,直到真正把需求了解清楚以后才允许开始写代码。这些东西都挺有意思。</p>
<p>你甚至可以在全局的 <code>CLAUDE.md</code>、<code>AGENTS.md</code> 或类似文件里规定:进入一个尚未初始化 Skill 的项目时,先分析各个目录使用了什么技术,再寻找并配置合适的 Best Practices Skill。</p>
<p>这样,就相当于把别人已经总结好的经验,很方便地引入自己的项目。</p>
<hr>
<h2><code>CLAUDE.md</code>、<code>AGENTS.md</code> 和项目规则</h2>
<p>除了 Skill,项目里最好还有一份稳定的规则文件。</p>
<p>使用 Claude Code,可以写 <code>CLAUDE.md</code>;使用 Codex,可以写 <code>AGENTS.md</code>;其他工具也有类似文件。</p>
<p>这些文件用来保存项目级规则和说明。在你和 AI 协作的过程中,它们通常比某次对话里临时提出的要求更稳定,也更容易成为 AI 长期遵循的约束。</p>
<p>拿到一个新项目,准备让 AI 参与开发时,我非常推荐先写好这样一份文件。</p>
<p>其中可以包括协作和编码规范,比如禁止 Placeholder 实现,使用陌生库之前必须先查文档,调用 API 前确认当前版本的真实用法,明确哪些情况可以直接修改,哪些情况必须先讨论,以及完成后需要执行哪些测试和检查。</p>
<p>还可以介绍项目本身,包括它解决什么问题、整体架构怎样划分、各个目录承担什么职责,以及主要的数据流和模块边界。</p>
<p>开发流程同样可以写进去,例如怎样创建分支、怎样提交、需要经过哪些检查、如何合并和发版。某些项目还会有自己的特殊规则,比如遇到特定报错时优先检查哪个模块,或者在某个目录工作时必须遵循哪些限制。</p>
<p>不过,这类文件最好控制篇幅。</p>
<p>上下文越来越长以后,模型对规则的注意力很容易下降。如果把大量不常使用、彼此重复,甚至互相冲突的内容全部塞进去,真正关键的规范反而可能失效。</p>
<p>因此,这类文件应该尽量简短、明确,只放那些适用于大多数任务、确实需要长期遵守的规则。更具体的内容可以拆到单独文档中,再从主规则文件里引用。</p>
<p>用我的来举个例子:</p>
<pre><code class="language-md"># Repository Guidelines
## Project Structure & Module Organization
- `cmd/api`: application entry point (config load, dependency wiring, Fiber startup).
- `internal/`: core packages (config, database, HTTP handlers/routers, services, domain models, persistence).
- `configs/`: runtime configuration files (e.g., app and auth settings).
- `migrations/`: Goose SQL migrations using `NNNN_description.sql` naming.
- `docs/`: generated OpenAPI artifacts (`swagger.json`).
- `storage/`: runtime data (logs, uploads, HTML snapshots, GeoIP databases).
## Build, Test, and Development Commands
- `go mod tidy`: sync Go module dependencies.
- `APP_PORT=8080 go run ./cmd/api`: run the API locally.
- `make migrate-up|migrate-down|migrate-status|migrate-version`: manage database migrations via Goose.
- `make migrate-create NAME=add_posts_table`: create a new SQL migration.
- `make docs`: regenerate OpenAPI JSON from Swagger annotations.
- Note: `swag` is sensitive to annotation order; keep `@BasePath /api/v2` in the main comment block (prefer near the end) to ensure it is emitted into `docs/swagger.json`.
## Coding Style & Naming Conventions
- Use standard Go formatting (`gofmt`) and idiomatic Go naming (PascalCase exports, camelCase locals).
- Keep packages cohesive and aligned with the existing layout (e.g., `internal/app/*` for services, `internal/domain/*` for entities/repositories).
- Migrations must follow `NNNN_description.sql` so Goose can order them.
## Additional Agent Requirements
- 0. Guarantee high-quality code; forbid placeholder implementations, fake implementations, or problematic code.
- 1. For major changes, list a modification plan first, including strategy, impacted files, technical approach, and choices with reasons.
- 2. Act as an excellent Go engineer; adhere to Go and Fiber best practices, handle Go legacy issues with modern syntax, and avoid GORM pitfalls using experienced practices.
- 3. Before using any library, check its latest version and documentation; leverage search and network access; do not guess or assume usage.
## Testing Guidelines
- No dedicated test suite is present in this repo yet. When adding tests, place `_test.go` files alongside the code under `internal/` and run `go test ./...`.
- Prefer table-driven tests for handler/service logic where possible.
## Commit & Pull Request Guidelines
- Follow the observed Conventional Commits style (e.g., `feat: ...`, `feat(server): ...`, `fix: ...`).
- PRs should include a clear summary, rationale, and any required config or migration notes.
- If you change API handlers or models, update `docs/swagger.json` via `make docs` and mention it in the PR.
## Database
- The only supported database is **PostgreSQL 17+**. SQLite support was removed; do not write cross-dialect SQL workarounds.
- Raw SQL may use PostgreSQL-specific syntax (e.g., `FILTER (WHERE ...)`, `jsonb` operators) when needed.
- Prefer GORM model-based queries where possible; use raw SQL only for aggregations or features not expressible through GORM's query builder.
## Security & Configuration Tips
- Runtime behavior is controlled via env vars like `APP_PORT`, `DB_DRIVER`, `DB_DSN`, `AUTH_SECRET`, and `AUTH_DEFAULT_ROLES`.
</code></pre>
<hr>
<h2>跨上下文:Agent 的记忆问题</h2>
<p>很多人在使用 AI 编码时,都会遇到一个很大的限制:Agent 的 Context 太小了。</p>
<p>第一次在完整上下文里开发时,模型效果可能非常好。但只要进行过一次压缩,它便可能忘记这个项目原本是什么样的。之后生成的代码不仅效果变差,还会和前面已经完成的设计无法对应。</p>
<p>多个 Agent 协作时,这个问题更加明显。一个 Agent 已经完成一半工作,你想把任务交给另一个工具继续,却发现前面积累的上下文太长,根本带不过去。不同工具组织上下文的方式也不一样,很难直接完成交接。</p>
<p>还有一种情况是,当前会话已经积累了大量内容。继续工作会越来越贵,尤其缓存过期以后,之前的 Tokens 可能需要重新发送。可一旦 Compact,又会损失不少细节。</p>
<p>所以,Agent 的状态管理,尤其是记忆,一直很难彻底解决。</p>
<p>我目前会把信息分成三个层次。</p>
<p>长期稳定、所有 Agent 都必须遵守的内容,放进项目规则文件。某个需求的分析、设计、进度和交接信息,放进项目文档或者 Obsidian。开发过程中逐渐积累的经验、历史决策和踩坑记录,则交给 Agent Memory。</p>
<p>我之前使用过一个 Agent Memory 项目。它可以部署在本地,通过 Hooks 捕获 Agent 的工具调用、代码读取和修改行为,再从中整理记忆;也可以通过 MCP 接入不同工具,让 Agent 主动搜索、增加、修改或者删除某条 Memory。</p>
<p><a href="https://github.com/rohitg00/agentmemory">https://github.com/rohitg00/agentmemory</a></p>
<p>不过,单纯依赖自动记忆还不够。</p>
<p>对一个稍微复杂的项目来说,最好还是给 Agent 留下明确文档。我自己会使用 Obsidian。比如,当我要让 AI 完成一个新需求时,可以先为它建立单独的目录或文档。</p>
<p>第一次接手任务的 Agent 阅读代码以后,需要把需求背景、当前结构、相关模块、已经确认的事实、仍然存在的问题、准备采用的方案、当前进度和下一步工作都整理进去。</p>
<p>当它的上下文快要用完,或者需要换另一个工具继续时,就先进行一次 Handoff,把当前状态完整写入文档。下一个 Agent 不需要继承前面全部的聊天记录,只要读取这份交接文档和相关代码,就可以继续工作。</p>
<p>还有一些开发中反复出现的提醒,比如某种实现以前失败过、某个模块不适合按照常规方式修改、遇到某类问题应该优先检查某个位置。这些内容不一定适合写成永久规则,但又值得以后重新想起,就可以保存到 Agent Memory。</p>
<p>我现在的思路,是把会话里的状态逐渐转化成规则、文档和记忆,而不是一直试图搬运完整的历史对话。</p>
<hr>
<h2>一些我会安装的插件</h2>
<p>插件方面,如果使用 Claude Code,我个人非常推荐 Claude HUD。</p>
<p><img src="/uploads/pictures/2026-07-15-16:47:04-a0.png" alt="image.png"></p>
<p>它可以直接显示当前的上下文占用、订阅额度、工具调用、Todo 状态、Token 消耗,以及模型输出速度。这些信息不会直接提高模型能力,却能让整个运行状态变得很直观。</p>
<p>你可以随时知道上下文还剩多少,模型已经消耗了多少 Token,任务执行到了哪一步,以及是否应该 Compact 或者开启一个新会话。</p>
<p>MCP 数量比较多,或者同时使用多个 Agent 工具时,也可以使用专门的管理和同步工具。现在已经有不少开源项目可以统一管理 Skills、MCP 和配置文件,按照自己的习惯选择即可。</p>
<p>不过,插件、Skill 和 MCP 最终都只是工作流的辅助。真正重要的,还是你怎样面对一个实际项目。</p>
<hr>
<h2>以我的博客项目为例</h2>
<p>当时我写博客项目的时候,其实已经赶上了这一轮 AI 快速发展的阶段。不过那时我使用 AI 还比较克制,并没有把大量工作直接交出去。</p>
<p>以前端部分为例,拿到项目之后,我首先会确认项目规范,也就是前面提到的规则文件,然后再设计目录结构。</p>
<p>代码结构一般讲究高内聚、低耦合。我的博客本身比较复杂,所以设计目录时,我大致借用了一些领域拆分的思路,把业务模块、公共能力和通用 UI 分开。</p>
<p>当时写给 Agent 的规范,大概包括这些内容:</p>
<pre><code class="language-markdown">页面只负责数据接入和模块编排,不堆积复杂业务逻辑。
业务能力按 feature 划分;跨功能能力收敛到 shared;通用组件放入 ui。
浏览器 API 必须封装,统一处理 cleanup、SSR 安全和重复绑定问题。
页面级数据优先通过 SvelteKit load 提供;跨层共享使用 Context 和 Store。
内容页面优先 SSR/SSG,评论、点赞和交互增强采用客户端 Islands。
禁止在 SSR 阶段访问浏览器对象,禁止随意引入全局状态,禁止修改构建产物和依赖目录。
只基于代码、日志和已知事实得出结论;证据不足时继续验证,不凭空猜测。
</code></pre>
<p>规范确定以后,再决定先完成哪些模块。</p>
<p>比如,首先要写文章模块。我会先和 AI 讨论这个模块应该怎样实现,包括数据查询、接口组织和整体结构。然后把自己的设计想法告诉它,让它按照项目规范给出实现方案、执行步骤,以及必要的代码片段。</p>
<p>等方案确认以后,再让 AI 正式实现。实现完成后,我会进行第一次 Review,检查它有没有遵守规范,结构是否合理,代码是否符合预期。Review 基本通过后,再让它补充单元测试,最后进行实际验证。</p>
<p>整个过程可以概括成:先确定模块,再讨论方案;对齐 API、技术栈和设计思路后开始实现;实现完成后由人 Review,再补测试和验证。</p>
<p>如果要使用 AI 辅助开发,提示词至少应该写清楚一些。要告诉它具体完成哪个模块,使用哪些 API,采用什么技术栈,遵循什么设计,哪些地方不能修改,以及最终怎样验收。</p>
<p>什么都不说清楚,只给一个模糊需求,AI 只能自行补全大量假设。最后很容易得到一套看起来完整,却和你的真实想法并不一致的实现。</p>
<hr>
<h2>一个更完整的项目流程</h2>
<p>我之前给朋友写过一个 Android 项目。</p>
<p>这类任务,我一般会先自己阅读文档,确认功能到底能不能实现。我会看 Android 官方文档,也会查 Jetpack Compose 等相关资料,先对准备使用的 API 和实现方式形成基本认识。</p>
<p>确认功能可行以后,再让 AI 阅读已有代码。我会开启 Subagent,让它们分别探索项目和相关模块,再按照我的协作 Skill 进入完整流程。</p>
<p>代码读完以后,让主 Agent 分析当前问题,并写出一份实践文档。文档里需要说明当前项目结构、与需求相关的代码、已经确认的事实、可选方案、方案之间的取舍,以及具体执行步骤。</p>
<p>这些内容写进文档以后,当前上下文可能已经消耗了很多 Tokens。这个时候可以 Compact,也可以开启一个新模型,让它重新对照代码和文档,检查方案有没有问题。</p>
<p>如果第二个模型认可,我自己也认可,就正式开始实现。</p>
<p>实现完成后,我会先自己 Review,确认方向和结构没有明显问题,再让 AI 补充测试。测试写完以后,再做第二轮 Review 和实际运行验证。</p>
<p>这就是我现在比较完整的一套工作流程。</p>
<hr>
<h2>怎样让 AI Debug</h2>
<p>让 AI Debug 时,我比较重视三个原则。</p>
<p>第一个原则是禁止推测。</p>
<p>AI 应该根据日志、代码、运行现象和各种线索分析问题,解释这些现象为什么会出现。证据不足时,就继续补充日志、设计实验或者提出需要验证的问题,不能直接把一个听起来合理的猜测当成根因。</p>
<p>第二个原则是控制修改面。</p>
<p>修复问题时,修改范围应该尽可能小。不能为了处理一个局部 Bug,顺便重构整个架构,牵连大量无关代码。应该先找到最小修复点,再说明为什么只需要修改这里,以及这次修改可能影响哪些范围。</p>
<p>第三个原则是寻找根因,不要只让报错消失。</p>
<p>几乎所有 AI 在修 Bug 时,都有一个比较明显的倾向:这里抛出异常,就加一个 <code>catch</code>;这里出现错误状态,就补一个默认值;某一步失败,就增加一个兜底分支,把问题绕过去。</p>
<p>报错可能暂时消失,原本的问题却仍然存在,只是变得更难发现。</p>
<p>所以,必须提前规定,AI 的目标是找到问题最初出现在哪里。除非兜底本身就是设计的一部分,否则不能用兜底代替根因修复。</p>
<hr>
<h2>测试不能只为了覆盖率</h2>
<p>让 AI 写测试时,也不能只是为了提高覆盖率,机械地生成大量测试代码。</p>
<p>每个测试都应该有明确目的,比如验证正常路径、边界条件、历史 Bug 是否会再次出现、不同平台上的行为是否一致,以及模块之间的集成是否符合预期。</p>
<p>测试也应该分层推进,从单元测试、集成测试,到多端测试、自动化实际运行测试,最后进入真实环境验证。</p>
<p>尤其需要注意,AI 很容易为自己刚刚写出的实现,再写一个“必然通过”的测试。</p>
<p>测试通过,不代表需求真的被满足。</p>
<hr>
<h2>怎样 Review AI 写的代码</h2>
<p>Review 非常重要。</p>
<p>我曾经有一段时间没有认真 Review AI 生成的代码,但现在基本都会检查。</p>
<p>在我自己的协作 Skill 里,有一个任务完成后的汇报机制。AI 写完以后,不能只告诉我“任务已经完成”,还要先汇报这次修改。</p>
<p>我会要求它自己判断,哪些内容最需要我关注。比如最重要的文件在哪里,核心功能怎样实现,做出了哪些设计选择,为什么选择这种方案,放弃了哪些方案,里面存在哪些取舍,以及哪些代码风险较高。</p>
<p>我会先检查这些重要部分,再去扫剩下的修改。</p>
<p>异常路径、资源生命周期和修改范围肯定也要看。尤其要确认 Diff 是否过大,有没有修改需求之外的代码,是否引入不必要的抽象,是否增加过多包装和参数,是否真的处理了根因,以及有没有资源没有释放或者状态流被破坏的问题。</p>
<p>如果模型一次写出的内容太多,我会让它把汇报拆开,一部分一部分讲。</p>
<p>修改量特别大时,还可以引入第二个模型进行交叉 Review,比如让 Codex 再检查一次其他模型写出的代码。</p>
<hr>
<h2>AI 是怎样毁掉一个项目的</h2>
<p>早期的 AI 很喜欢直接覆盖 Existing Code。</p>
<p>你让它修改一个地方,它可能一下子把原来的实现全部替换掉,甚至只留下一段注释,告诉你这里以后应该实现什么。</p>
<p>现在的模型很少再犯这么明显的问题,但还是有很多其他方式可以把项目搞坏。</p>
<p>它可能不搜索最新文档,直接按照训练数据里记住的内容猜测 API,最后生成大量不存在或者已经过时的接口。</p>
<p>它也可能写出大量 TODO、Placeholder,以及只有注释、没有真实实现的代码。表面上结构已经搭好,实际上核心功能根本没有完成。</p>
<p>还有过度防御性编程的问题。AI 有时很喜欢增加大量参数,在调用链之间一层又一层地包装,再加入各种没有必要的防御逻辑。最后看起来考虑得非常全面,真正的业务逻辑却被淹没了。</p>
<p>另一个常见问题,是需求还没有理解完整,它便已经开始修改。修一个 Bug 时不断扩大范围,最后动到很多无关模块。</p>
<p>面对复杂问题时,不同模型还可能给出完全相反的分析,最后变成一种左右脑互搏。</p>
<p>所以,人必须始终抓住已经确认的事实,不能被一套又一套听起来合理的解释带着走。</p>
<hr>
<h2>让 AI 辅助设计和文档</h2>
<p>AI 也可以参与设计工作。</p>
<p>比如,可以先让它根据现有视觉风格生成一套原子化设计规范和 Design Tokens,再由人逐项 Review。确认 Token 以后,再按照它们实现组件。这样比让 AI 每次临时发挥,更容易保持视觉统一。</p>
<p>技术文档也是一样。</p>
<p>完成一次问题排查后,文档至少应该讲清楚最初出现了什么现象,收集了哪些证据,排除了哪些方向,最终根因是什么,做了哪些修改,怎样验证有效,以及还有哪些风险。</p>
<p>任务完成以后,不同信息应该存到不同地方。</p>
<p>可复用的经验写进 Agent Memory;对某个模块形成的新理解,更新到项目文档;这次具体做过哪些修改,写进任务记录或者 Handoff 文档。</p>
<p>如果开发过程中发现原有文档已经不准确,也应该顺便更新,避免后面的 Agent 继续依据错误信息工作。</p>
<hr>
<h2>技术选型也可以考虑 AI</h2>
<p>如果是公司项目,技术栈已经确定,那基本没有选择空间。这里主要讨论个人项目,或者自己能够参与技术选型的场景。</p>
<p>当多个方案都能满足需求时,可以考虑哪些技术更方便 AI 编写,同时也方便人 Review。</p>
<p>前端方面,TypeScript 和 React 应该是目前 AI 非常熟悉的一套组合。SWR、TanStack Query、React Scan、Jotai、shadcn/ui、Tailwind CSS、Vite、Next.js 等工具的文档、示例和开源项目都比较多,AI 对常见用法通常也更熟悉。</p>
<p>这并不意味着所有项目都应该选择 React。只是当几个方案都合适时,选择资料丰富、社区规范成熟的技术,确实能降低和 AI 协作的成本。</p>
<p>有些语言在 AI 时代反而变得更有优势。</p>
<p>比如 Go。过去很多人会觉得 Go 表达能力有限,重复代码多,写起来比较累。有了 AI 以后,机械和重复的部分可以交出去,而 Go 清晰、直接、约束强的特点,让人更容易阅读和 Review AI 生成的代码。</p>
<p>Rust 也有相似的变化。过去使用 Rust 的门槛比较高,所有权、生命周期和类型问题会消耗很多时间。AI 降低了这部分成本,一些以前不太敢写的模块,现在也可以尝试完成。</p>
<p>不过,Rust 仍然不能完全交给 AI。自己至少需要具备一定基础,能够判断所有权、并发模型和错误处理是否合理。</p>
<p>代码通过编译,不代表设计一定正确。</p>
<hr>
<h2>让合适的模型做合适的事情</h2>
<p>不同模型的能力倾向并不完全一样,最好不要让一个模型包办所有任务。</p>
<p>以前端为例,我通常会把视觉设计、UI 实现、业务逻辑和 Review 分开。</p>
<p>前端视觉设计和原型,我更愿意交给 Gemini。具体的前端组件和页面实现,我会优先使用 Claude。业务逻辑和复杂代码更适合交给 Codex,代码 Review 也通常以 Codex 为主,Claude 可以作为补充。</p>
<p>Gemini 在视觉方向、页面布局和原型探索方面比较合适。Claude 在样式、组件结构和前端代码上的综合表现比较稳定。Codex 更擅长业务逻辑、复杂重构和 Review。</p>
<p>但如果直接让 Codex 从零设计一套 UI,我自己的体验并不算好。即使提供了 Design Tokens,最后的视觉效果有时还是比较普通。</p>
<p>没有一个模型能在所有任务上保持最优。让合适的模型完成它更擅长的工作,通常比始终使用同一个最强模型更加舒服。</p>
<hr>
<h2>成本是无法绕过的问题</h2>
<p>使用 Agent 编码,成本始终无法绕过。</p>
<p>首先还是上下文。上下文越长,成本越高。要做好记忆、文档、Handoff 和任务接力,避免重复探索,也不要不断消耗没有价值的 Tokens。</p>
<p>虽然前面推荐了很多 Skills 和 MCP,但数量也一定要控制。它们的定义、说明和工具信息同样会占用上下文。装得太多,不仅增加成本,也可能影响模型注意力。</p>
<p>模型和 Reasoning Effort 也应该按照任务强度分配。简单任务不需要最昂贵的模型,也没有必要开启最高推理强度。真正复杂的任务,再使用更强的模型和更高的 Effort。</p>
<p>至于订阅和 API,我自己的选择比较直接。Claude、Codex 这类价格较高、使用频率也高的工具,优先走订阅。国内模型如果提供合适的 Coding Plan 或 Token Plan,也优先购买套餐。</p>
<p>像 DeepSeek 这种 API 本身非常便宜的模型,可以直接按量付费。其他价格较高、又没有合适套餐的模型,我通常不太推荐长期走 API。</p>
<hr>
<h2>权限和安全</h2>
<p>安全问题也非常重要。</p>
<p>我之前发过一条 QQ 动态,说自己开启 <code>--dangerously-skip-permissions</code> 以后,就像打开了潘多拉魔盒,再也回不去了。</p>
<p>但实际上,不可能真的一直这样使用。这种权限实在太危险了。我真正长期完全跳过确认的时间并不多,最近也重新回到了需要手动确认的状态。</p>
<p>很多 Agent 工具都提供 Sandbox 模式,平时应该尽量开启,限制 Agent 能读取和修改的范围。也可以使用 Bubblewrap 一类的隔离工具,限制进程只访问相关目录。容器化也是比较可靠的方案。</p>
<p>对于危险命令,可以通过 Hooks 设定规则,要求必须由人确认,不能默认执行。</p>
<p>第三方 MCP 和 Skills 在安装前同样需要 Review。它们可能包含命令、提示词和外部服务调用,不能因为开源就完全不检查。</p>
<hr>
<h2>并行开发</h2>
<p>并行开发方面,我使用 <code>git worktree</code> 的次数其实不算多。</p>
<p>大多数时候,我还是串行开发,先完成一个任务,再继续下一个。即使同时工作,也通常是多个项目并行,很少在同一个项目中同时开启大量 Agent 修改代码。</p>
<p>如果多个任务之间会相互影响,我反而不太建议直接把它们完全隔离,让多个 Subagent 分别修改。这种情况下,可以考虑 Agent Team,让不同 Agent 之间互相发送消息、同步进度。</p>
<p>如果只是让几个完全隔离的 Agent 同时写同一套代码,确实很容易产生冲突。</p>
<p>并行并不是越多越好。任务之间真正能够拆分,而且边界足够清楚时,并行才有价值。</p>
<hr>
<h2>我为什么不再完全 Vibe Coding</h2>
<p>我开始大量把代码交给 AI,应该是在今年三四月份,也就是刚回到学校的那段时间。</p>
<p>当时我一直在尝试各种新模型,也开始采用比较纯粹的 Vibe Coding。它的效率确实非常高。只要提示词给得足够清楚,AI 生成的代码质量往往也不会太差。</p>
<p>但这种方式最大的问题,是可维护性太差。</p>
<p>一个项目只要大量使用 AI 编写,后面就可能变得很难维护。尤其是 AI 连续写了好几天,提交了一大堆 Diff,而你 Review 时只想看一眼,说一句:</p>
<blockquote>
<p>LGTM。</p>
</blockquote>
<p>这其实是非常痛苦的。</p>
<p>项目仍然在快速推进,你对它的理解却可能已经逐渐跟不上。到最后,你甚至会发现,一个项目只要大量使用过 AI,自己便不太敢再手动维护它。</p>
<p>所以,我现在会按照任务类型决定哪些工作可以直接交给 AI。</p>
<p>如果一个功能的实现方式已经完全确定,我也知道它应该怎样写,只是需要真正实现出来,那可以完整交给 AI。</p>
<p>如果我只有一个想法,还不知道具体怎样落地,或者里面涉及技术取舍,那就应该先讨论,不能直接动手。</p>
<p>还有一些事情,比如编译器、渲染系统和整体架构设计,我不会完全交给 AI。AI 可以提供方案、参与讨论、帮助验证,最终设计仍然需要由我完成。</p>
<p>我重新开始手写,也不意味着放弃 AI。不同类型的工作,本来就不应该采用同一种自动化程度。</p>
<p>现在对我来说,手写的意义也不只是练习语法。</p>
<p>手写会迫使我逐步回答:数据从哪里来,状态在哪里改变,这一段依赖什么假设,失败以后系统会处于什么状态,为什么这一层必须存在。</p>
<p>真正需要自己建立完整模型的代码,我仍然会亲手写,或者至少全程参与。</p>
<p>AI 负责扩大我的执行能力,我负责维护对系统的理解。</p>
<hr>
<h2>AI 与学习</h2>
<p>AI 确实可以提高学习效率。</p>
<p>过去接触一个新的库,可能需要先记住大量 API。现在很多时候,只要理解这个库解决什么问题、具备哪些能力、有哪些重要注意事项,就已经可以开始尝试。真正需要具体 API 时,再查文档或者让 AI 辅助。</p>
<p>但基础知识不能完全跳过。</p>
<p>AI 可以帮助学习,却无法替代思考。一定要分清楚,什么时候是自己真正理解了,什么时候只是 AI 帮你把东西做出来了。</p>
<p>千万不要因为 AI 能够完成一个任务,就认为自己已经掌握了这个领域。</p>
<p>我敢大量交给 AI 的内容,通常还是自己比较熟悉的技术栈。只有自己具备一定理解,才有能力判断它写出的东西是否正确。</p>
<p>至少目前,我还没有到离开 AI 就完全不会写代码的程度。我仍然保留手写和 AI 并行的习惯。</p>
<hr>
<h2>AI 编程真正改变了什么</h2>
<p>AI 编程首先改变的,可能是精力分配。</p>
<p>有了 AI 以后,我们可以把一部分重复、机械的实现工作交出去,节省时间和精力,用来完成更多事情。</p>
<p>但成本没有消失,只是发生了转移。</p>
<p>过去主要面对学习成本、实现成本和时间成本。现在又增加了 Token 成本、Review 成本、验证成本、维护成本,以及理解 AI 生成代码的成本。</p>
<p>而且,一个项目中由 AI 生成的代码越多,它的可读性和可维护性就越容易下降。这很难完全避免。</p>
<p>所以,在 AI 时代,人的价值可能会更多体现在架构、取舍和判断上。至少在 AI 编程这个场景里,判断力和学习能力仍然非常重要。</p>
<hr>
<h2>Vibe Coding 和 AI 辅助编码是两种用法</h2>
<p>Vibe Coding 和 AI 辅助编码其实是两个概念。</p>
<p>个人做原型、小项目,或者验证一个想法时,可以使用更接近 Vibe Coding 的方式,快速把东西做出来。</p>
<p>但面对大型、长期维护的项目,我不太建议完全采用这种方式。你当然可以使用 Agent 工具,但不能把整个项目全部交出去,自己不再参与理解和判断。</p>
<p>而且,Agent 越强,反而意味着你越需要了解自己的项目。</p>
<p>这件事看起来有些反直觉。很多人会觉得,模型能力越强,使用门槛就应该越低。</p>
<p>但模型越强,它一次能够完成的修改越多,能够替你做出的决策也越复杂。这个时候,使用者反而更需要具备足够的能力,判断它的方向是否正确。</p>
<p>你对项目理解得越深入,需求表达得越清楚,模型最终完成的效果才会越好。</p>
<p>更强的 Agent 确实降低了部分实现门槛,同时也提高了对架构能力、判断能力和表达能力的要求。</p>
<hr>
<h2>怎样才算会使用 AI 编程</h2>
<p>最后,怎样才算真正会使用 AI 编程?</p>
<p>我觉得,AI 编程有点像把工作交给一个小团队。</p>
<p>在传统开发中,你可能是一个组长。你需要理解需求、完成设计、拆分任务,再把不同工作交给不同成员。过程中还要跟进进度、Review 结果,并为最终交付负责。</p>
<p>现在面对 AI,做的其实是类似的事情。</p>
<p>你需要具备需求表达能力、架构设计能力、任务拆分能力、上下文组织能力、风险判断能力,以及 Review 和验收能力。</p>
<p>把需求扔进去,等代码吐出来,还不能算真正会使用 AI。</p>
<p>真正会使用 AI,意味着你能够判断哪些事情应该交给它,应该交给哪个模型,需要提供什么上下文,怎样验证结果,以及什么时候必须由自己接管。</p>
<p>所以,“会使用 AI 编程”在我看来,其实已经是一个比较高的评价。</p>
<p>如果一个人真的能够把 AI 编程这件事做好,那么至少在传统的软件开发环境里,他应该已经具备了带领一个小团队完成工作的部分能力。</p>
<p>半年前,我还在尝试让 AI 多替我写一些代码。</p>
<p>后来,我开始期待它替我完成整个项目。</p>
<p>到现在,我更关心的是,怎样让它参与工作的同时,不让自己失去对工作的理解。</p>
<p>我不再追求所有代码都由自己手写,也不再把“全部交给 AI”当成效率的终点。</p>
<p>真正稳定的状态,是知道什么时候应该讨论,什么时候可以让它执行,什么时候需要 Review,以及什么时候应该停下来,自己亲手实现。</p>
<hr>
<p><del>语音输入太多,口干舌燥了,就先写到这里吧</del></p>