Skip to content

内置工具

上下文视角:工具定义是 LLM 行动的说明书,工具返回值是它感知世界的方式。两者共同构成关键上下文。

上一节讲了系统指令如何定义 LLM 的行为基准。但光有身份不够——LLM 还需要行动能力

内置工具就是这种能力。它们是 Agent 开发者预先编写的函数——读文件、执行命令、搜代码、访问网络——集成在 Agent 内部,由 Agent 在你的本地机器上执行。

其中 bash(或 shell)是最万能的一个。理论上它能做任何事——读文件、装依赖、跑测试、查 Git 历史、curl 一个 API。那为什么还需要其他工具?因为专用工具更安全、更精确:read_filecat 更可控,edit_file 比手动拼接文件内容更不容易出错。

LLM 自己不能运行这些函数。它能做的是生成一个 JSON 对象,告诉 Agent "帮我执行这个操作"。

这个操作就是一次工具调用(tool call)。

Agent 在本地执行工具,然后把执行结果——成功或失败,连同输出——打包成新的消息,追加到对话历史里,再发给 LLM。LLM 看到结果,决定下一步是再次调用工具,还是回答用户问题。

这个"生成工具调用 → 本地执行 → 返回结果 → 基于结果再推理"的闭环,就是 agentic 工作流的核心。

Built-in Tools Structural View: Agent Capability Layer CONTEXT BUFFER System Instructions Tool Definitions (JSON Schema) tools: [ { name: "read_file", desc: "Read local file", args: { path: "str" } }, { name: "ls", ... }, { name: "grep", ... }, { name: "write_file", desc: "⚠️ Modify FS" } ] Occupies Context Window Space LLM Logic Inference Engine Gen: tool_calls AGENT RUNTIME AVAILABLE EXECUTORS read_file() ls / grep write_file() TRUST BOUNDARY > Executing... read_file("src/app.ts") LOCAL FILESYSTEM src/ app.ts package.json README.md OBSERVATION LOOP
Built-in Tools Structural View: Agent Capability Layer CONTEXT BUFFER System Instructions Tool Definitions (JSON Schema) tools: [ { name: "read_file", desc: "Read local file", args: { path: "str" } }, { name: "ls", ... }, { name: "grep", ... }, { name: "write_file", desc: "⚠️ Modify FS" } ] Occupies Context Window Space LLM Logic Inference Engine Gen: tool_calls AGENT RUNTIME AVAILABLE EXECUTORS read_file() ls / grep write_file() TRUST BOUNDARY > Executing... read_file("src/app.ts") LOCAL FILESYSTEM src/ app.ts package.json README.md OBSERVATION LOOP

工具调用流程

让我们通过一个完整的 HTTP 请求/响应流程,看看这个引擎怎么转。

假设你对 Agent 说:"把 logger.js 里的 log 函数改名为 logEvent。"

── 第 1 轮:从意图到工具调用 ──

Agent 将你的指令,连同包含所有可用工具定义的系统提示,打包发给 LLM。

json
// → REQUEST(agent → LLM API)
{
  "system": "你是一个代码助手。你可以使用以下工具:read_file, write_file...",
  "messages": [
    {
      "role": "user",
      "content": "把 logger.js 里的 log 函数改名为 logEvent"
    }
  ]
}

LLM 推理后,判断需要先看文件内容。它不直接输出代码,而是返回一个 tool_calls 请求:

json
// ← RESPONSE(LLM API → agent,SSE 流)
{
  "role": "assistant",
  "content": "好的,我先读取 logger.js 的内容。",
  "tool_calls": [
    {
      "id": "call_abc123",
      "name": "read_file",
      "arguments": { "filePath": "src/logger.js" }
    }
  ]
}

此时没有任何文件被修改。LLM 只是提出了一个行动计划


本地执行

Agent 收到响应,解析 tool_calls,在本地文件系统上执行 read_file,读取 src/logger.js 的内容。

整个过程在你的机器上完成,不涉及另一次 LLM API 调用。


── 第 2 轮:带着新上下文继续推理 ──

Agent 把工具执行结果包装成 tool 角色消息,追加到对话历史,发起新请求。注意 messages 比第 1 轮长了——上下文在增长。

json
// → REQUEST(agent → LLM API)
{
  "system": "你是一个代码助手。你可以使用以下工具...",
  "messages": [
    {
      "role": "user",
      "content": "把 logger.js 里的 log 函数改名为 logEvent"
    },
    {
      "role": "assistant",
      "tool_calls": [
        {
          "id": "call_abc123",
          "name": "read_file",
          "arguments": { "filePath": "src/logger.js" }
        }
      ]
    },
    {
      "role": "tool",
      "tool_call_id": "call_abc123",
      "content": "export function log(message) { console.log(message); }"
    }
  ]
}

LLM 的上下文中现在有了文件真实内容。它生成修改计划:

json
// ← RESPONSE(LLM API → agent,SSE 流)
{
  "role": "assistant",
  "content": "文件内容已读取。现在执行重命名。",
  "tool_calls": [
    {
      "id": "call_def456",
      "name": "write_file",
      "arguments": {
        "filePath": "src/logger.js",
        "content": "export function logEvent(message) { console.log(message); }"
      }
    }
  ]
}

Agent 再次在本地执行 write_file。一个完整的读取-修改-写入循环完成。

工具如何塑造上下文

走完这个流程,你会发现工具从两个方向塑造了 LLM 的上下文:

  1. 工具定义 → 静态上下文:每次请求的 systemtools 字段里,都带着完整的工具清单。你的 Agent 有 15 个工具?那每一轮请求——不管用户问的是什么——都会把 15 个工具的名称、描述、参数 schema 全部发过去。这就是"静态"的含义:不随对话变化,但始终占着窗口。LLM 靠它规划行动——不知道有哪些工具,就无法决定下一步。
  2. 工具返回值 → 动态上下文:每次工具执行结果追加到 messages,成为下一轮推理的输入。read_file 让 LLM 看到代码,bash 让它看到命令输出。LLM 通过工具定义知道能做什么,通过返回值了解外部世界的当前状态。
How Tools Shape Context Tool definitions are static context sent on every request. Tool return values are dynamic context appended to messages and can grow quickly. How Tools Shape Context Definitions are static (always sent). Results are dynamic (appended, can bloat fast). → REQUEST (EVERY ROUND) Static: tool definitions tools[]: read_file, write_file, bash, ... Sent on every API call Dynamic: messages + tool results messages[] + tool: "..." LLM Plans + emits tool_calls AGENT RUNTIME (LOCAL) Executes tools on your machine and returns results as context. read_file() grep ls write_file() bash (mutating ops) system + messages tool_calls JSON tool result → appended to messages[] (next round) CONTEXT WINDOW BUDGET Static baseline Dynamic grows fastest Trim at tool layer: limit lines • paginate long lists • prefer structured output
How Tools Shape Context Tool definitions are static context sent on every request. Tool return values are dynamic context appended to messages and can grow quickly. How Tools Shape Context Definitions are static (always sent). Results are dynamic (appended, can bloat fast). → REQUEST (EVERY ROUND) Static: tool definitions tools[]: read_file, write_file, bash, ... Sent on every API call Dynamic: messages + tool results messages[] + tool: "..." LLM Plans + emits tool_calls AGENT RUNTIME (LOCAL) Executes tools on your machine and returns results as context. read_file() grep ls write_file() bash (mutating ops) system + messages tool_calls JSON tool result → appended to messages[] (next round) CONTEXT WINDOW BUDGET Static baseline Dynamic grows fastest Trim at tool layer: limit lines • paginate long lists • prefer structured output

但工具返回值也是上下文膨胀最快的来源。一次未加限制的 ls -R 或读一个几万行的日志文件,直接撑爆大半个上下文窗口。

聪明的做法是在工具层就裁剪。Agent 开发者通常会在工具的实现中加入保护机制,比如 read_file 默认只返回前 2000 行,bash 工具会截断过长的输出。用户不直接控制这些行为,它们是保证 Agent 稳定运行的必要限制。

与其等上下文满了再想办法压缩,不如一开始就别让垃圾进来。

看懂 Agent 的探索行为

新手看到 Agent 连跑三次 lsgrep 就急了:"你倒是直接改代码啊?"

Agent 看不见你的屏幕——不知道 IDE 里打开了什么文件,不知道文件树长什么样。唯一"看见"世界的方式是工具返回值。

  • ls 是眼睛,确认文件在哪。
  • grep 是扫描仪,定位要改的地方。
  • read_file 是显微镜,看清代码细节。

这些"冗余"操作在构建导航上下文。没这些铺垫就是盲写。给它探索的时间。

信任边界分级

Agent 会真实执行 LLM 请求的操作。好的工具分两级信任:

读工具(放行)

lsread_filegrep。让它跑,别打断观察。想看 10 个文件才动手?让它看。

写/执行工具(介入)

write_filebash(修改类)。这是你的介入点。

盯一件事:有没有先读后改。Agent 没跑过 read_file 就直接 write_file?哪怕改对了也拒绝。那是幻觉碰运气。

你需要清楚你的 Agent 有多大权限,并有意识地监督高风险操作。

Trust Boundary Levels A risk-based view of built-in tools: allow read-only exploration, review low-risk writes, and confirm high-risk write or execute operations. Trust Boundary Levels Handle tools differently by risk: allow observation, review writes, confirm high-risk ops. RISK & PERMISSIONS → Read-only tools ALLOW Examples ls, read_file, grep Recommended handling Let it explore and observe. Builds navigation context. Low-risk write REVIEW Examples write_file, edit_file Recommended handling Review a diff. Keep changes small. Prefer reversible edits. High-risk write/execute CONFIRM Examples bash, rm -rf, deploy Recommended handling Explicit approval + guardrails. Add sandboxing when possible. Rule: read before write • stop if a write happens without a prior read • audit trail: tool_calls + tool results
Trust Boundary Levels A risk-based view of built-in tools: allow read-only exploration, review low-risk writes, and confirm high-risk write or execute operations. Trust Boundary Levels Handle tools differently by risk: allow observation, review writes, confirm high-risk ops. RISK & PERMISSIONS → Read-only tools ALLOW Examples ls, read_file, grep Recommended handling Let it explore and observe. Builds navigation context. Low-risk write REVIEW Examples write_file, edit_file Recommended handling Review a diff. Keep changes small. Prefer reversible edits. High-risk write/execute CONFIRM Examples bash, rm -rf, deploy Recommended handling Explicit approval + guardrails. Add sandboxing when possible. Rule: read before write • stop if a write happens without a prior read • audit trail: tool_calls + tool results

光说“工具”太抽象。不同 agent 的内置工具长什么样?看几个例子就明白了。下面是四个常见 AI 编码助手的工具集对比,让你对“内置”有个具体概念。

工具分类对比

工具类型Claude CodeCodexGemini CLIOpenCode
读取类Read, Glob, Grepread_file, list_dirread_file, list_directory, globread, glob, grep
写入类Write, Editapply_patchwrite_file, replaceedit, write
执行类Bashshell(沙箱内)run_shell_commandbash
搜索类Grep, Globgrep_filessearch_file_content, globgrep, lsp
网络类WebFetch, WebSearchweb_searchweb_fetch, google_web_searchwebfetch

权限控制对比

Agent权限模型用户配置方式
Claude Code分层权限(default, acceptEdits, plan, dontAsk)allowedTools 列表 + 交互式提示
Codex沙箱 + 审批策略(Auto / Read-only / Full Access 预设)CLI 参数 + ~/.codex/config.toml
Gemini CLI交互式确认 + Trusted Folders + Sandbox~/.gemini/settings.json
OpenCode每工具三档(allow, ask, deny)opencode.json 文件

工具名和分类不同,但模式一样——读、写、执行、搜索,再加上权限分级控制。这套组合拳是 Agent 与世界互动的基石。

本节小结

  • 上下文流动:工具定义是静态上下文,每次请求都在;工具返回值是动态上下文,执行后追加。两者共同驱动 LLM 的行动-感知循环。
  • 风险read_file 读一个 10MB 的日志?上下文窗口瞬间爆掉,早期关键信息被截断。bash 自动执行 rm -rf?没有确认机制的 Agent 大概率会执行。
  • 可审计性:每次 tool_calls 请求和对应的 tool 角色消息都在对话历史中——完整的行动证据链。

下一节看 MCP——当内置工具不够用时,如何让 Agent 调用外部服务。执行路径变了,但对 LLM 来说,一切照旧。