# 联网工具

DeepSeek 提供两个服务端工具，让模型具备与 DeepSeek 网页端一致的联网能力。是否联网由模型判断，搜索和抓取都在服务端完成，客户端不需要执行任何工具。

如果要在自己的程序里直接调用搜索和抓取，请使用 [网页搜索与抓取](https://api-docs.deepseek.com/zh-cn/guides/search.md) 接口。

| 能力                               | 开启方式                          | 说明                              |
| -------------------------------- | ----------------------------- | ------------------------------- |
| [联网搜索](#web-search)              | 声明 `deepseek_web_search`，关闭思考 | 模型根据提问自动发起搜索，并附引用作答             |
| [深度思考搜索](#search-while-thinking) | 声明 `deepseek_web_search`，开启思考 | 模型在多步推理中自主搜索、打开网页、页内查找，边推理边检索求证 |
| [阅读链接](#read-links)              | 声明 `deepseek_read_url`        | 模型自动识别用户消息中的链接，抓取网页内容并结合上下文作答   |

可在 Messages API、Responses API 与 Chat Completions API 中使用。本页大部分内容描述的是 Messages API 中的格式，另外两个协议中的格式见下文 [Responses API](#responses-api) 与 [Chat Completions API](#chat-completions-api)。

请使用 `deepseek-flash` 模型。

***

<a id="declare-tools"></a>

## 声明工具

在 `tools` 中声明要开启的工具。下面的请求同时开启了两个工具：

**Messages**

```bash
curl https://api.deepseek.com/anthropic/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: ${DEEPSEEK_API_KEY}" \
  -d '{
    "model": "deepseek-flash",
    "thinking": {"type": "enabled"},
    "tools": [
      {"type": "deepseek_web_search", "name": "deepseek_web_search"},
      {"type": "deepseek_read_url", "name": "deepseek_read_url"}
    ],
    "messages": [{"role": "user", "content": "DeepSeek V4.1 有哪些更新？"}],
    "stream": true
  }'
```

**Responses**

```bash
curl https://api.deepseek.com/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${DEEPSEEK_API_KEY}" \
  -d '{
    "model": "deepseek-flash",
    "reasoning": {"effort": "high"},
    "tools": [
      {"type": "deepseek_web_search"},
      {"type": "deepseek_read_url"}
    ],
    "input": "DeepSeek V4.1 有哪些更新？",
    "stream": true
  }'
```

**Chat Completions**

```bash
curl https://api.deepseek.com/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${DEEPSEEK_API_KEY}" \
  -d '{
    "model": "deepseek-flash",
    "thinking": {"type": "enabled"},
    "tools": [
      {"type": "deepseek_web_search"},
      {"type": "deepseek_read_url"}
    ],
    "messages": [{"role": "user", "content": "DeepSeek V4.1 有哪些更新？"}],
    "stream": true
  }'
```

只需要阅读链接、不需要搜索时，只声明 `deepseek_read_url`。

`tool_choice` 不能指定 `deepseek_web_search` 或 `deepseek_read_url`，否则返回 `400`：是否搜索或阅读链接由模型判断。`tool_choice` 为 `none` 时关闭全部工具，包括阅读链接。

***

<a id="web-search"></a>

## 联网搜索

关闭思考时，由模型判断是否搜索，并带引用作答，与 DeepSeek 网页端的联网搜索一致。

- 一次搜索可以包含多个查询词，全部列在 `input.queries` 中。
- 每次搜索产生一个 `input.action` 与 `kind` 都为 `search` 的 `server_tool_use` 块，以及一个 `web_search_tool_result` 块。回答通过 [`citations`](#citations) 引用搜索结果。
- 要关闭搜索，不声明 `deepseek_web_search` 即可；只声明 `deepseek_read_url` 仍可阅读链接。

关闭思考、提问“What is the population of Iceland?”的请求返回如下。这次搜索返回了三条结果，示例中只保留一条，`encrypted_content` 做了截短。

```json
{
  "id": "18f3b95b-bf3c-4ffb-8c90-ad50d7cfb211",
  "type": "message",
  "role": "assistant",
  "model": "deepseek-flash",
  "content": [
    {
      "type": "server_tool_use",
      "id": "srvtoolu_s_00_72b1a35619ec4611884415c48d35ba34",
      "name": "deepseek_web_search",
      "input": {
        "action": "search",
        "queries": ["Iceland population 2024", "Iceland population 2025"]
      },
      "caller": {"type": "direct"},
      "kind": "search"
    },
    {
      "type": "web_search_tool_result",
      "tool_use_id": "srvtoolu_s_00_72b1a35619ec4611884415c48d35ba34",
      "content": [
        {
          "type": "web_search_result",
          "title": "2024年冰岛人口总数、净移民人口数、劳动人口数及人口性别、年龄及城乡结构分析",
          "url": "https://www.huaon.com/channel/globaldata/1112834.html",
          "encrypted_content": "6sesWdNHoulpcfritukyowXu...",
          "page_age": "2025-10-15T16:00:00+00:00",
          "snippet": "华经产业研究院数据显示：冰岛是高收入国家之一，2024年冰岛人口总数为40.46万人，比上年增长了1.13万人...",
          "site_name": "华经情报网",
          "site_icon": "https://cdn.deepseek.com/site-icons/huaon.com"
        }
      ],
      "kind": "search"
    },
    {
      "type": "text",
      "text": "Iceland's population is approximately **394,000** (as of early 2026), based on data from Statistics Iceland",
      "citations": [
        {
          "type": "web_search_result_location",
          "url": "https://wallstreetcn.com/livenews/3197120",
          "title": "快讯：根据冰岛统计局（Statistics Iceland）的一份预测，冰岛人口将在四分之一个世纪内达到50万，高于2026年初的39.4 万。",
          "encrypted_index": "",
          "cited_text": "Iceland's population is approximately **394,000** (as of early 2026), based on data from Statistics Iceland"
        }
      ]
    },
    {
      "type": "text",
      "text": ".\n\nDifferent sources may have slight variations due to different statistical time points or estimation methods. For reference, data from 2024 shows a population of approximately **404,600** at that time",
      "citations": [
        {
          "type": "web_search_result_location",
          "url": "https://www.huaon.com/channel/globaldata/1112834.html",
          "title": "2024年冰岛人口总数、净移民人口数、劳动人口数及人口性别、年龄及城乡结构分析",
          "encrypted_index": "",
          "cited_text": ".\n\nDifferent sources may have slight variations due to different statistical time points or estimation methods. For reference, data from 2024 shows a population of approximately **404,600** at that time"
        }
      ]
    },
    {"type": "text", "text": "."}
  ],
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 1905,
    "cache_creation_input_tokens": 0,
    "cache_read_input_tokens": 0,
    "output_tokens": 72,
    "service_tier": "standard",
    "server_tool_use": {"web_search_requests": 1, "web_fetch_requests": 0, "tool_search": 2, "tool_fetch": 0, "tool_image_search": 0}
  }
}
```

<a id="image-search"></a>

### 图片搜索

图片搜索属于 `deepseek_web_search` 工具：用户消息带有图片时，模型可以按图片搜索，[深度思考搜索](#search-while-thinking) 时同样如此。

图片搜索的调用与结果，结构和联网搜索相同，有三点区别：

- `kind` 为 `image_search`，深度思考搜索中为 `deep_image_search`。
- 没有查询词，`queries` 为空数组。
- 每条结果多一个 `image_url` 字段，是图片在原网站上的地址，仅供展示。它可能不存在，也不保证能访问。

计费见 [用量与计费](#billing)。

***

<a id="search-while-thinking"></a>

## 深度思考搜索

开启思考时，`deepseek_web_search` 以深度思考搜索的方式工作：模型在多步思考中搜索、打开网页、页内查找，与 DeepSeek 网页端的深度思考搜索一致。

- 模型最多调用约 20 次工具后作答。

| `content[].input.action` | 步骤         |
| ------------------------ | ---------- |
| `search`                 | 联网搜索       |
| `open_page`              | 打开网页       |
| `find_in_page`           | 在已打开的网页中查找 |

- 每一步都是一个 `kind` 为 `deep_search` 的 `server_tool_use` 块，后面跟着它的结果。模型一次调用多个工具时，先下发全部调用块，再下发结果块。
- 这里的打开网页属于 `deepseek_web_search`：模型打开的是自己搜索到的网页。它与 `deepseek_read_url` 负责的阅读链接（阅读用户给出的链接）不同。
- 打开的网页只返回 URL、标题和发布时间：`data` 为空字符串，也没有 `signature`。

深度思考搜索中的 [图片搜索](#image-search)，`kind` 为 `deep_image_search`。

提问“Which is taller, the Eiffel Tower or the Tokyo Tower? Check their official sites.”的请求，依次返回以下内容块：

```text
thinking
server_tool_use         search        4 queries
web_search_tool_result
thinking
server_tool_use         open_page     https://www.toureiffel.paris/en/the-monument/key-figures
server_tool_use         open_page     https://en.tokyotower.co.jp/company/
web_fetch_tool_result
web_fetch_tool_result
thinking
server_tool_use         open_page     https://en.tokyotower.co.jp/
server_tool_use         find_in_page  pattern "330"
server_tool_use         find_in_page  pattern "meter"
server_tool_use         find_in_page  pattern "333"
web_fetch_tool_result   (4 results)
thinking
server_tool_use         search        3 queries
web_search_tool_result
thinking
server_tool_use         open_page     (2 calls)
web_fetch_tool_result   (2 results)
thinking
text                    4 blocks, 3 of them with citations
```

其中一次调用及其结果如下。`find_in_page` 的结果形式相同，`title` 为 `null`。

```json
[
  {
    "type": "server_tool_use",
    "id": "srvtoolu_ds_02_7e545ef1967b433eb8c0bfdfca520c89",
    "name": "deepseek_web_search",
    "input": {"action": "open_page", "url": "https://en.tokyotower.co.jp/company/"},
    "caller": {"type": "direct"},
    "kind": "deep_search"
  },
  {
    "type": "web_fetch_tool_result",
    "tool_use_id": "srvtoolu_ds_02_7e545ef1967b433eb8c0bfdfca520c89",
    "content": {
      "type": "web_fetch_result",
      "url": "https://en.tokyotower.co.jp/company/",
      "content": {
        "type": "document",
        "source": {"type": "text", "media_type": "text/plain", "data": ""},
        "title": "Tokyo Tower is a Tokyo landmark, standing 333 meters tall."
      },
      "published_at": null
    },
    "kind": "deep_search"
  }
]
```

***

<a id="read-links"></a>

## 阅读链接

最后一条用户消息包含 URL 时，`deepseek_read_url` 让模型阅读这些网页并据此作答，与 DeepSeek 网页端的阅读链接一致。

- 只在最后一条用户消息中识别 URL，重复的 URL 只算一个。最多考虑消息中前 10 个不同的 URL，由模型决定读其中哪些。
- 开启思考且声明了 `deepseek_web_search` 时，本轮使用 [深度思考搜索](#search-while-thinking)，不单独阅读链接。其他情况下（关闭思考，或只声明了 `deepseek_read_url`）才会阅读链接。一轮指从一条用户消息到模型给出最终回答的过程，对应一次请求。
- 每阅读一个网页，产生一个 `input.action` 为 `read_link`、带 `url` 的 `server_tool_use` 块，以及一个 `kind` 为 `read_link` 的 `web_fetch_tool_result` 块。同时阅读多个链接时，先下发全部调用块，再下发结果块。
- 结果中带有网页的 URL、标题和发布日期。网页正文不在块中返回，而是加密后放在 `signature` 里。块中的 `url`、`title`、`data`、`published_at` 仅供展示，回传前修改它们不会产生影响。
- 同一轮阅读多个链接时，单个网页可用的长度会减少，较长的网页会被截断。
- 开启 [模型内容安全](https://api-docs.deepseek.com/zh-cn/guides/safety.md) 后，阅读结果通过审核才下发，未通过的网页返回 `url_not_allowed` 错误。

***

<a id="response-blocks"></a>

## 响应内容块

每次调用产生一个 `server_tool_use` 块和一个结果块。流式输出时，这两种块的内容一次性出现在 `content_block_start` 中，不会分段下发。

请按 `tool_use_id` 关联调用与结果。同时阅读多个网页或开启模型内容安全时，结果不一定紧跟在调用之后。每个调用都会有结果：调用未完成时，结果为 `unavailable` 错误。

### server\_tool\_use

```json
{
  "type": "server_tool_use",
  "id": "srvtoolu_s_00_3f2a9c...",
  "name": "deepseek_web_search",
  "input": {"action": "search", "queries": ["DeepSeek V4.1"]},
  "caller": {"type": "direct"},
  "kind": "search"
}
```

| `content[].input.action` | `content[].name`      | `input` 中的其他字段     |
| ------------------------ | --------------------- | ------------------ |
| `search`                 | `deepseek_web_search` | `queries`：本次调用的搜索词 |
| `open_page`              | `deepseek_web_search` | `url`              |
| `find_in_page`           | `deepseek_web_search` | `url` 与 `pattern`  |
| `read_link`              | `deepseek_read_url`   | `url`              |

- `name` 是开启这项能力的工具名，与请求中声明的一致。它不在 Anthropic SDK 的类型定义中，但 SDK 运行时不校验。`input.action` 与 `kind` 是 DeepSeek 扩展字段，`kind` 标明这次调用属于哪种能力：`search`（联网搜索）、`deep_search`（深度思考搜索）、`read_link`（阅读链接）、`image_search` 或 `deep_image_search`（[图片搜索](#image-search)）。

### web\_search\_tool\_result

```json
{
  "type": "web_search_tool_result",
  "tool_use_id": "srvtoolu_s_00_3f2a9c...",
  "content": [
    {
      "type": "web_search_result",
      "title": "...",
      "url": "https://example.com/news",
      "encrypted_content": "...",
      "page_age": "2026-01-02T03:04:05+00:00",
      "snippet": "...",
      "site_name": "Example News",
      "site_icon": "https://cdn.deepseek.com/site-icons/example.com"
    }
  ],
  "kind": "search"
}
```

- `content` 可能为空数组。搜索失败时为 `[{"type": "web_search_tool_result_error", "error_code": "unavailable"}]`。
- `snippet`、`site_name`、`site_icon` 是用于展示的 DeepSeek 扩展字段，`site_name` 与 `site_icon` 可能为 `null`，回传时会被忽略。
- 图片搜索的结果还有 `image_url`，见 [图片搜索](#image-search)。
- `page_age` 为 RFC 3339 格式的 UTC 时间戳或 `null`。

### web\_fetch\_tool\_result

```json
{
  "type": "web_fetch_tool_result",
  "tool_use_id": "srvtoolu_rl_01_9c1d...",
  "content": {
    "type": "web_fetch_result",
    "url": "https://example.com/a",
    "content": {
      "type": "document",
      "source": {"type": "text", "media_type": "text/plain", "data": ""},
      "title": "页面标题"
    },
    "published_at": "2026-01-01"
  },
  "kind": "read_link",
  "signature": "q3J0b1RmZ1c4cE1x..."
}
```

- 网页正文不返回，`data` 恒为空字符串。`read_link` 的网页加密后放在 `signature` 里，请原样回传该块，网页才会拼回上下文。详见 [多轮对话](#multi-turn)。
- `published_at`：`read_link` 为网页上提取到的日期，格式不固定；深度思考搜索中打开的网页为 RFC 3339 时间戳。两者都可能为 `null`。
- 抓取失败时，`content` 为 `{"type": "web_fetch_tool_result_error", "error_code": "..."}`，且不带 `signature`：

| `error_code`         | 含义                         |
| -------------------- | -------------------------- |
| `url_not_accessible` | 无法读取该链接                    |
| `url_not_allowed`    | 不允许读取该链接，或网页未通过模型内容安全审核    |
| `unavailable`        | 服务不可用、深度思考搜索中打开网页失败，或调用未完成 |

***

<a id="citations"></a>

## 引用

回答引用了来源时，其 `text` 块带有 `citations`：

```json
{
  "type": "text",
  "text": "上海今天多云。",
  "citations": [
    {
      "type": "web_search_result_location",
      "url": "https://example.com/weather",
      "title": "...",
      "encrypted_index": "",
      "cited_text": "上海今天多云。"
    }
  ]
}
```

- 流式输出时，每条引用通过当前 `text` 块上的 `citations_delta` 事件下发。
- 一个 `text` 块带上引用后，之后的正文会另起一个新的 `text` 块，因此每个块的引用只对应它自己的文本。同一个块内同一 URL 最多出现一次。
- `type` 恒为 `web_search_result_location`，深度思考搜索中打开的网页也是如此。`cited_text` 是当前块截至该引用处的回答文本，不是从来源中摘录的原文。`encrypted_index` 恒为空字符串，`title` 可能为 `null`。
- 回传时会忽略引用。

***

## 流式输出

一次开启思考、搜索一次的请求，事件顺序如下：

```text
message_start
content_block_start (thinking) → thinking_delta … → signature_delta → content_block_stop
content_block_start (server_tool_use) → content_block_stop
content_block_start (web_search_tool_result) → content_block_stop
content_block_start (thinking) → thinking_delta … → signature_delta → content_block_stop
content_block_start (text) → text_delta … → citations_delta … → content_block_stop
content_block_start (text) → text_delta … → content_block_stop
message_delta
message_stop
```

- 开启思考时，`message_start` 之后会立即打开一个 `thinking` 块；如果模型先去搜索，这个块可能为空。
- `message_start` 中的 `usage` 只包含第一步推理，最终用量以 `message_delta` 为准。
- 开启 [`title`](https://api-docs.deepseek.com/zh-cn/guides/conversation_title.md) 时，`message_delta` 还会带上会话标题。
- 没有新内容产生时，流式响应会发送 `: keep-alive` 注释；非流式请求会在 JSON 之前收到换行符。详见 [限速与隔离](https://api-docs.deepseek.com/zh-cn/quick_start/rate_limit.md)。

### 结束原因

| `stop_reason` | 含义                                                                                         |
| ------------- | ------------------------------------------------------------------------------------------ |
| `end_turn`    | 回答完成                                                                                       |
| `max_tokens`  | 输出达到最大长度，回答被截断；或搜索、阅读链接之后上下文已用尽                                                            |
| `refusal`     | 被内容审核拒答，见 [模型内容安全](https://api-docs.deepseek.com/zh-cn/guides/safety.md#handling-refusals) |

***

<a id="multi-turn"></a>

## 多轮对话

每次请求都携带完整的历史，并把之前每一轮的回复原样回传，保留 `kind` 和 `signature` 字段。

- 搜索结果、打开的网页以及之前轮次的思考不会进入后续轮次的上下文，只保留回答正文。
- 带有联网工具块的历史消息，也可以发给没有声明这些工具的请求。
- 阅读链接得到的网页由 `signature` 还原，拼到该轮用户消息的末尾，模型在后续轮次中就能引用该网页。没有有效的 `signature` 时，该网页不会拼回，请求仍然正常执行。

例如，第一轮阅读了一个链接，第二轮把这条回复原样回传。示例中的 id 与 `signature` 做了截短。

**Messages**

```bash
curl https://api.deepseek.com/anthropic/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: ${DEEPSEEK_API_KEY}" \
  -d '{
    "model": "deepseek-flash",
    "tools": [
      {"type": "deepseek_web_search", "name": "deepseek_web_search"},
      {"type": "deepseek_read_url", "name": "deepseek_read_url"}
    ],
    "messages": [
      {"role": "user", "content": "用一句话总结 https://example.com/ 的内容"},
      {
        "role": "assistant",
        "content": [
          {
            "type": "server_tool_use",
            "id": "srvtoolu_rl_00_0efde247...",
            "name": "deepseek_read_url",
            "input": {"action": "read_link", "url": "https://example.com"},
            "caller": {"type": "direct"},
            "kind": "read_link"
          },
          {
            "type": "web_fetch_tool_result",
            "tool_use_id": "srvtoolu_rl_00_0efde247...",
            "content": {
              "type": "web_fetch_result",
              "url": "https://example.com",
              "content": {
                "type": "document",
                "source": {"type": "text", "media_type": "text/plain", "data": ""},
                "title": "Example Domain"
              },
              "published_at": null
            },
            "kind": "read_link",
            "signature": "tQU8k+8Ko7MY5XDAvJd0..."
          },
          {"type": "text", "text": "example.com 是专门留给文档示例使用的域名。"}
        ]
      },
      {"role": "user", "content": "原样引用这个网页的第一句话"}
    ]
  }'
```

**Responses**

```bash
curl https://api.deepseek.com/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${DEEPSEEK_API_KEY}" \
  -d '{
    "model": "deepseek-flash",
    "tools": [
      {"type": "deepseek_web_search"},
      {"type": "deepseek_read_url"}
    ],
    "input": [
      {"role": "user", "content": "用一句话总结 https://example.com/ 的内容"},
      {
        "type": "web_search_call",
        "id": "srvtoolu_rl_00_0efde247...",
        "status": "completed",
        "kind": "read_link",
        "action": {"type": "open_page", "url": "https://example.com"},
        "page": {"url": "https://example.com", "title": "Example Domain", "published_at": null},
        "signature": "tQU8k+8Ko7MY5XDAvJd0..."
      },
      {
        "type": "message",
        "role": "assistant",
        "content": [{"type": "output_text", "text": "example.com 是专门留给文档示例使用的域名。"}]
      },
      {"role": "user", "content": "原样引用这个网页的第一句话"}
    ]
  }'
```

**Chat Completions**

```bash
curl https://api.deepseek.com/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${DEEPSEEK_API_KEY}" \
  -d '{
    "model": "deepseek-flash",
    "tools": [
      {"type": "deepseek_web_search"},
      {"type": "deepseek_read_url"}
    ],
    "messages": [
      {"role": "user", "content": "用一句话总结 https://example.com/ 的内容"},
      {
        "role": "assistant",
        "content": "example.com 是专门留给文档示例使用的域名。",
        "server_tool_calls": [
          {
            "index": 0,
            "reasoning_content": "",
            "calls": [
              {
                "index": 0,
                "id": "srvtoolu_rl_00_0efde247...",
                "type": "deepseek_read_url",
                "kind": "read_link",
                "action": {"type": "read_link", "url": "https://example.com"},
                "status": "completed",
                "page": {"url": "https://example.com", "title": "Example Domain", "published_at": null},
                "signature": "tQU8k+8Ko7MY5XDAvJd0..."
              }
            ]
          }
        ]
      },
      {"role": "user", "content": "原样引用这个网页的第一句话"}
    ]
  }'
```

***

<a id="continue-generation"></a>

## 继续生成

要继续一条被中断的回复，让消息列表以这条未完成的 `assistant` 消息结尾。响应只包含新生成的部分。

- 使用过 `deepseek_web_search` 或 `deepseek_read_url` 的回复不能续写，会返回 `400`，请改为重发上一次请求。
- 在 Chat Completions API 中，需要在 beta 接口上给最后一条 `assistant` 消息加 `prefix: true`。Responses API 不支持继续生成。

**Messages**

```bash
curl https://api.deepseek.com/anthropic/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: ${DEEPSEEK_API_KEY}" \
  -d '{
    "model": "deepseek-flash",
    "safety_check": {"level": "high"},
    "messages": [
      {"role": "user", "content": "写一首关于秋天的短诗"},
      {"role": "assistant", "content": "秋风起，"}
    ]
  }'
```

**Chat Completions**

```bash
curl https://api.deepseek.com/beta/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${DEEPSEEK_API_KEY}" \
  -d '{
    "model": "deepseek-flash",
    "safety_check": {"level": "high"},
    "messages": [
      {"role": "user", "content": "写一首关于秋天的短诗"},
      {"role": "assistant", "content": "秋风起，", "prefix": true}
    ]
  }'
```

***

<a id="billing"></a>

## 用量与计费

最终 `message_delta`（或非流式响应）中的 `usage` 是整个请求的计费用量，按各步推理累加：

| 字段                                                             | 含义                                  |
| -------------------------------------------------------------- | ----------------------------------- |
| `input_tokens`                                                 | 未命中上下文缓存的输入 Token                   |
| `cache_read_input_tokens`                                      | 命中上下文缓存的输入 Token                    |
| `output_tokens`                                                | 输出 Token                            |
| `output_tokens_details.thinking_tokens`                        | 其中的思考 Token，开启思考时返回                 |
| `cache_creation_input_tokens`                                  | 恒为 `0`                              |
| `server_tool_use.web_search_requests`、`web_fetch_requests`     | 响应中搜索结果块、抓取结果块的数量（含错误块），仅供展示，不是计费次数 |
| `server_tool_use.tool_search`、`tool_fetch`、`tool_image_search` | 计费的搜索次数（不含图片搜索）、抓取次数、图片搜索次数         |

工具调用另行计费，按 [模型 & 价格](https://api-docs.deepseek.com/zh-cn/quick_start/pricing.md#web-tools-pricing) 中网页搜索、图片搜索和网页抓取的价格计算，与 Search、Fetch API 同价：

- 网页搜索：一次搜索调用返回了结果时，按它包含的查询词条数计费，例如一次调用包含 3 个查询词时计 3 次。调用失败或没有返回任何结果时不计费。
- 图片搜索：每张图片计 1 次，模型框选图片中的区域时每个区域另计 1 次。搜索失败或没有搜到结果时不计费。
- 网页抓取（阅读链接）：按成功抓取的网页数计费，包括开启模型内容安全后结果被替换为 `url_not_allowed` 或 `unavailable` 错误的网页。抓取失败的链接不计费。
- 网页抓取（深度思考搜索）：打开网页只在实际从网络抓取时计费。再次打开同一网页、在网页中翻页、打开内容已随搜索结果返回的网页均不计费。
- 页内查找不计费。

***

## 错误

输入命中内容审核时返回 `400 Content Exists Risk`。请求的上下文超过模型上限时返回 `400`。

常见错误信息：

| 原因                                                         | `error.message`                                                                                                                                   |
| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| 同一个工具声明了两次                                                 | ``tools: `deepseek_web_search` can only be declared once``                                                                                        |
| 声明了其他服务端工具                                                 | ``tools: other tools cannot be used together with `deepseek_web_search`, `deepseek_read_url`, `safety_check` or `title` yet``                     |
| 工具带有 `allowed_domains`、`blocked_domains` 或 `user_location` | `` tools: `allowed_domains` is not supported by `deepseek_web_search` ``                                                                          |
| `tool_choice` 指定了已声明的联网工具                                  | ``tool_choice: `deepseek_web_search` cannot be forced``                                                                                           |
| `safety_check` 没有合法的 `level`                               | `` safety_check: `level` must be `low` or `high` ``                                                                                               |
| 要续写的回复使用过联网工具                                              | ``messages: the last `assistant` message used `deepseek_web_search` or `deepseek_read_url` and cannot be continued; resend the previous request`` |

<a id="generation-failures"></a>

### 生成失败

回答开始生成之后出错时（例如推理超时或中断），HTTP 状态码已经是 `200`，响应以错误结束，并带上 `usage`。失败之前已经执行的推理、搜索与阅读照常计费。

| 协议               | 流式                                                   | 非流式                                                      |
| ---------------- | ---------------------------------------------------- | -------------------------------------------------------- |
| Messages         | 以 `error` 事件结束，之后没有 `message_delta` 与 `message_stop` | 响应体为 `{"type": "error", "error": {...}, "usage": {...}}` |
| Responses        | 以 `response.failed` 事件结束                             | `status` 为 `failed`，`error.code` 为 `server_error`        |
| Chat Completions | 最后一个 chunk 带有 `error`，`choices` 为空，之后没有 `[DONE]`     | 响应体为 `{"error": {...}, "usage": {...}}`                  |

```text
event: error
data: {"type":"error","error":{"type":"api_error","message":"The model failed to generate a complete response. Please retry."},"usage":{...}}
```

非流式响应的状态码是 `200`，SDK 不会抛出异常，请检查响应体中的 `error`（Responses API 检查 `status`）。

***

<a id="responses-api"></a>

## Responses API

同样的工具也可以在 [Responses API](https://api-docs.deepseek.com/zh-cn/guides/responses_api.md) 中使用：在 `tools` 中声明，`safety_check` 与 `title` 放在顶层，与 Messages API 一致。`tool_choice: "required"` 按 `auto` 处理。

```json
{
  "model": "deepseek-flash",
  "input": "DeepSeek V4.1 有什么新功能？",
  "tools": [
    {"type": "deepseek_web_search"},
    {"type": "deepseek_read_url"}
  ],
  "safety_check": {"level": "high"},
  "stream": true
}
```

### 请求

- 不能与 `web_search` 工具同时声明，也不支持 `custom`、`namespace`、`tool_search` 工具，均返回 `400`。其他无法识别的工具类型会被忽略。
- `text.format` 不为 `text`、传入 `top_logprobs`、`previous_response_id` 或 `conversation` 时返回 `400`。响应中 `store` 为 `false`。
- `input` 中包含 `item_reference` 或无法识别的 item 类型时返回 `400`。
- 部分参数会被忽略，见 [被忽略的参数](https://api-docs.deepseek.com/zh-cn/guides/build_a_chatbot.md#ignored-parameters)。
- `instructions` 以及 `system`、`developer` 消息会合并为一条 system 提示词。
- 若 `input` 以 assistant 的 `message` 或 `reasoning` item 结尾，会返回 `400`（Responses API 不支持继续生成）。

### 输出

每次工具调用是一个 `web_search_call` item，带 DeepSeek 扩展字段 `kind`：

```json
{
  "type": "web_search_call",
  "id": "srvtoolu_s_00_3f2a9c...",
  "status": "completed",
  "kind": "search",
  "action": {
    "type": "search",
    "queries": ["DeepSeek V4.1"],
    "sources": [
      {
        "type": "url",
        "url": "https://example.com/news",
        "title": "...",
        "snippet": "...",
        "site_name": "Example News",
        "site_icon": "https://cdn.deepseek.com/site-icons/example.com",
        "published_at": "2026-01-02T03:04:05+00:00"
      }
    ]
  }
}
```

| `output[].kind`                                             | `output[].action.type`                    | 其他字段                                                                                                 |
| ----------------------------------------------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `search`、`deep_search`、`image_search` 与 `deep_image_search` | `search`                                  | `action.queries`，以及带展示字段 `title`、`snippet`、`site_name`、`site_icon`、`published_at` 的 `action.sources` |
| `deep_search`                                               | `open_page` 或 `find_in_page`（带 `pattern`） | 打开网页时有 `page`：`{url, title, published_at}`                                                           |
| `read_link`                                                 | `open_page`                               | `page`；成功阅读时还有 `signature`                                                                           |

- 调用失败时 `status` 为 `"failed"`，并带 `error: {"code": "..."}`，错误码见 [web\_fetch\_tool\_result](#web_fetch_tool_result)。
- 思考是一个 `reasoning` item，内容为 `reasoning_text`，`summary` 为空，不返回 `encrypted_content`。
- 回答是一个 `message` item，其 `output_text` 以 `url_citation` 注解携带引用；`start_index` 与 `end_index` 按 Unicode 码点计数，`title` 未知时为空字符串。

| `status`                                                      | 含义                                                                                                                           |
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `completed`                                                   | 回答完成                                                                                                                         |
| `incomplete`，`incomplete_details.reason: "max_output_tokens"` | 输出达到最大长度，回答被截断                                                                                                               |
| `incomplete`，`incomplete_details.reason: "content_filter"`    | 内容审核拒答。`output` 只保留已执行的 `web_search_call`，见 [模型内容安全](https://api-docs.deepseek.com/zh-cn/guides/safety.md#handling-refusals) |

### 流式输出

- 一次调用依次产生 `response.output_item.added`（带完整的 `action`）、`response.web_search_call.in_progress`、`response.web_search_call.searching`、`response.web_search_call.completed`，以及带 `sources`、`page`、`signature` 或 `error` 的 `response.output_item.done`。
- 多个调用同时进行时，先全部 added，再逐个完成。请按 `output_index` 对应事件。
- 每条引用以一个 `response.output_text.annotation.added` 事件发送。
- 使用 OpenAI Python SDK 时，响应以 `content_filter` 结束会让 `get_final_response()` 报错，请从 `response.incomplete` 事件中读取最终响应。

### 用量

- `usage.server_tool_use` 中，`tool_search` 是计费的搜索次数（不含图片搜索），`tool_fetch` 是计费的抓取次数，`tool_image_search` 是计费的图片搜索次数。三者都为 `0` 时不返回该字段。

### 多轮对话

把上一轮的 `output` item 原样放回 `input`，包括 `kind` 和 `signature`，规则同 [多轮对话](#multi-turn)。`web_search` 工具产生的 `web_search_call` item 按搜索处理。

***

<a id="chat-completions-api"></a>

## Chat Completions API

同样的工具也可以在 Chat Completions API 中使用，通过请求与响应上的扩展字段实现。

在 `tools` 中声明工具，`safety_check` 与 `title` 放在顶层，与其他协议一致。`tool_choice: "required"` 按 `auto` 处理。

### 请求

- 声明了这些工具的请求传入 `web_search_options` 时返回 `400`，请改为在 `tools` 中声明工具。
- `response_format` 不为 `text`，或传入 `logprobs`、`top_logprobs` 时返回 `400`。
- 部分参数会被忽略，见 [被忽略的参数](https://api-docs.deepseek.com/zh-cn/guides/build_a_chatbot.md#ignored-parameters)。
- 支持 [`latest_reminder`](https://api-docs.deepseek.com/zh-cn/guides/latest_reminder.md) 消息。
- 继续生成只支持在 beta 接口上给最后一条 `assistant` 消息加 `prefix: true`，见 [继续生成](#continue-generation)。

### 输出

工具调用放在扩展字段 `message.server_tool_calls` 中。每个元素是一步：这一步的思考，以及这一步发起的调用。

```json
{
  "role": "assistant",
  "reasoning_content": "资料够了，可以回答……",
  "content": "这篇文章主要讲……。作者此前在……任职。",
  "annotations": [
    {"type": "url_citation", "url_citation": {"url": "https://example.com/post", "title": "...", "start_index": 0, "end_index": 10}}
  ],
  "server_tool_calls": [
    {
      "index": 0,
      "reasoning_content": "",
      "calls": [
        {
          "index": 0,
          "id": "srvtoolu_rl_00_3f2a...",
          "type": "deepseek_read_url",
          "kind": "read_link",
          "action": {"type": "read_link", "url": "https://example.com/post"},
          "status": "completed",
          "page": {"url": "https://example.com/post", "title": "...", "published_at": "2026-01-02"},
          "signature": "q3J0b1RmZ1c4cE1x..."
        }
      ]
    },
    {
      "index": 1,
      "reasoning_content": "读完了，再查一下作者背景……",
      "calls": [
        {
          "index": 0,
          "id": "srvtoolu_s_01_9c41...",
          "type": "deepseek_web_search",
          "kind": "search",
          "action": {"type": "search", "queries": ["..."]},
          "status": "completed",
          "sources": [
            {"type": "url", "url": "https://example.com/news", "title": "...", "snippet": "...", "site_name": "Example News", "site_icon": "...", "published_at": "2026-01-02T03:04:05+00:00"}
          ]
        }
      ]
    }
  ]
}
```

| 层级 | 字段                  | 含义                                                                                                                              |
| -- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| 步  | `index`             | 步的序号，从 0 开始                                                                                                                     |
| 步  | `reasoning_content` | 这一步的思考。开启思考时总是字符串，这一步没有思考时为空字符串；未开启思考时不返回该字段                                                                                    |
| 步  | `calls`             | 这一步发起的调用，按发起顺序排列                                                                                                                |
| 调用 | `index`、`id`        | 调用在这一步内的序号，以及与其他协议形式相同的 `id`                                                                                                    |
| 调用 | `type`              | 开启这项能力的工具：`deepseek_web_search` 或 `deepseek_read_url`                                                                           |
| 调用 | `kind`              | `search`、`deep_search`、`read_link`、`image_search` 或 `deep_image_search`                                                         |
| 调用 | `action`            | 调用参数：`{type: "search", queries}`、`{type: "open_page", url}`、`{type: "find_in_page", url, pattern}` 或 `{type: "read_link", url}` |
| 调用 | `status`            | `completed` 或 `failed`。响应结束时还没有结果的调用为 `failed`                                                                                  |
| 调用 | `sources`           | 搜索结果，展示字段与 Responses API 相同                                                                                                     |
| 调用 | `page`              | 打开的网页或阅读的链接的 `{url, title, published_at}`，仅供展示                                                                                  |
| 调用 | `signature`         | 加密的网页，只有成功阅读的链接才有                                                                                                               |
| 调用 | `error`             | 调用失败时的 `{code}`，错误码见 [web\_fetch\_tool\_result](#web_fetch_tool_result)                                                         |

- `message.reasoning_content` 只包含最后一步的思考，之前各步的思考在各自的条目里。
- `content` 中没有引用角标。引用在 `message.annotations` 中，类型为 `url_citation`：`start_index` 与 `end_index` 按 `content` 的 Unicode 码点计数，`title` 未知时为 URL 本身。没有引用时不返回该字段。引用的展示信息按 URL 在 `sources` 或 `page` 中查找。

| `finish_reason`  | 含义                                                                                                                                                          |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `stop`           | 回答完成                                                                                                                                                        |
| `length`         | 输出达到最大长度，回答被截断                                                                                                                                              |
| `content_filter` | 内容审核拒答。`content` 为空字符串，不返回 `annotations`；`server_tool_calls` 保留，各步的思考被清空。见 [模型内容安全](https://api-docs.deepseek.com/zh-cn/guides/safety.md#handling-refusals) |

### 流式输出

- 思考和正文照常通过 `delta.reasoning_content` 与 `delta.content` 流式输出。各步的思考依次输出，中间不加分隔。
- 工具调用的过程通过 `server_tool_event` 发送，它是 choice 上与 `delta` 并列的扩展字段。一个 chunk 最多带一个事件：

| `type`                | 字段            | 含义                                                           |
| --------------------- | ------------- | ------------------------------------------------------------ |
| `step_reasoning_done` | `step`        | 第 `step` 步的思考已输出完：在此之前输出、还没归属的思考都属于这一步。每一步在它的第一次调用开始之前发送一次   |
| `call_started`        | `step`、`call` | 这一步的一次调用开始，带完整的 `action`                                     |
| `call_completed`      | `step`、`call` | 调用结束，带 `status` 以及 `sources`、`page` 或 `error`，不带 `signature` |

- 完整的 `server_tool_calls` 与 `annotations` 只发送一次，在带 `finish_reason` 的最后一个 chunk 的 `delta` 中。最后一个 `step_reasoning_done` 之后输出的思考就是最后一步的思考。
- 开启 [`title`](https://api-docs.deepseek.com/zh-cn/guides/conversation_title.md) 时，标题在最后一个 chunk 的 `delta.title` 中，非流式响应在 `message.title` 中。
- 使用 OpenAI Python SDK 时，响应以 `content_filter` 或 `length` 结束会让 `.stream()` 的 `get_final_completion()` 报错。

### 用量

`usage.server_tool_use` 中的 `tool_search`、`tool_fetch` 与 `tool_image_search` 是计费的搜索、抓取与图片搜索次数，与 [Responses API](#responses-api) 相同。

### 多轮对话

把 assistant 消息连同 `server_tool_calls` 原样回传，规则同 [多轮对话](#multi-turn)。阅读链接得到的网页由对应调用的 `signature` 还原。如果框架或网关丢弃了 `server_tool_calls`，请求仍然正常执行，但之前读过的网页不再进入上下文。
