HomeArchiveBlog


Original contents are licensed under CC BY-NC 4.0. All rights reserved © 2026 Kai.
Back to Archives
Basic Skills: Agentic Coding

一篇面向初学者的 Agentic Coding 入门文档, 介绍 Context Window, KV Cache, MCP, Skills, Tool Calling, Plan Mode, 上下文管理和实际协作方法。

Wed Apr 29 2026
Wed Apr 29 2026
AgentsAI DevelopmentAgentic Coding
On this page
  • Basic Skills: Agentic Coding
    • 模型的Context Window
      • ~200K vs. 1M Context
    • KV Cache
      • 什么是 KV Cache
      • 缓存读和缓存写
      • 5m/1h Cache
    • MCP (Model Context Protocol)
    • Skills
    • 工具调用 (Tool Calling)
    • 关于模型的思考长度
    • 使用 AGENTS.md
    • 学会使用 Plan Mode
    • 正确的 Prompt 方式
    • 应该如何管理上下文
      • 自动压缩与手动压缩
      • 避免直接读入大文件
      • 遵循同一个主题
      • 记录 Progress
      • 使用 Subagents
      • 使用 Rewind 和 Git
    • 使用 Skills
      • Skills 的本质
      • Skills vs. AGENTS.md
      • 创建 Skills
    • 权限管理
      • 沙盒机制
      • 避免完全开放权限

Basic Skills: Agentic Coding

很难想象在 2026 年初的极短时间内, LLM 的演化速度会如此之快. 在 2026 年四月份的 LLM, 和去年年底那一会的 LLM 似乎已经是两种不同的东西了. 如果我的感觉没错, 应该是 Claude Opus 4.6 引发了 Agentic Coding 的热潮. 好像就是一瞬间各种 CLI 工具, 各种 IDE 插件, 各种在线平台都开始集成 Agentic Coding 的功能, 到处都是铺天盖地的宣传. 模型的应用方式突然之间就从还只是 Chatbot, 变成了能独立迭代十几分钟甚至几个小时的 Agent 了.

不过 Agentic Coding 突然火爆, 我个人并不觉得是 LLM 本身的能力提升很多, 也就是模型本身的能力, 或者说"智力水平"并没有发生质的飞跃. 但是 Agentic Coding 涉及到的工程技术, 比如 MCP, 上下文管理, Tool Calling, Subagents 的设计和管理, 是真真切切地发生了质的飞跃. 所以我更愿意把 LLM 编程能力的提升看成是各家公司在工程应用上的大爆发导致的.

言归正传, 无论承认与否, Agentic Coding 已经成为不可或缺的工具了. 本文希望介绍一些 Agentic Coding 里面常用的技巧, 并适当附带一些简单的原理解释, 希望能够帮助 beginners 更快地用好 Agents.

声明

即使 Agents 的能力很强大, 但我仍然不认为你可以忽视基本功. 用好 Agents 的前提仍然是你有一定的 Coding 能力和经验. 不难发现的一点是本身 Coding 能力越强 (通常表明逻辑组织能力越强) 的人用 Agents 写出来的代码质量会越高, 而且 Agents 在执行的过程中不容易跑偏方向. 如果你的 Coding 基础薄弱, 或者基本功极度欠缺, 上来就直接依赖 Agents 写代码, 甚至让 Agents 包办一切 (比如 Git 提交, PR, 跑各种测试/工具), 那和"文科生转码"没有本质区别.

模型的Context Window

Context Window 可以理解成模型一次工作时能摊在桌面上的材料. 你和模型的对话, 系统指令, 项目说明, 工具返回的文件内容, 命令输出, 错误日志, 以及之前的讨论都会占用这张桌子. 模型并不是像人一样长期记住所有细节, 它是在每次生成回答时读取当前上下文, 再基于这些材料继续推理和行动.

这件事对 Agentic Coding 非常重要. 传统 Chatbot 的上下文通常只是一段聊天记录, 但 Coding Agent 的上下文里会混入大量代码, diff, 测试输出, 目录结构和工具调用结果. 如果上下文组织得好, 模型就像拿到了清晰的项目地图; 如果上下文混乱, 它就像在一张堆满旧草稿, 错误日志和无关文件的桌子上找线索.

很多初学者会误以为只要 Context Window 足够大, 就可以把整个项目塞进去, 然后让模型自动理解一切. 这通常不是最好的做法. 上下文窗口越大, 可放入的内容越多, 但模型仍然需要在这些内容里分辨什么重要, 什么过时, 什么只是噪声. 对 Agent 来说, "给足够相关的上下文"通常比"给尽可能多的上下文"更重要.

~200K vs. 1M Context

现在很多模型已经支持几十万甚至上百万 token 的上下文. 这当然是巨大的进步, 因为它允许模型一次看到更多文件, 更长日志和更完整的对话历史. 对大型重构, 复杂论文阅读, 长文档生成, 多模块代码理解来说, 大上下文能明显降低来回找材料的成本.

但 200K context 和 1M context 的差别, 不应该简单理解成"1M 一定更聪明". Context Window 更像桌子面积, 而不是大脑智商. 桌子变大以后, 你可以摊开更多资料, 但如果资料本身没有整理, 重要信息被埋在一堆无关输出里, 模型仍然可能漏看关键点.

200K context 对大多数日常 Coding Agent 任务已经很够用. 例如一个中小型 feature, 一次 bug fix, 一组测试失败排查, 通常只需要读取相关模块, 测试文件, 错误日志和项目约定. 1M context 更适合那些必须跨越大量材料的任务, 例如迁移整个框架, 读完整设计文档, 对比多个大文件版本, 或者让 Agent 在长时间任务中保留更多历史.

更大的上下文还会带来实际成本. 它可能更慢, 更贵, 也更容易把早期已经过时的信息留在对话里. 如果 Agent 前面走过一条错误路线, 这些错误推理和错误命令也会留在上下文中. 后续模型虽然可以纠正, 但它仍然需要从旧信息里判断哪些应该保留, 哪些应该抛弃. 所以, 使用大上下文时更要主动管理信息质量.

比较好的习惯是把上下文当成工作台来整理. 需要的文件就读进来, 不需要的命令输出不要反复贴, 关键决策要及时总结, 已经废弃的思路要明确标记. 这样即使窗口不是最大, Agent 也能稳定工作.

更严重的问题是, 现在无论是 OpenAI 还是 Anthropic, 又或者是 Google, 尽管宣称模型支持百万上下文, 但超出 ~200K 的部分召回率通常下滑非常严重, 而且超出部分的计费速率也可能翻倍. 这就意味着, 在实际使用中, 1M 上下文的成本可能远高于 200K 上下文, 同时它的效果提升也不一定成正比.

KV Cache

KV Cache 是理解现代 LLM 成本和速度时很有用的概念. 它和你平时说的"模型记忆"不是一回事. 它不是让模型永久记住你的项目, 而是在一次或一段连续请求里, 复用模型已经处理过的前缀上下文.

可以把模型读取上下文想象成读一本很长的书. 如果每次提问都要从第一页重新读到最后一页, 成本会很高. KV Cache 的思路是: 对于前面那些没有变化的页, 模型已经算过一遍中间结果, 下一次请求可以复用这些中间结果, 只继续处理新加的内容.

什么是 KV Cache

Transformer 在生成文本时, 会把输入 token 转换成一系列内部表示. 在注意力机制里, 每个 token 会产生 Key, Value 等中间结果. 后面的 token 需要参考前面的 token, 因此这些 Key/Value 会被反复用到. KV Cache 就是把这些已经计算过的 Key/Value 保存起来, 避免下次重复计算完全相同的前缀.

从使用者角度看, 你不需要手动管理这些矩阵. 你只需要理解一个结论: 如果一大段上下文在多次请求里保持不变, 平台就有机会缓存它; 如果你总是在前面插入, 删除或修改内容, 缓存命中就会变差.

在 Agentic Coding 里, 这意味着稳定的系统指令, 项目规则, AGENTS.md, 工具说明和长文档前缀更容易被缓存. 而频繁变化的命令输出, 最新 diff, 用户新消息一般出现在上下文后部, 它们会成为每次需要新处理的部分.

缓存读和缓存写

缓存写指的是模型第一次处理某段可缓存上下文时, 平台把对应的中间结果写入缓存. 这一步通常不能省, 因为模型必须先真正读过这段内容. 缓存读指的是后续请求再次使用相同前缀时, 平台直接复用之前写好的缓存.

一个简化例子是这样的:

第一次请求:
系统指令 + AGENTS.md + 项目说明 + 用户问题
前面的大段稳定内容需要完整计算, 然后写入缓存.

第二次请求:
系统指令 + AGENTS.md + 项目说明 + 新的工具输出 + 用户补充
如果前面的稳定内容没有变, 就可以从缓存读取.

缓存通常要求"前缀一致". 也就是说, 如果你在上下文最前面改了一个字, 后面的缓存可能都无法直接复用. 这就像一本书的页码和内容整体错位了, 原来做好的书签不一定还能指向同一段文字.

这也是为什么很多 Agent 平台会把长期稳定的说明放在前面, 把实时变化的对话和工具输出放在后面. 这不是单纯的排版习惯, 而是为了让缓存更容易命中, 也让模型更容易区分长期规则和当前任务材料.

5m/1h Cache

如果你使用 API 服务, 比如 Amazon Bedrock, 会发现一些模型服务会提供不同有效期的上下文缓存, 常见说法里会看到 5 分钟 cache 或 1 小时 cache 之类的选项. 不同平台的具体计费和实现不完全一样, 但它们背后的取舍大致相同: 缓存保留时间越长, 越适合长时间连续工作的 Agent; 缓存写入成本或资源占用也可能更高.

5 分钟缓存适合短对话和快速迭代. 例如你让 Agent 修改一个函数, 跑一次测试, 再根据失败继续修, 这些请求往往在几分钟内连续发生. 只要上下文前缀稳定, 缓存就能减少重复读取成本.

1 小时缓存更适合长任务. 例如 Agent 需要在一个较大项目里持续工作, 中间多次读文件, 改代码, 跑测试, 总结进度. 如果稳定的项目说明和长上下文能在一小时内复用, 整体体验会更好.

不过缓存不是上下文管理的替代品. 缓存只能让重复计算更便宜, 不能让混乱的信息变得清晰. 如果你把大量无关文件和旧错误日志一直留在上下文里, 即使缓存命中了, 模型仍然需要在混乱材料中工作.

MCP (Model Context Protocol)

MCP 全称是 Model Context Protocol. 它可以理解成 Agent 和外部世界之间的一种标准接口. 在没有 MCP 或类似机制时, 不同工具需要为不同 Agent 单独适配: 一个工具给 IDE 插件写一套接口, 给 CLI Agent 写一套接口, 给桌面客户端再写一套接口. MCP 的目标是把这件事标准化, 让工具提供方按照统一协议暴露能力, Agent 客户端按照统一方式调用这些能力.

从结构上看, MCP 通常包括 MCP Client 和 MCP Server. Client 在 Agent 所在的一侧, 负责把模型想做的动作转换成协议请求. Server 在工具或数据源那一侧, 负责暴露可调用的工具, 可读取的资源, 以及某些可复用提示模板.

Rendering diagram...

对初学者来说, MCP 最重要的意义是让 Agent 不只是在聊天框里猜答案. 它可以真正去读 GitHub issue, 查数据库 schema, 打开浏览器, 搜索文档, 或访问某个内部系统. 但这也意味着权限边界变得更重要. 一个能读数据库的 Agent, 能造成的问题也比一个只能聊天的模型更大.

MCP 不是魔法记忆, 也不是让模型自动懂所有工具. MCP Server 只是把能力暴露出来, 模型仍然需要根据任务决定什么时候调用, 传什么参数, 如何解释返回结果. 如果工具描述写得含糊, 权限设计混乱, 或返回结果太大太脏, Agent 仍然会用不好.

一个好的 MCP 工具应该有清晰的名字, 明确的参数, 可预测的返回结果, 合理的权限限制, 以及足够具体的错误信息. 对 Coding Agent 来说, 这类工具可以把很多原本靠复制粘贴完成的动作变成可审计, 可重复, 可组合的工具调用.

Skills

Skills 可以理解成给 Agent 安装的"专业手册". 一个通用模型当然知道很多东西, 但它未必知道你的团队怎么写 PR 描述, 某个框架在这个项目里有什么约定, 处理某类文件时应该先跑什么脚本, 或者某个工作流有哪些固定步骤. Skill 就是把这些经验整理成可被 Agent 按需加载的局部知识.

和把所有说明都塞进系统提示不同, Skill 通常是可发现, 可选择, 可按需读取的. 当任务涉及某个领域时, Agent 先加载对应 Skill, 再按照里面的流程做事. 例如处理 PowerPoint 文件可以有一个演示文稿 Skill, 处理 GitHub PR 评论可以有一个 GitHub Review Skill, 生成图片可以有一个图像 Skill.

Skill 的价值不在于写很多漂亮说明, 而在于把重复工作流程固化下来. 如果你每次都要提醒 Agent "先检查文件结构, 再运行这个脚本, 最后验证输出", 这就适合变成 Skill. 它像一张放在工具箱里的操作卡片, 只有需要时才拿出来, 不会一直占用主上下文.

工具调用 (Tool Calling)

Tool Calling 是 Agentic Coding 从"会聊天"变成"会做事"的关键. 普通 Chatbot 只能生成文本, 它可以告诉你应该运行什么命令, 但不能亲自运行. Coding Agent 通过 Tool Calling 可以读文件, 搜索代码, 执行测试, 修改文件, 打开浏览器, 甚至调用 GitHub 或数据库工具.

一个典型 Agent 循环大概是:

理解任务 -> 决定下一步 -> 调用工具 -> 观察结果 -> 更新判断 -> 继续行动

例如你说"修复这个测试失败", 一个成熟的 Agent 不应该直接凭空改代码. 它应该先看失败日志, 定位测试文件, 搜索相关实现, 理解现有模式, 做最小修改, 再重新运行相关测试. 这个过程里, 模型的文本推理和工具调用是交替进行的.

工具调用也带来风险. 如果 Agent 能运行 shell 命令, 它就可能误删文件, 安装奇怪依赖, 或运行耗时很长的任务. 如果 Agent 能改代码, 它就可能改到无关文件. 因此好的 Agent 平台通常会有 sandbox, 权限请求, 工具白名单, diff 预览和人工确认.

作为使用者, 你也要学会给工具调用设边界. 比如你可以明确说"只修改这个文件", "不要提交 git commit", "先给计划, 不要动代码", "只运行相关测试", "不要联网". 这些边界能显著减少 Agent 跑偏的概率.

让 Agent 使用工具时, 最差的提示是只说"帮我看看". 更好的提示会给出目标, 范围和验证方式。例如:

请修复 `src/parser.ts` 里导致 `parser.test.ts` 失败的问题.
改动范围尽量限制在 parser 模块.
完成后运行相关测试, 不要修改快照, 不要提交 commit.

这段提示没有规定具体实现, 但它给了 Agent 清晰的工作边界和验收方式.

关于模型的思考长度

很多 Agent 平台会让你选择 reasoning effort, thinking budget 或类似选项. 它们控制的是模型在回答或行动前投入多少推理资源. 对 Coding Agent 来说, 思考长度不是越长越好, 而是要和任务难度匹配.

简单任务适合较短思考. 例如改一个文案, 补一个小函数, 调整一处类型错误, 或解释一段代码. 这类任务如果让模型过度思考, 反而可能引入不必要的抽象和改动.

复杂任务适合较长思考. 例如跨模块 bug, 架构迁移, 并发问题, 性能瓶颈, 安全边界, 或大范围测试失败. 这类任务需要模型在行动前建立更完整的因果链, 否则它很容易只修表面错误.

有一个实用判断方法: 如果错误信息已经明确指向一行代码, 可以用较低思考; 如果你自己也不确定问题在哪, 或者改错会影响多个模块, 就应该提高思考预算. 但即便提高思考预算, 也不应该鼓励 Agent 空想太久. 对编程任务来说, 最可靠的信息往往来自代码和测试, 不是来自模型脑补.

还要注意, 你不需要让模型展示所有内部推理过程. 更好的方式是让它输出可检查的计划, 关键假设, 修改范围和验证结果. 这些内容足够你判断它是否走在正确方向上, 同时不会把对话变成冗长的思维流水账.

使用 AGENTS.md

AGENTS.md 是写给 Coding Agent 的项目说明书. 它通常放在仓库根目录, 用来告诉 Agent 这个项目的基本规则, 例如使用什么包管理器, 如何运行测试, 代码风格是什么, 哪些目录不要碰, 提交信息怎么写, 文档怎么生成, 以及团队有哪些约定.

它和普通 README 的读者不同. README 主要写给人看, 介绍项目是什么, 怎么安装, 怎么使用. AGENTS.md 主要写给 Agent 看, 重点是让 Agent 在仓库里做改动时少走弯路.

一个好的 AGENTS.md 不需要很长. 它应该包含那些 Agent 如果不知道就容易犯错, 或者会浪费上下文去搜索正确做法的信息. 最起码应该包含你的项目应该怎么构建, 怎么运行起来, 以及一些代码风格和提交规范. 比如你需要用到某个工具进行构建, 但没放在任何地方向 Agents 说明, Agents 就会各种猜应该怎么构建, 浪费大量上下文和时间去试错. 尤其对于一些小众的软件, 比如 EDA 工具, 或者内部系统, 如果不指定构建和测试流程, Agent 可能连猜都没法猜.

示例:

# AGENTS.md

## Building
- Always run `conda activate project` before building or running tests
- Run `pip install -v -e .` to build the full project
- Run `ninja -C build [target]` to build specific targets

## Code style
- Make small, targeted diffs rather than large refactors, and always be concise
- Prefer general solutions instead of one-off `if/else` patches
- Use Modern C++ features and best practices in C++ code
- Use `assert` to enforce invariants and assumptions that should always hold by design.
- Avoid redundant validation checks, defensive programming patterns.

## Don'ts
- Do not modify repository structure without approval
- Do not install system packages without explicit user confirmation

AGENTS.md 最直接的价值是减少重复提醒. 如果你每次开新对话都要告诉 Agent 同一批规则, 这些规则就应该沉淀进 AGENTS.md. 但不要把整本文档都塞进去.

需要注意的是, AGENTS.md 也会算在模型的上下文里. 所以应该非常简明扼要 (比如分点列短句说明). 不要把什么 Motivation, 背景都放进去, 那没有一点作用.

学会使用 Plan Mode

Plan Mode 的核心作用是先对齐方案, 再动手执行. 在普通模式下, 你提出需求后 Agent 可能会立刻读文件, 改代码, 跑测试. 这对小任务很高效, 但对边界不清的大任务可能有风险. Plan Mode 会让 Agent 先分析任务, 梳理步骤, 暴露假设和风险, 等方案清楚后再进入实现.

当你不确定要怎么改, 或者担心 Agent 误解需求时, Plan Mode 很有用. 例如你要修改构建流程, 或修一个难以复现的 bug, 直接让 Agent 开始改可能会越走越偏. 先让它调查代码结构, 提出方案, 标出会改哪些文件, 说明如何验证, 你就能在成本较低的时候纠正方向.

Plan Mode 不是让 Agent 写一大段空泛计划. 好计划应该具体到工作边界. 它应该说明要先读哪些模块, 为什么这些模块相关, 预计修改哪些地方, 哪些行为不应该改变, 完成后跑什么测试. 如果计划里全是"分析代码, 实现功能, 测试验证"这种套话, 那基本没有价值.

一个比较好的 Plan Mode 提示是:

先不要改代码. 请先阅读相关文件, 给出实现计划.
计划里说明你认为需要修改哪些文件, 哪些行为保持不变, 以及如何验证.
如果需求里有歧义, 先指出来.

等计划合理后, 再让 Agent 执行. 这样既保留了 Agent 自动化能力, 又避免它在你还没看清方向时大规模改动项目.

现在的很多 CLI 工具比如 Codex CLI, Claude Code 都能让模型向你提问. 尤其对于没有想清楚具体该怎么做的需求, 你应该鼓励 Agent 多问几个问题, 直到它的方案足够清晰. 不论是什么模型, 都需要足够清晰的输入才能产出高质量的输出, 而 Plan Mode 就是用来弥补你的不清晰描述和模型理解之间的 Gap.

正确的 Prompt 方式

Agentic Coding 里的 Prompt 不是咒语, 也不是越长越好. 它更像你给一个工程师分配任务时写的工单. 一个好的工单不会只说"帮我优化一下", 而会说明现在的问题是什么, 期望结果是什么, 哪些地方可以改, 哪些地方不要改, 做完以后怎么判断成功. Prompt 的质量会直接影响 Agent 的行动路径, 因为 Agent 并不是只回答一句话, 它会根据你的描述决定读哪些文件, 调用哪些工具, 做多大范围的修改, 以及什么时候停下来.

最差的 Prompt 通常过于模糊. 例如:

帮我看看这个项目有什么问题.

这句话对人类同事也不够清楚. 它没有说明你关心的是 bug, 性能, 架构, 测试, UI, 依赖安全, 还是代码风格. Agent 收到这种请求以后, 只能自己猜范围. 一旦它猜错, 后续读文件, 做计划, 甚至改代码都会偏离你的真实目标.

又或者是

@claude, 阅读这个project的所有代码, 帮我写一份文档

😅 上下文窗口直接就爆炸了, 而且 Agent 也不知道你到底想要什么样的文档. 是 API 文档? 是设计文档? 是用户指南? 是开发者指南? 你想让 Agent 读多少代码? 读哪些模块? 读测试吗? 读历史 commit 吗? 这些细节都会影响 Agent 的工作路径.

更好的写法是把任务拆成几个信息: 目标, 背景, 范围, 限制和验收方式. 例如:

请调查登录页面偶尔无法跳转的问题.
背景是用户输入正确账号密码后, 有时仍停留在 `/login`.
请先阅读 auth 和 router 相关代码, 不要改代码, 先给出可能原因和排查计划.
重点关注前端状态更新和 redirect 逻辑, 暂时不要分析后端数据库.

这个 Prompt 并不复杂, 但它给了 Agent 足够明确的方向. Agent 知道问题是什么, 知道先不要动代码, 知道应该看哪些模块, 也知道哪些方向暂时不需要展开. 这会显著减少无效探索.

如果你已经知道希望 Agent 修改什么, Prompt 里就应该写清楚修改边界和验证方式. 例如:

请修复 `src/cache.ts` 中 LRU cache 在容量为 0 时仍然保留元素的问题.
改动尽量限制在 `src/cache.ts` 和对应测试文件.
不要重构整个 cache 实现, 不要修改公开 API.
完成后运行 cache 相关测试, 并说明新增或修改了哪些 case.

这里最关键的是"不要重构整个 cache 实现"和"不要修改公开 API". 很多 Agent 在看到一个局部 bug 时, 会倾向于顺手整理附近代码. 有时这确实有帮助, 但对真实项目来说, 不必要的重构会增加 review 成本和回归风险. 如果你希望 Agent 做最小修改, 应该明确说出来.

对于还没有想清楚的需求, 不要假装自己已经想清楚. 你可以直接要求 Agent 先问问题或先给方案:

我想给这个项目增加导出 CSV 的功能, 但还没确定放在哪个入口.
请先阅读现有导出相关代码, 然后问我最多 3 个关键问题.
在我回答前不要开始实现.

这类 Prompt 的重点是承认不确定性. Agent 不是读心术工具. 如果需求本身有歧义, 最好的做法不是让模型自由发挥, 而是让它把歧义暴露出来. 这也是 Plan Mode 的价值所在.

还有一种常见错误是把实现方案写得太死. 例如:

请在 `UserService` 里加一个 `if` 判断, 如果 token 为空就直接 return false.

这条指令看起来很明确, 但它可能跳过了真正的问题. 也许 token 为空不应该在 UserService 里处理, 而应该在请求解析阶段就被拒绝. 也许 return false 会吞掉错误, 导致调用方无法区分未登录和系统异常. 对 Agent 来说, 如果你直接指定一个很细的实现, 它可能会照做, 但不会再检查这个方案是否合理.

更稳妥的写法是描述现象和约束, 让 Agent 先判断实现点:

当前未登录请求有时会在 `UserService` 里触发 token 为空的异常.
请调查 token 为空应该在哪一层处理.
目标是让未登录请求返回明确的认证失败, 不要吞掉真正的系统错误.
先给出你建议的修改点, 再实现.

这并不是说永远不能指定实现. 如果你非常确定要怎么改, 当然可以直接下指令. 但在不确定的时候, 应该把问题交给 Agent 分析, 而不是把自己猜测的补丁伪装成需求.

写 Prompt 时还要注意信息的粒度. 太少的信息会让 Agent 猜, 太多的信息会把它淹没. 比较好的粒度是: 给出任务必须知道的上下文, 但不要一次性贴入大量无关文件. 如果你有错误日志, 先贴关键 stack trace; 如果你知道相关文件, 直接告诉它文件路径; 如果你知道最近改过什么, 说明这个变化为什么可能相关.

例如:

CI 里 `checkout.test.ts` 失败, 本地暂时复现不了.
失败信息是 `expected status 200, received 409`.
最近改动集中在 `src/payment/lock.ts` 和 `src/checkout/service.ts`.
请先根据测试和最近改动分析可能原因, 不要直接改 snapshot.

这类 Prompt 会让 Agent 从高价值位置开始调查, 而不是漫无目的地扫描整个仓库.

如果任务比较大, 不要一次要求 Agent "全部做完". 更好的方式是分阶段推进. 第一阶段让它调查和计划, 第二阶段实现最小可用版本, 第三阶段补测试和文档, 第四阶段清理边界问题. 分阶段的好处是每一步都可以校正方向, 也能避免 Agent 在一个巨大的目标里做出太多你没预料到的选择.

第一步只做调研: 找出现有导入功能的入口, 数据流和测试覆盖.
不要改代码. 输出一份简短计划, 说明如果要支持 JSON 导入需要改哪些文件.

等这一步完成后, 再继续:

按刚才的计划实现最小版本.
只支持标准 JSON 文件, 暂时不做拖拽上传, 不做批量导入.
完成后补充最关键的 parser 测试.

这种写法会让 Agent 的工作节奏更像真实开发, 而不是一次性生成一个巨大的不可控 patch.

最后, Prompt 里应该尽量写验收标准. "修好它"不是验收标准, "相关测试通过"也有时不够. 如果你关心兼容性, 性能, UI 行为, 错误提示, API 不变性, 都应该说出来. Agent 不一定会自动知道你最在意什么.

一个比较完整的 Coding Prompt 可以长这样:

请修复用户删除项目后列表没有立即刷新的问题.

背景:
点击删除按钮后, 后端请求成功, 但页面仍显示旧项目. 手动刷新后项目会消失.

范围:
优先检查 `ProjectList` 和项目删除 mutation 相关代码.
尽量不要修改后端 API, 不要重构整个数据请求层.

要求:
删除成功后列表立即更新.
删除失败时保留原列表, 并显示现有风格的错误提示.
不要引入新的状态管理库.

验证:
运行项目列表相关测试.
如果没有覆盖这个 case, 增加一个最小测试.
完成后说明改了哪些文件, 以及为什么这样更新缓存.

这个 Prompt 的结构并不神秘. 它只是把一个工程任务交代清楚了. 对初学者来说, 最重要的习惯是不要把 Agent 当成一个能自动补全所有上下文的黑箱. 你给它越清楚的目标, 越明确的边界, 越可检查的验收方式, 它就越容易产出可以 review, 可以合并, 可以维护的代码.

应该如何管理上下文

上下文管理是 Agentic Coding 的核心技能之一. 模型能力越强, 越容易让人忽视这一点. 但在真实项目里, 很多 Agent 跑偏不是因为模型完全不会写代码, 而是因为上下文里混入了过期信息, 无关文件, 太长的日志, 或者没有记录当前任务的真实目标.

管理上下文的目标不是把对话压到最短, 而是让 Agent 总能看到完成当前任务所需的最小充分信息. 这包括需求是什么, 当前进度到哪里, 哪些方案已经失败, 哪些文件是关键, 用户有哪些限制, 以及最后要如何验证.

自动压缩与手动压缩

长对话到一定程度后, 很多 Agent 平台会自动压缩上下文. 自动压缩的作用是把前面的对话总结成较短的摘要, 为后续工作腾出空间. 它很有用, 但不应该完全依赖.

自动压缩的问题在于, 它未必知道哪些细节对你最重要. 它可能保留了大方向, 却丢掉一个关键文件名, 一个失败命令, 一个用户特别强调的限制, 或者一个已经排除过的错误方向. 对复杂任务来说, 这些细节可能决定后续是否会重复踩坑.

手动压缩就是你主动整理进度. 例如在任务进行到一个阶段后, 让 Agent 总结当前状态:

请总结当前任务进展, 包括已修改文件, 已验证内容, 仍未解决的问题, 以及下一步计划.

这个总结可以继续留在对话里, 也可以写进临时 progress 文档. 手动压缩的优势是你可以要求它保留真正关键的信息, 而不是泛泛而谈.

避免直接读入大文件

很多初学者会让 Agent "读一下整个项目"或"把这个大文件全部看完". 这在小项目里问题不大, 但在真实仓库里很容易浪费上下文. 大文件里往往只有一小段和任务相关, 直接读入会把大量无关信息塞进窗口.

更好的方式是先搜索, 再局部阅读. 如果你要修一个函数, 可以先用 rg 找函数名, 类型名, 错误信息或测试名. 找到相关位置后, 再读取附近几十到几百行. 如果需要理解跨文件调用关系, 再逐步扩展范围.

这和人读代码的方式一样. 你不会为了修一个按钮样式先把整个前端仓库从头读到尾. 你会先找到组件, 找到样式, 找到测试或调用点. Agent 也应该这样工作.

尤其是对于日志. 不要把几万行 log 全塞给 Agent. 先找失败测试名, error, stack trace, failed, exception 这些关键位置. 让 Agent 看关键片段, 再根据需要扩展上下文. 这样它更容易抓住真正的失败原因.

遵循同一个主题

一个对话最好围绕一个主要任务展开. 如果你在同一个上下文里先让 Agent 修后端 bug, 接着写博客, 然后调 Docker, 再讨论旅行计划, 上下文会迅速变脏. 模型需要不断判断当前到底该沿用哪些旧信息, 哪些已经无关.

主题不一致还会污染隐含假设. 例如前半段对话一直在讨论 Python 项目, 后半段你突然让 Agent 写 TypeScript, 它可能仍然沿用前面关于测试命令, 项目结构或代码风格的判断. 这不是模型"故意犯傻", 而是上下文给了它混乱信号.

比较好的习惯是一个任务开一个对话, 或者在切换任务时明确重置上下文:

下面是一个新任务, 和前面的 bug fix 无关.
请忽略前面关于后端测试失败的上下文, 只关注这个文档文件.

如果任务跨度很大, 更稳妥的做法是开启新会话, 只带上必要背景.

记录 Progress

Agent 做长任务时, progress 记录非常重要. 人类程序员工作时也会记笔记: 哪些文件看过, 哪些假设被否定, 哪个测试还没过, 下次应该从哪里继续. Agent 同样需要这种记录, 否则上下文压缩或会话中断后很容易重复工作.

Progress 可以写在对话里, 也可以写在仓库的临时文档里. 对于正式项目, 通常不应该随便提交临时笔记; 但在长时间迁移或调研任务中, 维护一份明确的工作记录会很有帮助.

一个有效的 progress 记录应该包含当前目标, 已完成事项, 重要发现, 已修改文件, 验证结果和下一步。它不需要很长, 但要具体。例如"修了一些 bug"没有价值, "修复了 parser 对空数组的处理, parser.test.ts 仍有 2 个 snapshot 失败"就有价值.

当你中途要暂停 Agent, 可以让它先总结:

请给出一份 handoff summary, 让下一次对话可以继续这个任务.
包括当前目标, 关键文件, 已做修改, 测试结果, 未解决问题.

这类总结比普通聊天记录更容易被后续 Agent 接上。

使用 Subagents

Subagents 是把一个大任务拆给多个子 Agent 并行处理的机制. 它的核心价值不是让模型数量变多, 而是把上下文隔离开. 每个子 Agent 只看自己那部分问题, 产出一个较小的结论或补丁, 主 Agent 再负责整合.

这很像软件团队分工. 如果一个人同时脑内维护前端样式, 后端 API, 数据库 migration 和 CI 配置, 很容易混乱. 把任务拆给不同人后, 每个人只关注自己的边界, 整体效率更高.

适合使用 Subagents 的场景是任务之间相对独立. 例如一个子 Agent 调查测试失败原因, 另一个子 Agent 阅读文档更新 API 用法, 主 Agent 本地继续实现无冲突的代码改动. 如果两个子 Agent 会同时修改同一个文件, 或者彼此结果强依赖, 并行反而可能制造冲突.

使用 Subagents 时, 任务描述要非常具体. 不要说"看看这个项目", 而要说"请只调查 auth 模块里 token refresh 的调用链, 不要修改文件, 最后给出相关文件和结论". 对会改代码的子 Agent, 还要明确它拥有的文件范围, 并提醒它不要回滚别人改动.

最终仍然需要主 Agent 或人类做整合。Subagents 可以加快探索, 但不能替代整体判断. 多个局部结论之间可能有矛盾, 也可能都对但不适合一起合并.

使用 Rewind 和 Git

无论是 Codex, Claude Code, 还是 OpenCode, 很多 Agentic Coding 工具都有类似 Rewind 的功能. 它的作用是让 Agent 回到之前的某个状态, 放弃后续的对话, 工具调用结果和部分工作现场. 这对于纠正 Agent 跑偏非常有用. 有时候你会发现 Agent 在某个错误方向上越走越远, 这时直接 Rewind 回到上一轮关键节点, 修正你的 Prompt, 让它重新尝试, 往往比在错误基础上继续解释更高效.

Rewind 管理的主要是 Agent 的上下文状态. 换句话说, 它关心的是"Agent 当前相信什么", "它看过哪些输出", "它沿着哪条推理路线走到这里", 以及"后续对话是否还会受到错误历史影响". 如果 Agent 已经读了一堆无关文件, 做了错误判断, 或者反复围绕一个错误假设行动, 即使你告诉它"刚才错了", 这些错误过程仍然可能留在上下文里. Rewind 的价值就在于把这些污染过的上下文丢掉, 回到一个更干净的分叉点.

但是 Rewind 不能替代 Git. Git 管理的是代码仓库状态, 也就是文件内容, diff, commit, branch, stash 这些东西. Agent 的上下文可以回退, 不代表你的工作区一定已经回到你想要的代码状态; 反过来, Git 可以把文件恢复到某个版本, 但它不会自动清理 Agent 对话里已经产生的错误记忆. 所以在 Agentic Coding 里, Rewind 和 Git 解决的是两个不同层面的问题.

可以这样理解:

Rewind: 回退 Agent 的思考和对话现场.
Git:    回退或保存代码仓库的文件状态.

这两个工具最好配合使用. 在让 Agent 做较大改动前, 先用 Git 确认工作区是否干净:

git status

如果当前已经有你自己的未提交修改, 就要先搞清楚这些修改是什么, 不要让 Agent 随便覆盖. 对重要改动, 可以先提交一个 checkpoint commit, 或者至少用 git diff 看清当前状态:

git diff
git diff --staged

如果你正在尝试一个不确定方案, 可以新建一个临时分支:

git switch -c experiment/agent-refactor

这样 Agent 即使做了比较大的修改, 也不会直接污染主分支. 如果方案最后证明可行, 可以整理 commit 后合并; 如果不可行, 可以丢弃这个分支. 对初学者来说, 分支就是给代码状态开一个实验房间, 你可以在里面大胆试, 但不要把实验中的半成品直接混进主线.

还有一种非常实用的做法是使用小粒度 commit. 当 Agent 完成一个明确阶段, 例如修复一个 bug, 补完一组测试, 或完成一个独立文档章节, 你可以 review diff 后提交一次. 这样后面如果 Agent 又走错了, 你可以回到最近的稳定点, 而不是在一大团混杂修改里手动挑选.

git add src/cache.ts tests/cache.test.ts
git commit -m "fix cache capacity zero behavior"

这并不意味着要让 Agent 自动 commit. 更稳妥的方式是让 Agent 修改和验证, 你自己 review 后决定是否提交. Commit 是项目历史的一部分, 不只是保存按钮. 如果让 Agent 在你没检查的情况下连续提交, 后面排查问题会很麻烦.

当你只是想临时保存当前未完成工作, 可以用 git stash. 它适合这种场景: 你正在做 A 任务, 突然需要让 Agent 处理一个无关的 B 问题, 但你又不想把 A 的半成品提交。此时可以先 stash:

git stash push -m "wip before agent task"

处理完 B 后再恢复:

git stash pop

不过 stash 不是长期任务管理工具. Stash 多了以后很容易忘记每一份是什么, 也可能在 pop 时产生冲突. 如果一份工作需要保存较久, 分支或 WIP commit 通常更清楚.

真正需要回退代码时, 要先分清楚你想回退什么. 如果只是想丢弃某个文件里的未提交修改, 可以用:

git restore path/to/file

如果想取消已经 git add 的暂存, 但保留文件修改, 可以用:

git restore --staged path/to/file

如果某个 commit 已经进入历史, 并且你希望用一个新 commit 抵消它, 更适合使用 git revert:

git revert <commit>

对于 git reset --hard 这类命令要非常谨慎. 它会直接丢弃工作区修改, 初学者很容易把自己或 Agent 刚做的工作全部清掉. 除非你非常确定工作区里没有需要保留的内容, 否则不要把它当成普通撤销按钮.

Rewind 和 Git 配合时, 一个比较健康的工作流是这样的: 先用 Git 确认或保存当前代码状态, 再让 Agent 开始一个清晰任务. 如果 Agent 中途跑偏, 先判断问题属于哪一层. 如果只是上下文被污染, 代码还没坏, 用 Rewind 回到较早对话点并重新提示. 如果代码已经被改乱, 用 Git diff 查看改动, 必要时 restore 部分文件, 然后再 Rewind 或开启新对话. 如果 Agent 已经完成一小段正确工作, 先把这段用 commit 固定下来, 再继续下一阶段.

一个例子是, Agent 为了修一个测试失败, 顺手重构了半个模块. 如果你不想要这个方向, 可以先看 diff:

git diff

如果确认这些修改都不要, 可以恢复相关文件, 然后 Rewind 到它开始重构之前的对话点, 重新给 Prompt:

刚才的方向太大了. 请只修复 failing test 指向的边界条件.
不要重构公共 API, 不要移动文件, 修改范围限制在 parser 模块.

这比在当前上下文里反复说"不要这样"更干净, 因为错误方向的中间推理和无关文件读取已经被丢掉了.

另一个例子是, Agent 前半段修复了 bug, 后半段为了补测试把项目搞乱了. 这时不一定要全部回退. 你可以先保留前半段正确代码, 用 Git 只恢复测试相关文件, 或者把正确部分单独提交。然后 Rewind 到补测试之前, 重新要求它只补最小测试。Git 的优势在于它能精确管理文件级和 commit 级状态, Rewind 的优势在于它能精确管理对话分支和上下文状态.

最重要的是形成一个意识: Agent 工作时同时存在两条时间线. 一条是代码时间线, 由 Git 记录; 另一条是上下文时间线, 由对话和 Rewind 管理. 只会用 Rewind, 你可能无法安全保护代码; 只会用 Git, 你又可能让 Agent 一直带着错误上下文继续工作. 真正稳定的 Agentic Coding, 是在关键节点同时管理这两条时间线.

使用 Skills

前面已经提到 Skills 是 Agent 的专业手册. 在实际使用中, 你可以把它看成一种可复用的工作流封装. 当某类任务频繁出现, 且每次都有固定步骤和注意事项时, Skill 就比临时提示更合适.

例如你经常让 Agent 修改 .docx 文件. 这类任务不是简单改文本, 它可能需要解包文档, 修改 XML, 重新打包, 渲染检查页面布局. 如果每次都从零解释, 很容易漏步骤. 一个文档处理 Skill 可以规定固定流程: 先备份, 再修改, 再渲染, 最后视觉检查. Agent 只要识别到任务属于这个领域, 就加载 Skill 执行。

Skills 的本质

Skill 的本质不是给模型增加新参数, 也不是训练一个新模型. 它只是把一组领域说明, 工作流程, 脚本路径, 模板文件和注意事项组织起来, 让 Agent 在需要时读取.

这点很重要. 很多人会把 Skill 想成"插件"或"超能力", 但它更接近一份结构化 runbook. 如果 Skill 里写的是错误流程, Agent 会更稳定地犯同一种错误. 如果 Skill 里写得太空泛, 它也不会神奇地提升效果.

好的 Skill 通常有几个特征。它触发条件明确, 说明什么时候应该使用, 什么时候不应该使用. 它的步骤具体, 能告诉 Agent 先做什么再做什么. 它引用的脚本和资源路径准确, 不需要 Agent 到处猜. 它还会说明验证方法, 因为没有验证的自动化流程很容易看起来完成了, 实际上结果不可用.

从上下文角度看, Skill 还有一个好处: 它避免把所有领域知识常驻在主上下文里. 主上下文保持轻量, 只有任务真正需要某个领域时, 才把对应 Skill 读进来.

Skills vs. AGENTS.md

AGENTS.md 和 Skills 都是在给 Agent 提供额外指令, 但它们的作用范围不同. AGENTS.md 是仓库级规则, 适合描述这个项目长期稳定的约定. Skills 是任务级能力, 适合描述某类工作应该怎么做.

如果一条规则只要进入这个仓库就总是成立, 它适合放进 AGENTS.md. 例如包管理器, 测试命令, 生成文件策略, 代码风格边界. 如果一条规则只在某类任务中成立, 它适合放进 Skill. 例如处理 Excel, 调试 GitHub Actions, 生成图片, 发布 PR, 编辑 PowerPoint.

可以这样区分:

AGENTS.md: 这个仓库里的 Agent 应该一直知道什么.
Skill: 当 Agent 做某类任务时, 应该临时掌握什么流程.

把所有东西都写进 AGENTS.md 会让它越来越长, 最后变成另一个噪声源. 把项目核心规则都放进 Skills 又会导致 Agent 进入仓库时缺少基本约束. 两者应该配合使用: AGENTS.md 管通用边界, Skills 管专业流程.

创建 Skills

创建 Skill 时, 不要从"我要写很多知识"开始, 而要从一个反复出现的具体任务开始. 例如"每次处理 PR 评论都要先读取 unresolved threads", "每次生成图片都要遵守品牌风格", "每次编辑课件都要渲染检查", 这些都是合适的 Skill 候选.

一个简单 Skill 通常需要说明四件事。第一, 什么时候触发它. 第二, 它应该按什么步骤工作. 第三, 它可以使用哪些脚本, 模板或资源. 第四, 完成后如何验证结果.

Skill 的文字要写给 Agent 看, 所以要直接, 明确, 可执行. 不要写"尽量做好", 而要写"修改后运行 npm test -- parser.test.ts". 不要写"注意格式", 而要写"使用 pnpm format 格式化被修改文件". 不要写"检查输出", 而要写"渲染第一页和最后一页, 确认没有文字溢出".

一个很小的 Skill 可以像这样:

# CSV Report Skill

Use this skill when asked to create or modify CSV reports.

Workflow:
1. Inspect the header row before editing.
2. Preserve column order unless the user asks otherwise.
3. Validate that every row has the same number of columns.
4. If formulas are involved, explain that CSV cannot preserve formulas.

Verification:
Run a parser check after editing and report the row count.

虽然这里用了编号列表, 但它们是给 Agent 执行的步骤, 不是写给读者看的正文。真正重要的是 Skill 具体到可以执行. 如果你的 Skill 写完以后, Agent 仍然需要猜下一步怎么做, 那它还不够好.

最后要记住, Skills 也需要维护. 项目工具变了, 脚本路径变了, 团队流程变了, Skill 也要更新. 过期的 Skill 比没有 Skill 更危险, 因为它会让 Agent 带着很强的信心执行错误流程.

权限管理

Agentic Coding 的能力越强, 权限管理就越重要. 一个只能聊天的模型最多给出错误建议; 一个能读文件, 改代码, 运行命令, 联网, 调用 GitHub 或数据库工具的 Agent, 已经接近一个真实开发者账号. 它能提高效率, 也可能误删文件, 泄露 token, 修改错误目录, 安装不该安装的软件, 或把半成品推到远端仓库.

因此, 使用 Agent 时不能只问"模型聪不聪明", 还要问"它被允许做什么". 权限管理的核心原则是最小权限: Agent 只应该拿到完成当前任务所需的能力, 不应该默认拥有整台机器, 所有网络, 所有密钥和所有仓库的完全访问权.

沙盒机制

现在主流 Agentic Coding 工具一般不会让模型直接控制你的电脑. 中间通常会有一层工具执行环境, 负责把模型想做的事情转换成受控操作. 模型可能提出"读取这个文件", "运行这个测试", "修改这几行代码", 但真正执行这些动作的是 Agent 客户端和它背后的工具系统. 这层系统可以做权限检查, 路径限制, 网络限制, 命令审批和操作日志记录.

最常见的是文件系统沙盒. 它会限制 Agent 能读写哪些目录. 例如只允许读当前仓库, 只允许写 workspace 目录, 不允许访问你的 home 目录, SSH key, 浏览器数据, 系统配置或其他项目. 这类限制非常重要, 因为真实开发机器里往往有很多敏感文件, 例如 ~/.ssh/id_rsa, ~/.aws/credentials, .env, npm token, GitHub token 等. 如果 Agent 能随意读取这些文件, 再配合联网能力, 风险会明显上升.

第二类是命令沙盒. Agent 可以请求运行 shell 命令, 但不是所有命令都应该直接执行. 像 rg, sed, git diff, npm test, pytest 这类读取或验证性质的命令, 风险相对较低; 像 rm -rf, sudo, chmod -R, chown -R, git reset --hard, docker system prune, curl | sh, npm install -g, brew install 这类命令, 可能删除文件, 改系统状态, 安装软件, 或执行远程脚本, 就应该被拦截并要求人工确认.

第三类是网络权限. 一些 Agent 默认不能联网, 或者联网需要额外授权. 这可以防止它在你不知情的情况下下载依赖, 调用外部 API, 上传日志, 或把本地信息发送到不该去的地方. 对编程任务来说, 联网有时很有用, 例如查官方文档, 下载依赖, 拉取远程仓库. 但联网不是无害能力, 尤其当上下文里可能包含错误日志, 环境变量, 私有代码或内部路径时.

第四类是工具权限. MCP, GitHub connector, 浏览器自动化, 数据库工具, 云服务 CLI 都可以成为 Agent 的工具. 每多一个工具, Agent 的行动面就扩大一圈. 一个能读 GitHub issue 的工具和一个能 merge PR 的工具不是同一风险等级; 一个只读数据库 schema 的工具和一个能执行 SQL 写入的工具也不是同一风险等级. 好的工具系统应该把 read 和 write 分开, 把普通操作和高危操作分开, 并且留下清楚的审计记录.

还有一类安全机制是人工审批. 当 Agent 要执行超出默认权限的操作时, 工具会把命令, 目的和影响展示给用户, 由用户决定是否允许. 这一步看起来会打断自动化, 但它是非常重要的安全阀. Agentic Coding 的目标不是让模型绕过你接管电脑, 而是让它在你设定的边界里自动完成低风险工作, 在高风险节点主动停下来询问.

需要注意的是, 沙盒不是绝对安全边界. 如果你给了 Agent 写入仓库的权限, 它就能破坏仓库里的文件; 如果你给了它运行测试的权限, 测试脚本本身也可能执行任意代码; 如果你把 Docker socket 挂给它, 它可能间接获得接近 root 的能力; 如果你允许它运行 sudo, 那很多本地限制都会失去意义. 所以沙盒应该和 Git, 代码 review, 最小权限, 审批机制一起使用, 不能把它当成万能保险箱.

避免完全开放权限

很多初学者为了省事, 会把 Agent 设置成 full access, auto approve, unrestricted network, 然后让它自己安装依赖, 改文件, 跑命令, 提交代码. 这在短时间内看起来很顺滑, 但长期看非常危险. Agent 一旦误判任务, 它会在没有阻拦的情况下快速扩大影响范围. 更糟糕的是, 你可能直到很久以后才发现它改了系统设置, 删除了缓存, 覆盖了本地文件, 或把不该提交的内容加入了 git.

更好的做法是预设一组常见规则, 让低风险操作自动通过, 高风险操作必须审批. 例如读取文件, 搜索代码, 查看 git diff, 运行项目内已有测试, 通常可以默认允许. 写入当前 workspace 可以允许, 但应该要求 Agent 在最终回答里说明改了哪些文件. 涉及系统目录, home 目录, 远程网络, 包管理器安装, 删除文件, 修改权限, sudo, docker 清理, git 历史重写, push 到远端等操作, 应该要求人工确认.

可以把规则写进 Agent 配置, 也可以写进 AGENTS.md 作为行为约束. 例如:

## Agent Permissions

Allowed without asking:
- Read files inside this repository.
- Search with `rg`.
- Run `git status`, `git diff`, and `git log`.
- Run targeted tests documented in this repository.

Ask before:
- Installing dependencies.
- Running network commands.
- Creating, deleting, or moving many files.
- Changing file permissions or ownership.
- Running Docker cleanup commands.
- Creating commits or pushing to remotes.

Never run without explicit approval:
- `sudo`
- `rm -rf`
- `git reset --hard`
- `git clean -fd`
- `chmod -R` or `chown -R`
- `curl ... | sh` or `wget ... | sh`

这类规则的意义不是让 Agent 永远不能做高风险操作, 而是让它在关键节点停下来解释. 例如安装依赖并不一定危险, 但你应该知道它要安装什么, 为什么需要安装, 会写入哪里. 删除文件也不一定错误, 但你应该看到它准备删除哪些文件, 是否只是生成物, 是否已经被 Git 跟踪. sudo 更应该谨慎, 因为它表示 Agent 正在请求系统级权限, 一旦命令错误, 影响就不再局限于当前仓库.

审批时不要只看命令本身, 还要看命令的工作目录和参数. rm -rf build/ 和 rm -rf / 都是删除, 风险完全不同. chmod +x scripts/build.sh 和 chmod -R 777 . 也不是一回事. docker compose up 可能只是启动开发环境, docker system prune -a --volumes 却可能删除大量镜像, 容器和 volume. 关键命令应该让 Agent 说明意图, 影响范围和替代方案。

对于删除类操作, 一个安全习惯是先让 Agent 列出目标, 再确认删除. 例如不要直接批准:

rm -rf generated/

可以先要求:

find generated -maxdepth 2 -type f

或者:

git status --short generated/

确认这些文件确实是可再生的生成物, 或确实是你想删除的未跟踪文件, 再允许删除. 对 Git 跟踪的文件, 更推荐通过 diff 和 review 来处理, 不要让 Agent 用粗暴命令清空目录.

对于安装依赖, 也应该区分项目内安装和系统安装. npm install 会修改项目依赖和 lockfile, 需要 review; pip install -e . 可能只是开发环境操作, 但仍可能执行构建脚本; brew install, apt install, sudo apt install 会改变系统环境, 更应该审批. 如果只是为了运行一次测试而缺少依赖, 让 Agent 先说明缺少什么, 官方安装方式是什么, 是否有项目文档支持, 再决定是否允许.

对于联网命令, 要特别注意 curl | sh 和 wget | sh. 这种写法会把远程脚本下载后直接交给 shell 执行, 人类还没看脚本内容, 系统已经开始跑了. 如果确实需要执行安装脚本, 更安全的做法是先下载到文件, 阅读关键内容, 确认来源可信, 再手动执行. 对 Agent 来说, 这种命令默认应该要求审批, 而不是自动通过.

对于 Git 操作, 建议默认允许只读命令, 谨慎允许本地整理命令, 严格审批会改变历史或远端状态的命令. git status, git diff, git log, git show 通常可以自动运行. git add 和 git commit 最好由用户明确要求, 因为 commit 是项目历史的一部分. git push, git rebase, git reset --hard, git clean -fd, git checkout -- . 都可能造成难以恢复的影响, 不应该让 Agent 自己决定.

更稳妥的日常配置是让 Agent 在当前仓库里拥有读权限和有限写权限, 允许它自动运行搜索, 格式化和针对性测试, 但禁止它默认访问仓库外文件, 禁止默认联网, 禁止默认安装依赖, 禁止默认执行 sudo 和破坏性命令. 如果某个项目确实需要频繁运行特定命令, 可以把这些命令加入 allowlist. 例如一个前端项目可以允许:

pnpm test
pnpm lint
pnpm typecheck

一个 Python 项目可以允许:

pytest tests/unit
ruff check .
mypy src

allowlist 最好按命令前缀和项目范围设置, 不要过宽. 允许 pytest tests/unit 和允许任意 python 不是一回事; 允许 pnpm test 和允许任意 shell 脚本也不是一回事. 规则越具体, 自动化越可控.

最后还要保护密钥. 不要把 API key, SSH private key, .env 文件内容直接贴给 Agent. 如果 Agent 需要知道环境变量名字, 给名字和用途就够了, 不要给真实值. 如果 Agent 需要调试认证问题, 可以提供脱敏日志. 如果必须在本地运行带密钥的命令, 最好由你自己执行, 再把必要的非敏感输出提供给 Agent.

权限管理的目标不是把 Agent 绑到什么都不能做, 而是把它变成一个可靠的协作者: 普通读写和测试可以快速自动化, 关键操作必须解释和审批, 破坏性操作默认禁止. 这样 Agent 才能在不牺牲安全性的前提下真正提高开发效率.