# 8.3 工具执行与结果处理

## 8.3.1 工具执行流程

```mermaid
graph LR
    A["接收调用请求"] --> B["验证参数"]
    B --> C["执行工具"]
    C --> D["处理结果"]
    D --> E["返回给模型"]
```

图 8-3：工具执行流程

## 8.3.2 参数验证

在执行前验证参数的有效性：

```python
def validate_params(tool_name, params, schema):
    # 检查必需参数
    for required in schema.get("required", []):
        if required not in params:
            raise ValueError(f"缺少必需参数: {required}")

    # 检查参数类型
    for key, value in params.items():
        expected_type = schema["properties"][key]["type"]
        if not isinstance(value, TYPE_MAP[expected_type]):
            raise TypeError(f"参数 {key} 类型错误")

    # 检查枚举值
    for key, value in params.items():
        if "enum" in schema["properties"][key]:
            if value not in schema["properties"][key]["enum"]:
                raise ValueError(f"参数 {key} 值无效")
```

## 8.3.3 执行策略

### 同步执行

简单场景，等待执行完成：

```python
result = execute_tool(tool_name, params)
```

### 异步执行

IO 密集型或耗时操作：

```python
async def execute_tools(tool_calls):
    tasks = [execute_tool_async(tc) for tc in tool_calls]
    results = await asyncio.gather(*tasks)
    return results
```

### 超时控制

防止工具执行无限等待：

```python
try:
    result = await asyncio.wait_for(
        execute_tool(tool_name, params),
        timeout=30.0
    )
except asyncio.TimeoutError:
    result = {"error": "执行超时"}
```

## 8.3.4 结果格式化

将工具结果格式化为模型易理解的形式：

**简洁输出**

```jsonc
{
  "status": "success",
  "data": {
    "temperature": 25,
    "condition": "晴"
  }
}
```

**包含上下文**

```jsonc
{
  "query": "北京天气",
  "result": {
    "city": "北京",
    "temperature": 25,
    "condition": "晴",
    "humidity": 45
  },
  "data_time": "2026-03-01 10:00"
}
```

## 8.3.5 错误处理

工具执行可能失败，需要优雅处理：

### 错误类型分类

| 错误类型 | 处理方式 | 反馈给模型  |
| ---- | ---- | ------ |
| 参数错误 | 不执行  | 说明具体问题 |
| 执行失败 | 记录日志 | 返回错误信息 |
| 超时   | 终止执行 | 建议稍后重试 |
| 权限不足 | 拒绝执行 | 说明权限要求 |

### 错误信息模板

```json
{
  "status": "error",
  "error_type": "execution_failed",
  "message": "无法连接到天气服务",
  "suggestion": "请稍后再试或换一个城市查询"
}
```

## 8.3.6 结果注入上下文

工具结果需要正确注入对话上下文：

```jsonc
{
  "role": "assistant",
  "content": null,
  "tool_calls": [{
    "id": "call_abc123",
    "type": "function",
    "function": {
      "name": "get_weather",
      "arguments": "{\"city\": \"北京\"}"
    }
  }]
},
{
  "role": "tool",
  "tool_call_id": "call_abc123",
  "content": "{\"temperature\": 25, \"condition\": \"晴\"}"
}
```

## 8.3.7 结果压缩

工具返回大量数据时可能需要压缩：

```python
def compress_result(result, max_tokens=500):
    if count_tokens(result) > max_tokens:
        # 提取关键信息
        return summarize(result)
    return result
```

## 8.3.8 多轮工具调用

复杂任务可能需要多轮工具调用：

```mermaid
sequenceDiagram
    participant M as 模型
    participant A as 应用

    M->>A: 调用工具 A
    A->>M: 工具 A 结果
    Note over M: 分析结果，决定下一步
    M->>A: 调用工具 B
    A->>M: 工具 B 结果
    Note over M: 综合结果，生成响应
    M->>A: 最终响应
```

图 8-4：多轮工具调用流程

每轮结果都成为上下文的一部分，影响后续决策。

## 8.3.9 安全考虑

工具执行涉及安全风险：

1. **输入验证**：防止注入攻击
2. **权限控制**：验证操作权限
3. **操作审计**：记录敏感操作
4. **确认机制**：危险操作需人工确认

## 8.3.10 高级工具执行技术

随着智能体需要使用的工具数量增长，传统的工具调用方式面临挑战。以下介绍两项高级技术：

### 工具搜索工具

**问题**：当连接多个 MCP 服务器时，工具定义可能消耗大量 Token（规模取决于工具数量、Schema 复杂度与描述长度）：

**解决方案**：不预加载所有工具，而是按需发现。

```json
{
  "tools": [
    {"type": "tool_search_tool", "name": "tool_search"},
    {
      "name": "github.createPullRequest",
      "defer_loading": true
    }
  ]
}
```

**效果（常见观察）**：

* 只暴露必要工具可以显著降低上下文开销
* 工具选择更聚焦，误调用与歧义通常会减少

### 编程式工具调用

**问题**：传统工具调用有两个瓶颈：

1. 中间结果污染上下文（分析 10MB 日志文件，全部进入上下文）
2. 每次调用需要一次推理，开销大

**解决方案**：让模型生成受限的工作流计划，由服务端在沙箱和权限边界内执行；不要让模型生成的任意代码直接持有团队、费用、客户或生产系统凭据。

```python
# 模型只生成声明式计划；服务端负责鉴权、执行、脱敏和审计
workflow = {
    "operation": "expense_budget_check",
    "team": "engineering",
    "period": "Q3",
    "output": "over_budget_summary",
}

result = await workflow_runner.run(
    workflow,
    caller=user_identity,
    policy_checks=["team_scope", "read_only", "pii_redaction"],
    network_scope="internal_tools_only",
)
return result.redacted_summary
```

**效果（常见观察）**：

* 上下文只接收最终结果而非原始数据，通常能显著降低 Token 消耗
* 降低中间结果“污染上下文”的概率，并减少不必要的多轮推理

**使用指南**：

| 技术                        | 适用场景                   |
| ------------------------- | ---------------------- |
| Tool Search Tool          | 工具定义 >10K Token、10+ 工具 |
| Programmatic Tool Calling | 处理大数据集只需摘要、3+ 步依赖工具调用  |

## 8.3.11 工程实战：端到端数据分析助手

以下展示一个完整的数据分析助手工作流，包含规划、执行、结果处理和上下文更新。

**场景**：用户上传 CSV 文件并要求：“分析上季度的销售趋势，并画图展示。”

**流程图**：

```mermaid
graph TB
    User["用户输入"] --> Plan["规划器(Planner)"]
    Plan --> Step1["步骤1: 读取CSV"]
    Step1 --> Tool1["调用 read_csv"]
    Tool1 --> Res1["返回 DataFrame 摘要"]
    Res1 --> Step2["步骤2: 分析数据"]
    Step2 --> Tool2["调用 python_repl"]
    Tool2 --> Res2["生成图表(Base64)"]
    Res2 --> Final["生成最终回复"]
```

图 8-5：端到端数据分析工作流

**关键代码实现逻辑**：

```python
async def run_analysis_agent(user_query, context):
    messages = context + [{"role": "user", "content": user_query}]

    # 1. 规划阶段
    plan = await llm.plan(messages)
    # output: 1. read_csv, 2. analyze_trend, 3. plot_chart

    results = {}

    for step in plan.steps:
        # 2. 执行阶段
        tool_name = step.tool
        tool_args = step.args

        try:
            # 3. 结果处理
            # 仅截取前5行数据作为上下文，避免 Token 爆炸
            raw_result = await tools.execute(tool_name, tool_args)
            processed_result = truncate_dataframe(raw_result)

            # 注入当前步骤结果到上下文
            messages.append({
                "role": "tool",
                "tool_call_id": step.tool_call_id,
                "content": processed_result
            })

        except Exception as e:
            # 错误恢复机制
            messages.append({"role": "system", "content": f"工具执行失败: {str(e)}，请尝试其他方法"})
            continue

    # 4. 生成最终回复
    final_response = await llm.chat(messages)
    return final_response
```

## 8.3.12 核心指标与评估

在生产环境中，需要关注以下指标来衡量工具执行系统的健康度：

| 指标           | 目标值（示意）    | 说明                        |
| ------------ | ---------- | ------------------------- |
| **执行成功率**    | 以基线提升为目标   | 工具调用无异常（Crash/Timeout）的比例 |
| **参数准确率**    | 以基线提升为目标   | 模型生成的参数符合 Schema 定义且逻辑正确  |
| **平均延迟**     | 取决于工具与 SLO | 工具本身的执行耗时（不含 LLM 推理）      |
| **幻觉率**      | 越低越好       | 调用了不存在的工具或虚构了参数           |
| **Token 效率** | 越高越好       | 原始工具结果 vs 注入上下文的结果大小      |

**优化建议**：

* 对于高频且低延迟要求的工具（如查天气），使用本地逻辑而非 LLM 规划。
* 对于易错的复杂参数（如 SQL），在 System Prompt 中提供 Few-Shot 示例。


---

# 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/context_engineering_guide/di-san-bu-fen-jin-jie-ji-shu-yu-jia-gou/08_tools/8.3_tool_execution.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.
