> For the complete documentation index, see [llms.txt](https://yeasy.gitbook.io/agentic_ai_guide/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yeasy.gitbook.io/agentic_ai_guide/di-yi-bu-fen-dan-ti-zhi-neng-jia-gou/04_tools/4.2_tool_use.md).

# 4.2 工具使用机制

工具使用（Tool Use）机制是连接大语言模型与外部代码逻辑的桥梁。本节将深入剖析其工作原理、实现机制以及如何通过它来构建强大的智能体应用。

## 4.2.1 核心原理

在早期对话式大模型刚被广泛使用时，常见批评之一是“它无法获知最新信息”和“它不能完成实际任务”。这是因为模型本身无法联网，也无法直接操作文件系统。

**工具使用（Tool Use）**（也常被称为函数调用/工具调用机制），彻底打破了这堵墙。它赋予了智能体“手”和“脚”，使其能够执行 API 调用、运行代码、控制浏览器，从而真正地干涉物理和数字世界。

***

### 运行机制

工具调用并不是魔法，它本质上是一种 **结构化输出协议**。模型并没有真的去运行 Python 函数，它只是生成了一段 **请求运行工具** 的文本。

### 工具定义

为了让智能体使用工具，必须先用精确的语言定义工具。通常使用 JSON Schema 或 Pydantic 模型。

**好的工具定义示例**：

```python
tools = [
    {
        "name": "search_web",
        "description": "搜索互联网获取信息。适用于查询新闻、事实、最新数据等。不适用于需要推理或创作的任务。",
        "parameters": {
            "type": "object",
            "properties": {
                "query": {
                    "type": "string",
                    "description": "搜索查询词，应该简洁明确"
                },
                "num_results": {
                    "type": "integer",
                    "description": "返回结果数量，默认 5",
                    "default": 5
                }
            },
            "required": ["query"]
        },
        "examples": [
            {"query": "某年度诺贝尔物理学奖获得者"},
            {"query": "Python 3.12 新特性", "num_results": 3}
        ]
    }
]
```

**工具定义要素**：

| 要素          | 说明                              | 重要性    |
| ----------- | ------------------------------- | ------ |
| name        | 简洁、有意义的名称                       | 必须     |
| description | 详细说明用途和限制。LLM 依靠这段描述来判断何时调用该工具。 | **关键** |
| parameters  | 清晰的参数定义 (JSON Schema)           | 必须     |
| examples    | 示例调用 (Few-shot)                 | 推荐     |
| use\_when   | 何时应该使用                          | 推荐     |
| avoid\_when | 何时不应使用                          | 推荐     |

### 执行流程

当用户说“查询北京明天的天气”时：

1. **思考 (Thinking)**: LLM 分析语义，发现需要外部数据。
2. **选择 (Selection)**: LLM 扫描工具列表，发现 `get_weather` 最相关。
3. **生成 (Generation)**: LLM 输出一个特殊的 JSON 结构：

   ```json
   {
     "tool_calls": [
       {
         "id": "call_123",
         "function": {
           "name": "get_weather",
           "arguments": "{\"location\": \"Beijing\", \"date\": \"tomorrow\"}"
         }
       }
     ]
   }
   ```
4. **执行 (Execution)**: Python 脚本（**运行时 Runtime**）解析这个 JSON，在本地真正调用 `get_weather("Beijing", "tomorrow")` 函数，获取 `Sunny, 25C` 这样的天气结果。
5. **反馈 (Feedback)**: Runtime 构建一条 `ToolMessage`，包含返回值，追加到对话历史中，再次喂给 LLM。
6. **响应 (Response)**: LLM 看到最新的 ToolMessage，终于可以说：“北京明天晴朗，气温 25 度。”

该执行模式在[第 2.3 节 ReAct 框架](/agentic_ai_guide/di-yi-bu-fen-dan-ti-zhi-neng-jia-gou/02_reasoning/2.3_react.md)中有形式化定义。

***

## 4.2.2 常用工具类型

一个全能的智能体通常通过 **Toolkit** 的形式加载一组工具，常见的工具类型包括信息获取、计算与逻辑、生产力与协作等。

### 信息获取类

* **Web Search**：解决 LLM 知识截止和时效性问题。
* **Wikipedia**: 获取背景知识。
* **Arxiv**: 搜索学术论文。
* **RAG Retriever**: 搜索私有的企业知识库。

### 计算与逻辑类

LLM 是文科生，算数（Arithmetic）很差，经常一本正经地算错。

* **Calculator**: 简单的四则运算。
* **Python Interpreter**: 终极武器。当需要解方程、数据分析、画图时，让智能体写一段 Python 代码并在沙箱中运行，是准确率最高的方法（代码解释器模式）。

**计算器**

计算器工具适合处理明确的四则运算与可控表达式求值，优点是确定性强、实现简单。工程上建议使用安全解析器而不是直接 `eval`，并明确支持的运算符与函数集合。

**代码解释器详解**

代码解释器的核心是让 LLM 从“说话者”变成“行动者”。它通常作为一个 **工具（Tool）** 暴露给 LLM，当用户提出需要计算或数据处理的请求时，LLM 生成代码并通过工具调用将代码发送给解释器执行。

**核心价值**：

| 价值         | 问题                | 解决方案                             |
| ---------- | ----------------- | -------------------------------- |
| **弥补数学短板** | LLM 是概率模型，不擅长精确计算 | 运行 `print(248 * 1923)` 得到确定性正确结果 |
| **精确数据分析** | 百万行数据无法放入上下文      | 编写 Pandas 代码进行清洗、聚合和分析           |
| **多模态输出**  | 需要生成图表、文档         | 调用 Matplotlib、MoviePy 等库         |
| **算法验证**   | 复杂逻辑难以口述验证        | 实际运行代码验证正确性                      |

**沙箱技术方案**：

代码解释器必须运行在严格隔离的沙箱中，防止 `rm -rf /` 等危险操作：

| 技术                     | 描述                   | 优点        | 缺点       |
| ---------------------- | -------------------- | --------- | -------- |
| **Docker 容器**          | 行业标准，每个 Session 独立容器 | 隔离性强，库支持全 | 启动较慢     |
| **WebAssembly (WASM)** | 浏览器端通过 Pyodide 运行    | 绝对安全，轻量   | 性能有限，库受限 |
| **E2B 微虚拟机**           | 云原生沙箱，毫秒级启动          | 快速、安全、可扩展 | 依赖云服务    |
| **gVisor/Firecracker** | 轻量级容器运行时             | 安全性极高     | 配置复杂     |

以下示例展示了如何使用 E2B 沙箱运行代码并获取生成的图表：

```python
from e2b_code_interpreter import CodeInterpreter

async def run_analysis(code: str, data_path: str):
    with CodeInterpreter() as sandbox:
        sandbox.upload_file(data_path)
        result = sandbox.run_code(code)
        for artifact in result.artifacts:
            if artifact.type == "image":
                return artifact.download()
        return result.text
```

### 生产力与协作类

* **Gmail/Outlook**:读写邮件。
* **Calendar**: 安排日程。
* **Jira/Trello**: 管理项目任务。
* **File System**: 读写本地文件（需严格限制路径）。

## 4.2.3 工具设计哲学与评估驱动优化

在实践中，工具的有效性并不由数量决定，而由设计质量与目标导向决定。Anthropic 团队基于大量工具评估与优化实践，总结出以下核心设计理念。

### 确定性与非确定性的权衡

传统软件开发中，工具是确定性的：给定相同输入，输出永远相同。但智能体工具处于不同语境——它们是 **非确定性系统（智能体）与确定性系统之间的接口**。

例如，`getWeather("NYC")` 作为确定性函数总是返回相同结构；但当用户问“应该带伞吗？”时，智能体可能：

* 调用天气工具
* 从知识库回答
* 反过来问用户位置

这意味着工具设计必须考虑智能体的 **多元解决策略**，而非单一的“正确路径”。

### 选择正确的工具而非包装所有 API

关键原则：**更多工具不一定更好**。常见误区是把每个 API 端点都包装成工具。实际上应该问：

1. **上下文成本 vs 实用性**：每个额外的工具都消耗智能体的有限上下文。加载 100 个工具，其中 50 个不相关，会严重降低智能体的专注度。
2. **工具合并优于枚举**：比起提供 `list_users`, `list_events`, `create_event` 三个工具，不如实现单一的 `schedule_event` 工具，它内部负责查询可用性并一步完成预订。

   对比：

   * **不推荐**：`read_logs` 工具返回所有日志（可能数千行），智能体逐行阅读
   * **推荐**：`search_logs` 工具支持筛选，只返回相关日志和上下文
3. **Token 效率优先**：工具返回应当精简。支持 `response_format` 参数让智能体在 “concise”（仅关键数据）和 “detailed”（包含技术标识符）之间选择，从而在精确性和 Token 消耗间动态平衡。

### 评估驱动的工具改进流程

最有效的工具优化遵循以下迭代循环：

1. **生成评估任务**：基于真实工作流，创建 20-50 个综合性任务
   * 弱示例：“搜索日志中的错误”
   * 强示例：“找出客户 9182 报告的三次重复收费问题的所有相关日志，判断是否有其他客户被影响”
2. **运行评估**：让智能体在这些任务上执行，记录完整轨迹
3. **分析失败模式**：
   * **重复调用增多** → 调整分页参数或返回数据量
   * **参数无效错误** → 改进工具描述和示例
   * **工具选择错误** → 重新设计工具命名空间（按服务/资源分组）
4. **与 Claude 协作优化**：将评估轨迹导入 Claude Code，让其自动分析并建议：
   * 工具描述是否清晰
   * 参数定义是否有歧义
   * 是否存在可合并的工具

### 工具命名空间化策略

当工具数量增加时，合理的命名约定能显著提升智能体的准确度：

```
推荐：按服务 + 资源分层命名
  asana_projects_search
  asana_users_search
  asana_tasks_create

  slack_messages_search
  slack_channels_list
```

前缀-后缀式的命名能帮助智能体快速定位工具，避免在语义相近的工具间混淆。研究表明，这个看似简单的改进能提升工具调用准确度 5-15%。

***

## 4.2.4 鲁棒性与安全

赋予智能体操作外部世界的能力，必须设置严格的安全护栏。

> **说明** **关于安全主题的分工**
>
> * 本节 (4.2) 侧重于 **单次工具调用的沙箱机制**（如何防止 `rm -rf /`）。
> * [**9.5 企业级安全**](/agentic_ai_guide/di-san-bu-fen-gong-cheng-shi-jian-yu-luo-di/09_agentops/9.5_enterprise.md) 侧重于 **生产环境的整体防护**（网络隔离、PII 保护）。
> * [**11.1 安全边界**](/agentic_ai_guide/di-si-bu-fen-wei-lai-zhan-wang/11_future/11.1_security.md) 侧重于 **对抗性攻击与防御**（提示词注入、越狱）。

### 工具响应的 Token 效率优化

工具返回的数据量直接影响智能体的上下文消耗。以下策略能显著降低 Token 成本：

1. **精简返回数据**：
   * 移除低信息密度的字段（UUID、mime\_type、256px\_image\_url）
   * 保留语义相关字段（name、image\_url、file\_type）
2. **分页与截断**：实现可配置的分页、范围选择与截断，默认参数应保守（如限制 25,000 tokens）。
3. **智能错误响应**：

   * **不推荐**：`Error: ValidationError: field 'sql' type mismatch`
   * **推荐**：`SQL 参数错误：检测到 DELETE 操作，仅允许 SELECT。请改为：SELECT * FROM users WHERE...`

   通过给出具体修正建议，减少智能体的盲目重试。

### 容错设计

* **参数幻觉（Hallucinated Args）**：LLM 可能会编造不存在的参数名。代码层必须做 Schema 校验（Pydantic），如果校验失败，将 **校验错误（Validation Error）** 直接返给 LLM，让它 **自我修正**。
* **工具报错**：如果 API 超时或报错，智能体不应崩溃，而应捕获异常，并尝试重试或换一个工具。

可先运行[确定性离线工具循环夹具](https://github.com/yeasy/agentic_ai_guide/tree/main/examples/offline_smoke.py)，验证工具观察记录、未知工具处理和“必须显式结束”的循环边界，再接入真实外部服务。

**示例：健壮的执行器实现**

```python
class ToolExecutor:
    def execute(self, tool: Tool, params: dict) -> ToolResult:
        try:
            result = tool.run(**params)
            return ToolResult(success=True, data=result)

        except InvalidParameterError as e:
            return ToolResult(
                success=False,
                error=f"参数错误：{e}",
                suggestion="请检查参数格式"
            )

        except ToolNotAvailableError as e:
            return ToolResult(
                success=False,
                error=f"工具暂时不可用：{e}",
                suggestion="稍后重试或使用替代方案"
            )

        except Exception as e:
            return ToolResult(
                success=False,
                error=f"未知错误：{e}",
                suggestion="请联系管理员"
            )
```

### 安全沙箱

代码执行必须在隔离的沙箱中进行（Docker、E2B、WebAssembly），防止恶意代码影响主系统。对于敏感操作（转账、删除、发送消息），必须实施人工确认机制：智能体生成操作请求，用户批准后系统才执行。通过权限校验、输入验证、高风险操作确认和审计日志记录形成完整防御体系。

详见《AI 安全指南》第 7 章关于代码沙箱、权限控制与人工介入的完整配置方案。

## 4.2.5 工具描述与 Prompt 工程

工具描述是智能体是否能正确使用工具的 **关键**。描述会被直接加载到智能体的上下文中，是模型做出工具选择决策的主要依据。

### 描述的关键要素

将工具描述看作“给新员工讲解怎么用这个工具”：

* **明确用途与限制**：例如，不要只说“搜索”，而要说“搜索互联网获取最新信息。不适用于推理或创意任务。”
* **清晰的参数名**：用 `user_id` 而非 `user`；用 `start_date` 而非 `date`
* **具体示例**：提供 few-shot 示例，展示正确的调用方式

```json
{
  "name": "web_search",
  "description": "搜索互联网获取最新信息、事实和时事。返回相关网页摘要。不适用于需要推理、创意或个人经验的任务。",
  "parameters": {
    "type": "object",
    "properties": {
      "query": {
        "type": "string",
        "description": "搜索查询词，应简洁明确"
      }
    }
  },
  "examples": [
    {"query": "2025年诺贝尔物理学奖获得者"},
    {"query": "Python 3.13 新特性"}
  ]
}
```

### Prompt 工程对工具使用的影响

即使工具定义完美，系统 Prompt 中的上下文引导也很关键：

在工具评估中，调整工具描述、添加使用场景往往能显著提升准确度。这表明系统 Prompt 中的上下文引导至关重要。

在 SWE-bench Verified 等基准中，仅通过精化工具描述就能显著改进结果。

## 4.2.6 结构化输出

**结构化输出（Structured Outputs）** 是工具使用能力的增强版本，能够保证 API 响应严格匹配预定义的 JSON Schema。

传统的工具使用方式存在格式不稳定问题：

```python
# 传统方式：模型可能返回不符合 Schema 的数据

response = agent.run("提取用户信息")

# 可能返回：{"name": "张三"} 而非预期的 {"full_name": "张三", "age": null}
```

结构化输出通过 **约束解码** 尽可能保证输出符合 Schema：

```python
# 结构化输出：保证格式正确

response = agent.run(
    "提取用户信息",
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "user_info",
            "schema": {
                "type": "object",
                "properties": {
                    "full_name": {"type": "string"},
                    "age": {"type": ["integer", "null"]}
                },
                "required": ["full_name", "age"]
            }
        }
    }
)

# 保证返回：{"full_name": "张三", "age": null}
```

## 4.2.7 关键应用场景

| 场景         | 说明                    |
| ---------- | --------------------- |
| **数据提取**   | 下游系统依赖无错误、一致的格式       |
| **多智能体架构** | 智能体间通信格式一致性是性能和稳定性的关键 |
| **复杂搜索工具** | 多字段必须精确填充并符合特定模式      |

### 收益

1. **消除解析错误**：无需 try-catch 和重试逻辑
2. **简化代码**：移除复杂的失败回退处理
3. **提升可靠性**：生产环境中工具调用成功率显著提升

### 保证范围声明

> **警告** **Schema-valid ≠ Semantically-valid** 约束解码 / 结构化输出主要保证“输出符合 Schema（字段、类型、格式）”，从而显著降低解析错误与重试成本。但它 **不保证** 以下语义层面的正确性：
>
> * **工具选择正确**：模型仍可能选错工具。
> * **参数值正确**：字段类型正确不意味着填入的值符合业务逻辑。
> * **结果解读正确**：模型对工具返回值的推理仍可能出错。

生产系统仍需在格式保证之上叠加 **二次校验**：

* **范围校验**：参数值是否在合理区间（如日期格式、金额上下限）。
* **权限校验**：该用户/会话是否有权调用此工具、访问此资源。
* **幂等性校验**：重复调用是否会产生副作用（如重复下单）。
* **业务规则校验**：参数组合是否满足业务约束。

当校验失败时，推荐将错误信息回填给模型进行 **自修复**（Self-Repair）：把校验失败原因作为新一轮的 Observation 送回 LLM，让其纠正参数后重新调用。

> **提示** **何时使用这些机制**：
>
> * 工具多、来源多：优先做“工具目录/按需加载”。
> * 批处理、多步编排：优先做“编程式编排 + 沙箱”。
> * 用法复杂：给出正反示例与失败回退。

***

**下一节**: [4.3 工具连接协议：模型上下文与工具服务](/agentic_ai_guide/di-yi-bu-fen-dan-ti-zhi-neng-jia-gou/04_tools/4.3_mcp.md)
