跳转到内容

Claude Code 的工作原理:代理循环与工具调用

「它刚才一连读了五个文件、跑了两遍测试,最后才回我一句话。这中间到底发生了什么?」

上一章你已跑通会话,并熟悉了 Slash 命令 面板。本章把那种「它自己在干活」的直觉,换成可核对的一套机制:代理循环工具权限。读完后,你能根据终端里的工具名和权限弹窗,判断 Agent 处在循环的哪一步,以及为什么会被拦住或停下来。

官方机制说明见 How the agent loop worksHow Claude Code works。CLI 与 Agent SDK 共用同一套循环;下文以终端会话为主,并标注与 SDK 选项的对应关系。


用最直白的话说:你给出意图,模型在每一轮里决定要不要调用工具;若要,运行时执行工具并把结果塞回上下文,再进入下一轮,直到模型只回复文字、不再要工具为止。

这和「聊一句答一句」的网页聊天不同。网页聊天没有把你的 repo 当工作区,也不能替你执行 npm test。Claude Code 在循环里反复 观察 → 行动 → 读结果 → 再观察,直到任务完成、触达限制,或你中断。

你输入目标
模型评估当前上下文(历史、CLAUDE.md、工具结果)
输出:纯文字 和/或 一个或多个工具调用
若有工具调用 → 运行时执行 → 工具结果写回上下文
重复,直到本轮没有工具调用
把最终文字呈现给你(你可审查 diff、继续追问)

一轮指模型发出带工具调用的回复,加上这些工具执行完毕、结果写回上下文,尚未开始下一次模型推理的完整过程。简单问题可能一两轮结束;重构加测可能几十轮。官方把「只有工具调用、没有最终纯文字」的往返计入 max_turns 上限;见 Turns and budget


假设你输入:修复 auth.ts 里导致测试失败的问题,改完跑测试确认。

下面是一种典型顺序,名称与 Tools reference 一致:

轮次模型可能做的事你终端里会看到
1调用 Bashnpm test权限弹窗或已预授权的 Bash
2调用 Readauth.ts、测试文件通常无弹窗
3调用 Edit 改源码,再 Bash 重跑测试Edit 与 Bash 可能各弹一次
末轮只输出文字,不再要工具总结:修了哪、测试是否通过

要点有三条:

  1. 每一轮的决定权在模型,但能不能执行由权限规则、模式和你的确认决定。
  2. 工具输出会留在上下文里,所以后面轮次会基于真实测试输出改代码,而不是凭空猜。
  3. 你看到的「最终回复」只是循环的出口;中间多轮工具调用可能并不逐条展开成聊天段落,但会驱动同一条任务链。

动手: 在已有测试的项目里输入:只读方式列出 src 下所有 .ts 文件,不要改任何文件。 观察是否主要出现 GlobGrep,且很少出现 Edit。再输入:运行测试并告诉我失败用例的文件名。 对比 Bash 是否出现。能区分「只读探索」和「要执行命令」两类轮次即可。


内置工具:能做什么、要不要你点头

Section titled “内置工具:能做什么、要不要你点头”

Claude Code 通过具名工具操作环境,而不是只在聊天框里贴代码。工具名与权限规则、Hook、子代理配置里写的是同一套字符串。

工具作用默认是否要批准
Read读文件内容
Glob按文件名模式找文件
Grep在文件内容里搜模式
Edit精确替换片段改文件
Write创建或整文件覆盖
Bash跑 shell 命令
WebSearch搜索网络
WebFetch抓取指定 URL
Agent派生子代理处理子任务启动本身不批;子代理内部工具仍受权限约束

完整列表与细节行为见 Tools reference。还有 EnterPlanModeSkill、MCP 相关工具等,会在后续章节展开;本章只需记住:读多写少时弹窗少,一改文件或一跑命令就容易弹窗。

ReadGrepGlob 不触发编辑类批准,但并非「免费」。大仓库里广撒网式搜索会把大量路径和片段塞进上下文,带来费用和变慢。你在 第一个会话 里学过的 @ 引用和 /compact,就是在管这件事。

官方说明:只读类工具可并行;会改状态的工具顺序执行,避免冲突。你在终端里若看到短时间多次 Read,属于正常优化。


你无法逐步单步调试模型的内部推理,但可以观察输入侧输出侧,建立稳定预期。

输入侧主要包括:

  • 你的当前与历史消息
  • 项目中的 CLAUDE.md 等说明
  • 工作区文件结构与会话内已读内容
  • 各轮工具的返回:测试日志、grep 结果、编辑成功或失败信息

输出侧每一轮只能是:

  • 纯自然语言
  • 一个或多个工具调用
  • 两者兼有

模型根据「目标是否达成、还缺什么证据」选择工具。例如测试仍失败时会再 Read 或再 Edit;若 Editold_string 不匹配失败,官方 Edit 行为 要求先 Read 且磁盘未变,模型通常会加长匹配片段或先重新 Read。

你能施加的影响:

手段影响的是
把目标、约束、验收写清楚模型倾向选哪些工具、何时停
CLAUDE.md默认习惯,例如先跑哪条测试命令
/permissions 与 settings工具能否执行,与模型想不想无关
拒绝某次 Bash该轮工具结果变成「被拒绝」,模型常改道或向你说明

重要边界:提示词和 CLAUDE.md 管的是「它想做什么」;权限管的是「允许做什么」。CLAUDE.md 里写「禁止删库」不能代替 deny 规则。见 Configure permissions


结束方式含义你可怎么做
自然结束模型认为目标完成,末轮无工具调用审查 diff 与测试结果
你中断Esc 或停止当前生成/resume 或说明从哪继续
权限拒绝关键工具未获批,模型无法继续批准、改规则,或缩小任务
预算或轮次上限SDK 场景下 max_turnsmax_budget_usdCLI 日常较少遇;自动化时要设
上下文撑满/compact/clear长任务定期压缩

「跑偏」往往不是循环坏了,而是停止条件不清晰:你说「优化项目」,模型缺少可验证的完成信号,就会一直探索。把验收写成可运行命令,循环更容易在合适时刻停下。


官方权限文档 把工具分成三类:

类型例子首次使用
只读Read、Grep、Glob一般不弹窗
改文件Edit、Write需批准;可选「本会话不再问」
执行Bash、WebFetch 等需批准;可对命令模式做持久 allow

在设置文件或 /permissions 里使用 ToolTool(specifier)

{
"permissions": {
"allow": [
"Bash(npm run test *)",
"Bash(git status *)",
"Read"
],
"deny": [
"Bash(git push *)",
"Read(./.env)"
],
"ask": [
"Bash(curl *)"
]
}
}

评估顺序:deny → ask → allow,先匹配先生效。Bash(npm run *) 只匹配以该前缀开头的命令;复合命令 cmd1 && cmd2 会对每一段子命令分别匹配。

通过 /config 或 settings 的 defaultMode 切换整体策略:

模式行为适用
default未在 allow 列表中的敏感操作逐个问日常开发
acceptEdits自动接受工作区内编辑类操作信任度高的迭代
plan只读探索,不改源码Plan Mode 配合
dontAsk未预批准的一律拒绝CI、严格环境
bypassPermissions跳过提示仅隔离容器;有管理员可禁用

bypassPermissions 仍会拦截删根目录等极端命令,且不应在含密钥的本机长期使用。

动手: 运行 /permissions,为 Bash(npm run test *) 添加 allow。再让 Agent 跑测试,确认弹窗消失。然后 deny 一条你绝不会点的命令,看模型是否改道。


权限是应用层闸门。还有几层值得单独记住:

沙箱在操作系统层限制 Bash 进程的路径与网络,与 allow/deny 叠加使用。机制、/sandbox 开关与环境选型见 沙箱隔离机制

允许 Bash 时,模型仍可能用 curl 访问任意 URL,不限于 WebFetch 的域名规则。若只要查文档,可 deny 通用 curl,仅 allow WebFetch(domain:...)

Hooks 在工具执行前后插入你的脚本,可做格式化、审计或二次拒绝。检查顺序上 Hook 早于 allow 规则,适合组织级策略。

子代理在独立上下文里跑完再回报一行结果;父会话看不到中间每一步。后台子代理不会再弹权限窗,只能用会话里已授予的权限,未批准的调用会被自动拒绝。委派大任务前,先想清楚权限是否过宽。


开发服务器、watch 测试等长时间进程,模型可用 Bash 的 run_in_background 挂到后台,主对话继续。列出与停止用 /tasks,与 Bash 工具行为 一致。

注意:

  • 默认单条 Bash 有约两分钟超时,长任务应显式放后台或拆命令。
  • 输出过长会写入会话目录中的文件,模型通过路径再读,你在 /tasks 里也能跟进。

动手: 让 Agent「在后台启动项目的 dev 脚本,告诉我任务 ID」。用 /tasks 查看状态,再让它停掉。确认你理解「前台一轮对话」与「后台进程」是两条线。


症状常见原因下一步
一直 Read 不改目标含糊或权限只给了只读写清验收;检查是否在 plan 模式
Edit 反复失败文件已被外部修改或未 Read让 Agent 先 Read;你本地勿并行改同一文件
测试通过它仍继续未定义「完成」/goal 写可验证终点,或明确「测试全绿即可停」
突然变「笨」上下文接近上限/context,必要时 /compact
子代理说做不到后台权限不足改 allow 规则或改前台执行
批准了仍危险过于宽泛的 Bash(*)收窄前缀;敏感路径写 deny

决策边界:何时信循环、何时加模式

Section titled “决策边界:何时信循环、何时加模式”
场景直接循环即可建议加 Plan Mode 或拆任务
单文件小改、明确测试
跨多模块重构可,但要写阶段验收
不熟代码库摸底只读探索先 plan 再执行
生产数据、支付、鉴权严格 deny + 人工审查每步 Edit

循环能力强,不等于每个任务都应一次扔给它。先只读弄清结构,再写改代码,通常比边搜边改更省 token,也更少误改。


合上文档,试着回答:

  1. 「一轮」和「一整次会话」差在哪?
  2. 为什么 CLAUDE.md 写「不要 push」仍可能 push?
  3. 只读工具和 Edit 在权限上有何本质区别?
  4. 子代理后台跑时,权限弹窗为什么可能不再出现?

有卡壳,回到对应小节重做「动手」。

自检清单:

  • 能根据工具名判断本轮是探索还是执行
  • /permissions 里加过一条 allow 和一条 deny
  • 见过至少一次自然结束与一次因拒绝而改道
  • 知道 /tasks 用于查看后台命令

上一章:多平台运行环境全览 · 下一章:Plan Mode——在代理循环之上,把「想」和「做」拆开:先只读规划,再经你批准进入执行,减少灾难性乱改。