智能体循环 · 工具调用 · 上下文窗口 · CLAUDE.md · checkpoint · 权限模式 · Plan 模式 · 审查 diff
用 AI 编程工具干活:你出需求和验收标准,它跑循环,你审结果
Claude Code 这类工具本身就是一个 agent:模型提议“读这个文件、改那一行、跑一下测试”,外面那层程序(harness)真正去执行,结果送回模型,再决定下一步,直到做完。精华:它能干多好,取决于两件你负责的事。一是它看得见什么:项目文件、CLAUDE.md、你给的上下文。二是它能不能自己验证:有没有一条命令(通常是测试)能告诉它做对了没有。不懂这一点的典型用法,是在网页聊天框里贴代码、再把回答复制回来,这时你自己成了工具执行者;或者一句话甩过去、不审就全盘接受。
全景:一个 FastAPI 请求的一生 · 站末总结(不是链路上的一站,是写这条链路的方式)地图:站 01 · 用 AI 编程工具干活以 Claude Code 官方文档(2026-11)为准
①什么时候用得上:这两天的每一页,都是这样做出来的
站 01 这 7 页,从 uv 到 pytest,每一页的实验代码、实测数字、页面本身,都是 Claude Code 在这个仓库里一轮轮循环做出来的:读 skill 里的要求、建项目、跑实验、写页面、校验 HTML、发布、推送、等上线、清理。你看到的是结果,没看到的是中间那些工具调用。这一页把它摊开,然后轮到你自己来。
20 次提交
2026-11-08 起学习笔记仓库的全部提交,每一次都带着 Co-Authored-By: Claude,新增 15,890 行 实测(git log --shortstat)。
0 个 CLAUDE.md
这个仓库没有 CLAUDE.md。规矩放在两个 skill 里(learn 182 行、reverse-learn 122 行),偏好放在 10 条自动记忆里,每次会话开头加载。
1 个真 bug
pytest 那一页,测试第一次跑就抓到 httpx.ReadTimeout 没接住;修复、重跑、全绿,是一次完整的“收集上下文、动手、验证”。⑤ 就拿它来复盘。
②常见笨办法:要么你当它的手,要么你当它的橡皮图章
你:(贴 main.py 的 60 行)
这里为什么会 500?
它:可能是 fetch 没处理……
你:(复制它的代码,粘回去,
跑测试,再贴报错回去)
你:加个缓存
它:(改了 6 个文件,引入一个新依赖,
顺手重命名了两个函数)
你:看着挺多的,应该没问题吧
git commit -am "add cache"
你:tests/test_api.py 里
test_summary_marks_hung_host 失败了,
httpx.ReadTimeout 没被 fetch 接住。
改 main.py 让它通过,别动测试,
跑 uv run pytest 确认全绿。
它:(跑测试 → 读报错 → 读 main.py
→ 加 2 行 → 再跑 → 10 passed)
你:(看 diff,确认只加了一个 except)
- 笨办法一的问题:模型最擅长的“读一堆文件找关联、跑一下看结果”被你手工替代了,又慢又容易漏。
- 笨办法二的问题:没有验收标准,它只能猜“做完”长什么样;不审 diff,猜错的部分就混进了代码。
- 缺的那一块就是这页的精华:让它看得见(项目、规矩)、让它验证得了(测试、命令),你守住两头:需求和审查。
③工具和路线
| 工具 | 形态 | 它能看到 / 能做 | 适合 |
|---|---|---|---|
| Claude Code | 终端里的 agent(也有桌面、网页、IDE 插件) | 整个项目、终端命令、git 状态、CLAUDE.md 和记忆;能读写文件、跑测试、提交 | 跨多个文件的改动、排查、跑实验,像这两天这样 |
| Cursor | 基于 VS Code 的编辑器 | Tab 补全(按键级);Agent 聊天能改多个文件、跑命令;规则放在 .cursor/rules/*.mdc,也读 AGENTS.md(按文档) | 边写边补全,喜欢在编辑器里看改动 |
| 编辑器补全插件 | 写代码时给下一行建议 | 主要是当前文件和附近上下文 | 写样板代码 |
| 网页聊天 | 对话框 | 只有你贴进去的东西 | 问概念、讨论设计,不适合改项目 |
“这个项目做什么、怎么跑测试?”先看它的理解对不对,不对就纠正,或者写进 CLAUDE.md。
有测试就指定测试;没有就先让它(或你)写一个会失败的测试。大改动先用 Plan 模式出方案。
改代码、跑测试、看结果、再改。中途方向不对就按 Esc 打断,直接说哪里不对。
git diff 逐行看:只改了该改的?有没有顺手多做?测试有没有被改松?
本页以 Claude Code 为主:这两天的页面都是用它做的,你手边就有。Cursor 的思路一样,区别在界面;凡是 Cursor 特有的说法都按官方文档写,本机没有实际操作过。
④背后的机制:一个 agent 循环、一扇上下文窗口、两张安全网
- 模型一次只写一个 token,而且不记得上一次对话:每轮都要把需要的东西重新放进上下文窗口。见站 02 全景 一句话怎么变成模型的回答。
- 工具调用:模型不能自己读文件,它只能输出“我要调用某个工具,参数是什么”,由外面的程序执行,再把结果送回。站 04 会亲手写这一层。
1智能体循环:收集上下文、动手、验证,转到做完为止 站 04 你要亲手写的就是这个
查日志、解析 GC 日志,你的代码执行,结果送回,直到它答得出来。2上下文窗口:它“知道”的一切都得放在这里 ≈ 一张大小有限的工作台
系统说明、CLAUDE.md、自动记忆 MEMORY.md 的前 200 行或 25 KB、各 skill 的简介。
你的每句话、它读过的每个文件、每条命令的输出。读得越多,桌面越满。
自动把对话压成摘要。摘要保留请求和关键代码,早先的细节指令可能丢。可以 /compact 并说明重点保留什么。
长期要遵守的写进 CLAUDE.md(Cursor 是 .cursor/rules 或 AGENTS.md),每次会话都会重新加载,不怕被压缩掉。
每个新会话都从一张空桌子开始,不记得上次聊过什么。这就是这两天每做一页都要先“读 skill、读地图、读全景页”的原因,也是练习 2 要你写 CLAUDE.md 的原因:把每次都要重复说的话,变成它每次都会自己读到的文件。看当前桌面上放了什么:/context。
3两张安全网:checkpoint 管文件,权限模式管动作
checkpoint:改文件之前先拍快照
它每次改文件前都保存一份原样。改坏了,按两次 Esc 回到之前的状态,或者直接说“撤销刚才的改动”。
只管本地文件。推送代码、改数据库、调外部 API、发布页面、删除线上的东西,这些都撤不回来。所以这两天每次 git push 和发布前,都要先确认要推什么。
它和 git 是两回事:checkpoint 是会话里的后悔药,git 提交才是长期记录。练习里每完成一步就提交一次。
权限模式:Shift+Tab 切换
| 模式 | 它可以不问你就做什么 |
|---|---|
| Manual | 什么都要问:改文件、跑命令都先征求同意 |
| Accept edits | 改文件、mkdir、mv 这类不问,其他命令还问 |
| Plan | 只读、只出方案,不改源文件 |
| Auto | 后台有个分类器审查,拦下有风险的动作,其余直接做 |
常用又安全的命令(uv run pytest、git status)可以写进 .claude/settings.json 的允许列表。刚上手建议 Manual 或 Accept edits,大改动先切 Plan。
4交给它还是自己来:两条标准
标准一:能不能自动验证
有测试、有类型检查、有一条命令能说“对”或“不对”,它就能在循环里自己纠错。验证不了的(“这个设计好不好”“这个阈值该设多少”),它只能猜,你得自己判断。
标准二:错了能不能撤回
改本地文件,错了有 checkpoint 和 git;推送、发布、删数据、动生产配置,错了就收不回来。撤不回来的事,要么你亲手做,要么它做之前你逐字看过。
实验台:这件事交给 AI 吗?8 件值班助手里的真事
按上面两条标准判断。这是经验规则,不是实测;不同团队尺度可以不一样,重要的是说得出理由。
先选一件事,再猜:
5为什么这样设计:给模型整个项目和一个终端,而不只是补全下一行
agent:看得见全局,能自己验证Claude Code、Cursor 的 Agent
- 能跨文件找关联、能跑测试看结果,改错了自己发现、自己再改。
- 一个需求可以连着几十次工具调用做完,你只在两头出力。
- 代价:权限大,必须有 checkpoint、权限模式这些安全网;做得多,审查的担子也重。
补全:只看光标附近,猜下一行Tab 补全一类
- 快、打扰少,你始终在掌控每一个字。
- 不知道项目里别处有什么,不会跑测试,对不对全靠你当场判断。
- Cursor 文档写明:项目规则对 Tab 补全不起作用。
决定胜负的约束:写代码最难的不是敲字,而是“找到该改哪儿”和“确认改对了”。补全帮不上这两件事,agent 可以,前提是它能读整个项目、能执行验证命令。所以这类工具都在往“给模型一个终端”的方向走,同时用 checkpoint 和权限把风险关在笼子里。
最少的操作:Claude Code 常用命令 都来自官方文档
| 做什么 | Claude Code | 说明 |
|---|---|---|
| 在项目里开始 | cd 项目 && claude | 它能看到这个目录和子目录 |
| 生成项目说明 | /init | 生成一份 CLAUDE.md 草稿,你再改 |
| 看上下文里有什么 | /context | 桌面占了多少、被什么占了 |
| 主动压缩 | /compact 重点保留 API 的改动 | 告诉它摘要里留什么 |
| 切换模型 | /model | |
| 停下来 | Esc | 取消正在跑的工具调用,等你说话 |
| 撤回文件改动 | 连按两次 Esc | 只管本地文件 |
| 切权限模式 | Shift+Tab | Manual / Accept edits / Plan / Auto |
| 接着上次的会话 | claude --continue / /resume | 新会话不记得旧对话 |
| 检查安装和配置 | /doctor |
⑤跟着做一遍:复盘那次修 bug,每一步看什么
值班助手的代码已经整理成一个独立的 git 仓库:~/claude/oncall-helper(就在这台机器上,一次提交,10 个测试从零跑通 实测)。下面把 pytest 那一页修 bug 的过程拆成 6 步,每步写清“它做了什么”和“你该看什么”。⑥ 的练习就在这个仓库里做。
curl -LsSf https://astral.sh/uv/install.sh | sh # 这台机器上还没装 uv
cd ~/claude/oncall-helper
uv sync # 按 uv.lock 装依赖,含开发依赖 pytest
uv run make_logs.py # 生成 logs/(已被 .gitignore 忽略)
uv run pytest -q # 应该看到 10 passed
claude # 在这个目录里启动 Claude Code
| 步 | 它做了什么 | 你该看什么 |
|---|---|---|
| 1 需求 | 收到:“让 test_summary_marks_hung_host 通过,别动测试,跑 uv run pytest 确认”。 | 需求里有没有“在哪、怎么算做完、什么不许动”。缺哪样,它就会猜哪样。 |
| 2 先看失败 | 跑 pytest -q:1 failed, 9 passed,报错 httpx.ReadTimeout: agent hung。 | 它是不是先复现了问题,而不是一上来就改代码。没复现的修复,等于没验证。 |
| 3 定位 | 看出 fetch 只接住了 asyncio.timeout 抛的 TimeoutError。 | 它说的原因你认不认可。这里要你懂 asyncio 的超时,否则判断不了它对不对。 |
| 4 改 | 在 fetch 里加一个 except httpx.HTTPError,记成这一台出错。 | 改动范围:只动了 main.py 的两行?测试文件一个字没动? |
| 5 验证 | 再跑 pytest -v:10 passed;覆盖率 96%。 | 看到的是真实输出,不是它嘴上说“应该能过了”。 |
| 6 审查、提交 | (你来做)git diff,确认后提交。 | 异常类选得太宽了吗?httpx.HTTPError 会不会把不该吞的错误也吞了?这是你的判断,不是它的。 |
$ git diff main.py
except TimeoutError:
return HostGc(host=host, error="timeout 1s")
+ except httpx.HTTPError as e: # httpx 自己的超时、连不上:也记成这一台出错
+ return HostGc(host=host, error=type(e).__name__)
return parse(host, r.text)
- 审两行,一处,测试没动:范围对。
- 审
httpx.HTTPError是 httpx 所有请求异常的父类,超时、连不上、协议错误都会被记成“这一台出错”。对值班助手合理:一台机器出问题,不能拖垮整个汇总。 - 审但它没处理“日志代理返回 500”这种情况(不抛异常),pytest 页预测题 5 推出过。这就是下一条需求,可以留给练习 4。
⑥刻意练习:6 个练习,由易到难,做对了你自己看得出来
都在 ~/claude/oncall-helper 里做,每做完一个提交一次。练习 1 到 4 是这一站的过关要求,5、6 选做。做完后把仓库推到你的 GitHub,或者直接告诉我做到了哪一步,我来看提交记录。
- 你说
- “这个项目做什么?怎么跑测试?fetch 遇到哪几种情况会把这一台标成出错?”
- 做对了
- 它读了
main.py、tests/、pyproject.toml,说出uv run pytest,并且列出:asyncio1 秒超时、httpx.HTTPError、日志里没有停顿。你拿 ⑤ 对一下,它说漏或说错的地方,就是你要纠正的地方。
- 你做
- 运行
/init生成草稿,然后自己改:测试命令;不要改uv.lock,加依赖要用uv add;测试不许碰网络;提交信息用中文。提交它。 - 做对了
- 退出,重开一个新会话,直接问“怎么跑测试、能不能 pip install”,它不用再读代码就答对,因为 CLAUDE.md 每次都会加载(见 ④-2)。
- 你说
- “在 tests/test_api.py 里用 parametrize 给 minutes 加 0、1、60、61 四个边界,预期 422、200、200、422,再给 /healthz 补一个测试。只改 tests/,跑 pytest 和覆盖率确认。”
- 做对了
git diff --stat只有tests/test_api.py;pytest显示 15 passed;覆盖率报告里第 85 行(healthz)不再列在 Missing 里。
- 你做
Shift+Tab切到 Plan 模式,说:“日志代理返回非 200 时,这一台要标成出错,而不是 no pauses;超时秒数要能在测试里改小。先给方案。”审方案,满意了再切回去让它做。- 做对了
- Plan 模式下它只读、只出方案,没有改任何文件;动手后新增的测试里,“日志代理返回 500”那一台的 error 不是
no pauses;超时测试不到 0.2 秒;全部测试通过。
- 你说
- “加个缓存。”看它做了什么,然后连按两次
Esc撤回。再改写成:“同一个 service 和 minutes,30 秒内重复请求直接返回上次结果;只缓存成功的;加测试。” - 做对了
- 你能说出第一次它自己“猜”了哪些东西(缓存什么、多久、放哪、出错时缓不缓存),第二次这些都被你的需求定死了。撤回后
git status是干净的。
- 你做
- 用 Cursor 打开仓库,在
.cursor/rules/下写一条.mdc规则(或者直接放一个AGENTS.md),用它的 Agent 做练习 3 的同类改动。 - 做对了
- 写一段对比:哪个更顺手、哪个审查改动更方便、规则文件的写法差在哪。这部分本页是按 Cursor 文档写的,你的体验比我的描述更可靠。
和 AI 结对时,团队里的几条约定
没有测试的代码,先让它补测试并看着测试失败一次。
它说“改好了”,其实没人验证过。
在哪、要什么结果、什么不许动、怎么算做完。
它替你猜,猜的方向未必是你要的。
提交信息里写的是你认可的改动;看不懂的改动不提交,先问它为什么。
不理解的代码进了仓库,出事时没人说得清。
推送、发布、删数据、改生产配置,执行前逐字看一遍。
checkpoint 管不到的地方出事。
CLAUDE.md 提交进仓库,团队共享;个人偏好放用户级配置。
每次会话重新解释一遍,压缩后又忘。
⑤ 第 3、6 步全靠你懂 asyncio 和异常层级才审得了。
“看起来对”的错误代码。
下一圈
- Hooks:每次改完文件自动跑格式化和测试,把“验证”从约定变成机制。
- Skills:把这两天的 learn、reverse-learn 当范例,给值班助手写一个“排查 Full GC”的 skill(站 07)。
- Subagents:把“查日志、查指标、查笔记”分给三个子 agent 并行(站 08 的预演)。
- MCP:把值班助手的接口接进 Claude Code,让它直接调用(站 07)。
- 用 git worktree 同时开两个会话,各改一个分支。
↺回到⑤:拿你自己的那几次,和 ⑤ 对一对
做完练习 3、4 后,翻回 ⑤ 的表格逐行对照:你的需求里四样都有吗?它先复现了吗?你看 diff 时发现过什么?把发现写进 CLAUDE.md,下一次就不用再说。
1. 用一句话说出这一页的精华。
AI 编程工具是一个 agent:模型提议工具调用、外面的程序执行、结果送回,循环到做完;它能干多好,取决于它看得见什么(项目、CLAUDE.md)和能不能自己验证(测试、命令),你守住需求和审查两头。
2. 在网页聊天里贴代码、复制回答,痛在哪?
模型看不到项目、跑不了测试,读文件、执行命令、贴结果全由你手工完成,你成了工具执行者;而且它没法自己验证,对不对全靠你当场判断。
3. 为什么长期规矩要写进 CLAUDE.md,而不是在对话开头说一遍?是 ④ 哪条?
④-2:每个新会话都从空的上下文开始,长对话还会被压缩成摘要,早先的细节指令可能丢;CLAUDE.md 每次会话开头都会加载。
4. 预测:你让它“修好这个 bug”,但项目里没有任何测试。它最可能怎么“验证”?会出什么问题?
它可能只是读一遍改过的代码就说“应该好了”,或者自己临时写个脚本跑一下。没有可重复的测试,修复的正确性只能靠你判断,下次有人改动时也不会有人发现它又坏了。所以先补一个会失败的测试。
从 ④-4 的标准一(能不能自动验证)推出。
5. 预测:在 Accept edits 模式下,它改坏了 main.py 又执行了 git push。按两次 Esc 能撤回什么,撤不回什么?
能撤回本地 main.py 的改动;撤不回已经推到远端的提交(还得另做一次提交或回滚)。而且 Accept edits 模式下 git push 这种命令本来就会先问你,按了同意就是你的决定。
从 ④-3:checkpoint 只管本地文件,权限模式管动作。
6. 放回全景:站 01 的 10 站里,哪些是这次“和 AI 结对”时你最需要自己懂的?为什么?
第 5~7 站(asyncio)和第 8 站(解析和异常)。⑤ 里那个 bug 的根源是“超时有两种、异常类不同”,看懂它要懂事件循环怎么超时、httpx 的异常层级;审查 except httpx.HTTPError 吞得太宽还是正好,也要懂第 8 站解析失败时会怎样。工具能替你写代码,但审查需要你懂原理,这也是前面 7 页要一页页讲透的原因。
见 全景第 7 站。
下一步:站 01 的 8 个知识点到这里都有页了。做完练习 1~4 以后,说“回到全景”,合上页面把站 01 的 10 站讲给我听。