# 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 超时或报错，智能体不应崩溃，而应捕获异常，并尝试重试或换一个工具。

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

```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)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yeasy.gitbook.io/agentic_ai_guide/di-yi-bu-fen-dan-ti-zhi-neng-jia-gou/04_tools/4.2_tool_use.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
