很多人在使用 AI Agent 时,都会遇到一种熟悉的挫败感:

帮我优化这个项目。

Agent 看起来理解了,也开始行动了,但结果可能并不稳定。它也许改了一堆无关文件,也许跳过了测试,也许给出了一些看似合理但无法验证的建议。问题不一定是模型“不聪明”,而是这个任务本身太大、边界太模糊、执行路径不清晰。

如果换一种写法:

请先扫描项目结构,找出构建入口和测试命令。
然后检查前端渲染相关代码里是否有明显性能问题。
只修改 src/components 下的文件。
修改后运行 pnpm test 和 pnpm build,并汇报改了哪些文件。

这个 Prompt 的质量就明显不同了。它不只是表达了一个愿望,而是把任务拆成了一组可执行、可检查、可回退的步骤。

这背后其实就是 Atomic Tools 的思想。

什么是 Atomic Tools

Atomic Tools,可以理解为 Agent 能调用的“最小可执行动作”。

它们不是“修复整个项目”“做一个网站”“优化系统”这种大而模糊的能力,而是更小、更稳定的操作,比如:

read_file
search_code
list_directory
apply_patch
run_command
run_tests
open_browser
click
type
screenshot
query_web

每个工具只做一件事:

  • read_file 负责读取文件
  • search_code 负责搜索代码
  • apply_patch 负责应用修改
  • run_command 负责执行命令
  • screenshot 负责截取页面状态

复杂任务不是靠一个万能工具完成的,而是靠这些小工具一步步组合出来的。

比如“修复一个前端 bug”,可以被拆成:

搜索相关代码
读取文件
复现问题
查看报错
修改代码
运行测试
启动页面
截图验证
汇报结果

这就是原子化工具的价值:把模糊的大任务拆成可观察的小动作。

为什么要原子化

原子化工具的核心优势,不是“工具更多”,而是“执行更可靠”。

首先,它让任务可组合。

一个 read_file 本身很简单,一个 run_tests 也很简单,但组合起来就能完成复杂工作流:

list -> search -> read -> patch -> test -> report

Agent 不需要一次性猜完整答案,而是可以根据每一步结果继续决策。

其次,它让过程可控。

如果一个工具叫:

fix_project()

那它内部做了什么很难知道。它改了哪些文件?有没有运行测试?失败在哪一步?这些都不清楚。

但如果任务被拆成:

search_code
read_file
apply_patch
run_tests

每一步的输入、输出和失败原因都更明确。

第三,它让结果可验证。

好的工具应该能告诉你:

  • 成功还是失败
  • 输出是什么
  • 错误是什么
  • 下一步是否还能继续

例如:

run_tests -> exit code + stdout + stderr
apply_patch -> patch 是否成功应用
read_file -> 文件内容或文件不存在错误

这使得 Agent 不只是“执行”,还能“观察”和“修正”。

一个好的 Atomic Tool 应该怎么设计

设计 Atomic Tool 时,可以遵循几个原则。

第一,单一职责。

一个工具只做一类动作。

好的例子:

read_file
write_file
search_text
run_command
take_screenshot

不好的例子:

fix_bug
optimize_app
analyze_and_modify_project

后者太粗,失败后难以定位,也容易产生不可控副作用。

第二,输入输出明确。

工具最好有稳定的参数和稳定的返回。

例如一个 read_file 工具可以设计成:

{
  "name": "read_file",
  "description": "Read a UTF-8 text file.",
  "input": {
    "path": "string",
    "start_line": "number optional",
    "end_line": "number optional"
  },
  "output": {
    "content": "string",
    "line_count": "number",
    "truncated": "boolean"
  }
}

这样 Agent 才能基于返回结果继续推理,而不是只收到一段不可控文本。

第三,副作用要小。

读文件、搜索代码、列目录这类工具没有副作用,天然安全。

写文件、运行命令、删除资源这类工具副作用更大,就应该被设计得更严格。例如相比直接 write_file 覆盖整个文件,apply_patch 往往更可控,因为它能表达“只修改这一小段”,也更容易发现冲突。

第四,失败信息要结构化。

不要只返回:

Failed

更好的返回是:

{
  "ok": false,
  "error": "ENOENT",
  "message": "File not found",
  "path": "src/app.ts"
}

这样 Agent 才知道下一步应该搜索文件、换路径,还是询问用户。

Atomic Tools 对写 Prompt 有什么用

理解 Atomic Tools 后,写 Prompt 的方式会发生变化。

你会从“描述愿望”,转向“描述可执行路径”。

普通写法:

帮我看看这个项目哪里有问题。

更好的写法:

请先读取 README、package.json 和 src 入口文件。
总结项目结构后,只检查启动失败相关问题。
不要先修改代码。
如果找到原因,给出最小修复方案。

普通写法:

帮我重构一下。

更好的写法:

请找出 src/components 中重复最多的逻辑。
先列出候选点和风险,不要直接改。
只在我确认后做最小重构。

普通写法:

修好这个 bug。

更好的写法:

请先复现这个 bug,记录报错信息。
然后定位触发路径。
修复时只做最小改动。
修复后重新运行同一个复现步骤,并运行现有测试。

这些 Prompt 的共同点是:

看什么 -> 改什么 -> 怎么验证 -> 有什么边界

这正好对应 Agent 调用 Atomic Tools 的过程。

一个实用 Prompt 模板

日常使用 Agent 时,可以用这个模板:

目标:修复/实现 [具体目标]。

范围:
- 可以修改:[路径/模块]
- 不要修改:[路径/模块]

流程:
1. 先检查相关文件和现有实现。
2. 找到最小修改方案。
3. 实现修改。
4. 运行 [测试/构建/命令] 验证。
5. 汇报修改文件、验证结果、剩余风险。

约束:
- 遵循现有代码风格。
- 不做无关重构。
- 如果发现需求不明确,先问我。

这个模板的重点不是形式,而是让 Agent 的任务具备几个关键条件:

  • 目标明确
  • 范围明确
  • 步骤明确
  • 验证方式明确
  • 副作用边界明确

这会显著提升 Agent 的执行稳定性。

Agent 不是魔法,而是调度系统

很多人对 Agent 的期待是:我给它一个目标,它自动完成一切。

这个方向没有错,但真正可靠的 Agent 并不是靠一个巨大的万能动作完成任务,而是靠不断循环:

计划 -> 调用工具 -> 观察结果 -> 调整计划 -> 再调用工具

Atomic Tools 就是这个循环里的基础动作。

一个好的 Agent,需要的不只是“聪明的大脑”,还需要一组设计良好的工具:

小
稳
清晰
可验证
可组合
可恢复
低副作用
失败信息结构化

而一个好的 Prompt,也不是越短越好,而是要帮助 Agent 把目标拆成可执行的路径。

最终可以总结成一句话:

好的 Prompt = 明确目标 + 清晰边界 + 可执行步骤 + 验证方式。

理解 Atomic Tools 的意义,不只是知道 Agent 内部有哪些工具,而是学会用更工程化的方式和 Agent 协作。

当你开始这样写 Prompt,Agent 就不再只是“猜你想要什么”,而是能一步步执行、检查、修正,最终更稳定地完成任务。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐