---
title: "Anthropic Messages"
description: "用官方 Anthropic SDK 调用 pirouter 上接受 Anthropic 协议的模型，包括 Claude。本页说明 Messages 怎么调、两种鉴权头、提示词缓存怎么计价、思考参数怎么写，以及和 Anthropic 官方行为的差异。"
canonical: "https://pirouter.ai/zh/docs/protocols/anthropic"
last-updated: "2026-10-17"
lang: "zh"
source: "content/docs/zh/(start)/protocols/anthropic.mdx"
---

# Anthropic Messages

用官方 Anthropic SDK 调用 pirouter 上接受 Anthropic 协议的模型，包括 Claude。本页说明 Messages 怎么调、两种鉴权头、提示词缓存怎么计价、思考参数怎么写，以及和 Anthropic 官方行为的差异。

用官方 Anthropic SDK 调用 pirouter，只需要改 base URL 和 key。本页说明怎么发请求、两种鉴权头、提示词缓存、思考参数，以及和 Anthropic 官方行为的差异。

## 用官方 SDK 发请求

端点是 `POST /v1/messages`。SDK 的 base URL 填 `https://api.pirouter.ai`，不带 `/v1`，SDK 会自己拼上。模型 ID 写 `vendor/model`。

cURL:

```bash
curl https://api.pirouter.ai/v1/messages \
  -H "x-api-key: $PIROUTER_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-5.5",
    "max_tokens": 1024,
    "messages": [{ "role": "user", "content": "Hello!" }]
  }'
```

Python:

```python
import os
import anthropic

client = anthropic.Anthropic(
    base_url="https://api.pirouter.ai",
    api_key=os.environ["PIROUTER_API_KEY"],
)

message = client.messages.create(
    model="anthropic/claude-sonnet-5.5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
)
print(message.content[0].text)
```

TypeScript:

```ts
import Anthropic from '@anthropic-ai/sdk'

const client = new Anthropic({
  baseURL: 'https://api.pirouter.ai',
  apiKey: process.env.PIROUTER_API_KEY,
})

const message = await client.messages.create({
  model: 'anthropic/claude-sonnet-5.5',
  max_tokens: 1024,
  messages: [{ role: 'user', content: 'Hello!' }],
})
console.log(message.content[0].text)
```

你应该看到一段回答。在控制台的 **日志** 里能找到这次请求。

要流式输出，在请求体里加 `"stream": true`，并给 curl 加 `-N`：

```bash
curl -N https://api.pirouter.ai/v1/messages \
  -H "x-api-key: $PIROUTER_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-5.5",
    "stream": true,
    "max_tokens": 1024,
    "messages": [{ "role": "user", "content": "Hello!" }]
  }'
```

你应该看到 SSE 事件成对到达，一行 `event: `，一行 `data: `。第一个事件是 `message_start`，最后一个是 `message_stop`，之后没有 `[DONE]`。

## 两种鉴权头

key 可以放在下面任一个请求头里，值都是 pirouter 的 API key：

| 请求头                     | SDK 里怎么写                                     |
| ----------------------- | -------------------------------------------- |
| `x-api-key`             | SDK 的默认写法，传 `api_key`（TypeScript 是 `apiKey`） |
| `Authorization: Bearer` | 改传 `auth_token`（TypeScript 是 `authToken`）    |

两个都带时以 `Authorization` 为准。读取规则见[在请求里带上 key](https://pirouter.ai/zh/docs/authentication.md#在请求里带上-key)。

`anthropic-version`、`anthropic-beta` 这类请求头原样转发给 provider。

## 哪些模型能用

接受 Anthropic 协议的有 Claude 系列，也有部分其它厂商的模型。一个模型接不接受，看 `GET /v1/models/{vendor}/{model}/endpoints` 返回的 `protocols` 里有没有 `anthropic`，或者在[模型列表](https://pirouter.ai/zh/models)里看每个模型的协议。用不接受的模型调用，返回 `422`，见[协议不匹配](https://pirouter.ai/zh/docs/models.md#协议不匹配)。

Claude 模型也可以用别名调用，例如不带厂商前缀的名字。别名清单看同一个响应的 `aliases`。无论用哪个名字，日志和账单里记的都是完整 ID。

## 使用提示词缓存

在要缓存的内容块上加 `cache_control`，写法和 Anthropic 官方相同，pirouter 原样转发。`ttl` 可以写 `"5m"` 或 `"1h"`：

```json
"system": [
  {
    "type": "text",
    "text": "一段很长、每次请求都不变的说明",
    "cache_control": { "type": "ephemeral", "ttl": "1h" }
  }
]
```

缓存的用量在响应的 `usage` 里：

| 用量字段                                       | 含义           | 计价                                |
| ------------------------------------------ | ------------ | --------------------------------- |
| `input_tokens`                             | 没有命中缓存的输入    | 输入价（`prompt`）                     |
| `cache_read_input_tokens`                  | 从缓存读出的输入     | 缓存读取价（`input_cache_read`）         |
| `cache_creation.ephemeral_1h_input_tokens` | 写入 1 小时缓存的输入 | 1 小时缓存写入价（`input_cache_write_1h`） |
| `cache_creation.ephemeral_5m_input_tokens` | 写入 5 分钟缓存的输入 | 模型价格里的缓存写入价                       |

输入总量是 `input_tokens`、`cache_read_input_tokens`、`cache_creation_input_tokens` 三项之和。各项单价见模型的 `pricing`，说明见[价格](https://pirouter.ai/zh/docs/billing.md#价格)。

## 控制思考

`thinking` 是 Messages 协议自己的参数，原样转发。在 Claude 模型上，用 `thinking: {"type": "adaptive"}` 打开思考，用 `output_config.effort` 设档位，可以是 `low`、`medium`、`high`、`xhigh`、`max`。写了不接受的档位，返回 provider 的 `4xx`。

部分 Claude 模型只接受 `adaptive` 这种思考方式，部分不能关闭思考。写成 `"type": "enabled"`，或在这些模型上写 `"type": "disabled"` 时，请求不会因此被拒绝，但思考的方式不保证和你写的一致。要稳定地控制思考，用 `adaptive` 加 `output_config.effort`。

请求里没写 `thinking`，也没写 `output_config.effort` 时，部分 provider 登记了默认推理档：pirouter 写入 `thinking: {"type": "adaptive"}` 和这一档；默认档是 `none` 时写入 `thinking: {"type": "disabled"}`。

部分 provider 只按 token 预算限制思考。在这些 provider 上，你写了 `budget_tokens` 时，pirouter 把它压到 `max_tokens` 以下，剩下的留给回答；没写时按 `output_config.effort` 换算预算，没写档位按 `medium` 算，预算不低于 1024。

## 与 Anthropic 官方行为的差异

| 方面           | pirouter 的行为                                                                                                                                                                                           |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 错误体          | pirouter 自己的错误（`401`、`402`、`404`、`422`、`429`、`5xx`）是 `{"error": {"message", "type", "code"}}`，不是 Anthropic 的 `{"type": "error", "error": {…}}`。provider 自己返回的错误照原样转交。SDK 按状态码抛出异常，`error.message` 照常可读 |
| 响应里的 `model` | 改写为 pirouter 的模型 ID（`vendor/model`）。provider 自己报的名字在响应头 `X-Pi-Upstream-Model` 里                                                                                                                        |
| 模型名          | 除完整 ID 外也接受别名，见[哪些模型能用](https://pirouter.ai/zh/docs/protocols/anthropic.md#哪些模型能用)                                                                                                                     |
| 强制调用工具       | `tool_choice` 为 `any` 或指定某个工具时，部分模型不保证调用工具：请求照常返回 `200`，回答可能是普通文本                                                                                                                                      |
| 失败重试         | provider 在返回第一个字节之前失败时，pirouter 自动换下一家，见[失败时自动换一家](https://pirouter.ai/zh/docs/routing.md#失败时自动换一家)                                                                                                    |

## 出错时的返回

| 状态码与 `error.code`            | 原因                 | 处理                                                                         |
| ---------------------------- | ------------------ | -------------------------------------------------------------------------- |
| `401` `invalid_api_key` 等    | key 缺失、写错或已失效      | 检查 key，见[鉴权失败时的返回](https://pirouter.ai/zh/docs/authentication.md#鉴权失败时的返回) |
| `402` `insufficient_balance` | 余额不够               | [充值](https://pirouter.ai/zh/docs/billing.md#充值)后重发                         |
| `404` `model_not_found`      | 模型 ID 不存在          | 核对 `vendor/model` 的写法                                                      |
| `422` `validation_failed`    | 模型不接受 Anthropic 协议 | 换一个模型，或改用它接受的协议                                                            |
| `429` `rate_limited`         | 上游部署的分钟配额用满        | 等 `Retry-After` 秒，见[限流](https://pirouter.ai/zh/docs/rate-limits.md)        |

全部错误码见[错误码](https://pirouter.ai/zh/docs/errors.md)。

## 目前没有的能力

下面这些 Anthropic 端点 pirouter 目前没有：

- `POST /v1/messages/count_tokens`。调用它返回 `400`，错误码 `invalid_request`，`message` 是 `model is required`。这个错误说的不是你的请求缺字段，而是 pirouter 不提供这个端点。
- Message Batches 端点。

## 下一步

- [Gemini](https://pirouter.ai/zh/docs/protocols/gemini.md): 用 Google GenAI SDK 或 REST 调用 Gemini 协议模型。
- [定价与计费](https://pirouter.ai/zh/docs/billing.md): 每类 token 怎么计价。
