# Messages（Claude）

Anthropic Messages 兼容端点,支持 Claude 原生内容块、extended thinking、工具调用和 prompt cache。

```text
POST https://api.clomio.ai/v1/messages
POST https://api.clomio.ai/v1/messages/count_tokens
```

> **分组要求:** `/v1/messages` 支持 Claude/Anthropic 分组,也支持启用了 Messages ingress 的 OpenAI/Grok 分组转换。具体模型、工具和流式能力以分组为准。`/v1/messages/count_tokens` 对 OpenAI/Grok 分组固定返回 404,其他 Anthropic-compatible 分组是否支持取决于平台能力;主对话成功时 count_tokens 404 通常可忽略。见 [端点 × 分组](#/api-usage)。

---

## 请求头

| 请求头 | 必填 | 值 |
|--------|:----:|-----|
| `Authorization` | 是 | `Bearer 你的密钥`(也兼容 `x-api-key: 你的密钥`;普通网关还接受 `x-goog-api-key`,但 Claude Code 不推荐用它) |
| `anthropic-version` | 是 | 如 `2023-06-01` |
| `anthropic-beta` | 否 | 使用 beta 能力时按 Anthropic 规范传入 |
| `Content-Type` | 是 | `application/json` |

手写 curl 至少带 `anthropic-version: 2023-06-01`。使用 beta 能力时按客户端要求保留 `anthropic-beta`。普通 `/v1` 网关路径禁止把密钥放在 query string:`?key=` 或 `?api_key=` 会返回 400 `api_key_in_query_deprecated`;请用 header。

---

## 请求参数

| 参数 | 类型 | 必填 | 说明 |
|------|------|:----:|------|
| `model` | string | 是 | Claude 模型名或映射模型名,以控制台分组为准 |
| `messages` | array | 是 | 对话消息,`role` 为 `user`/`assistant` |
| `max_tokens` | integer | 是 | 最大输出 token |
| `system` | string/array | 否 | 系统提示;可为字符串或 content block 数组 |
| `temperature` | number | 否 | 采样温度;部分推理模型可能忽略 |
| `top_p` / `top_k` | number/int | 否 | 采样控制 |
| `stream` | boolean | 否 | SSE 流式返回 |
| `stop_sequences` | array | 否 | 停止序列 |
| `tools` | array | 否 | 工具定义,每项含 `name`、`description`、`input_schema`;也可带 `cache_control` |
| `tool_choice` | object | 否 | `{"type":"auto"}` / `any` / `none` / `{"type":"tool","name":"..."}`;可带 `disable_parallel_tool_use` |
| `thinking` | object | 否 | Extended thinking,如 `{"type":"enabled","budget_tokens":2000}` |
| `output_config` | object | 否 | 输出强度配置,如 `{"effort":"low|medium|high|max"}` |
| `metadata` | object | 否 | 终端用户或请求元数据,如 `user_id` |

---

## content block

`messages[].content` 可为字符串,也可为 block 数组。常用 block:

| type | 关键字段 | 说明 |
|------|----------|------|
| `text` | `text`, `cache_control` | 文本输入/输出 |
| `image` | `source{type,media_type,data/url/file_id}` | 图片输入 |
| `document` | `source`, `title`, `cache_control` | 文档输入 |
| `thinking` | `thinking` | assistant extended thinking 内容 |
| `tool_use` | `id`, `name`, `input` | assistant 请求调用工具 |
| `tool_result` | `tool_use_id`, `content`, `is_error` | user 回传工具结果 |

`cache_control` 可放在 `system` block、`messages[].content[]` block 或工具定义上,常见值:

```json
{"type":"ephemeral"}
```

也可带 `ttl`,如 `{"type":"ephemeral","ttl":"1h"}`;具体是否生效取决于上游模型能力。

**请求边界:** 请求体不能为空且必须是合法 JSON；`model` 必须是非空 string，`stream` 应使用 boolean。OpenAI/Grok 分组是否开放 Messages 转换由分组能力决定，未开放时返回 403 `This group does not allow /v1/messages dispatch`。OpenAI/Grok 分组调用 `/v1/messages/count_tokens` 返回 404 `Token counting is not supported for this platform`。请求体过大时返回 413 `invalid_request_error`。

---

## 响应

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | string | 消息 ID |
| `type` | string | `message` |
| `role` | string | `assistant` |
| `content` | array | 内容块数组,可能包含 `text`、`thinking`、`tool_use` 等 |
| `model` | string | 实际模型 |
| `stop_reason` | string | `end_turn` / `max_tokens` / `tool_use` 等 |
| `stop_sequence` | string/null | 命中的停止序列 |
| `usage` | object | `input_tokens` / `output_tokens`,可能含 `cache_creation_input_tokens`、`cache_read_input_tokens`、`service_tier` 等 |

```json
{
  "id": "msg_xxx",
  "type": "message",
  "role": "assistant",
  "content": [{ "type": "text", "text": "你好!" }],
  "stop_reason": "end_turn",
  "usage": { "input_tokens": 10, "output_tokens": 6 }
}
```

流式以 SSE 返回 `message_start`、`content_block_start`、`content_block_delta`、`message_delta`、`message_stop` 等事件;累积 `text_delta.text`、`thinking_delta.thinking` 和 `input_json_delta.partial_json`。

---

## 最小可验证 curl

下面请求可验证 `/v1/messages`、`anthropic-version`、`model`/`max_tokens`/`messages` 基本形态和非流式响应；在 Claude 分组下把 `stream` 改成字符串可验证本地解析错误 `Failed to parse request body`。

## 示例:基础调用

```bash
curl https://api.clomio.ai/v1/messages \
  -H "Authorization: Bearer 你的密钥" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-6",
    "max_tokens": 1024,
    "system": "你是简洁的助手。",
    "messages": [{"role": "user", "content": "你好"}]
  }'
```

```python
from anthropic import Anthropic
client = Anthropic(api_key="你的密钥", base_url="https://api.clomio.ai")

msg = client.messages.create(
    model="claude-sonnet-4-6",
    max_tokens=1024,
    messages=[{"role": "user", "content": "你好"}],
)
print(msg.content[0].text)
```

> 用官方 anthropic SDK 时,`base_url` 填 `https://api.clomio.ai`(**不带** `/v1`,SDK 会自动补 `/v1/messages`)。

---

## 示例:流式

```bash
curl https://api.clomio.ai/v1/messages \
  -H "Authorization: Bearer 你的密钥" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-6",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "写一句鼓励的话"}],
    "stream": true
  }'
```

---

## OpenAI 分组 Messages bridge

OpenAI/Grok 分组下的 `/v1/messages` 仍使用 Anthropic Messages 请求形状；服务会按分组能力转换并返回 Anthropic Messages 响应。启用条件和边界:

- API Key 必须绑定 OpenAI 分组，且当前分组已开放 Messages 兼容能力；否则返回 403 `This group does not allow /v1/messages dispatch`。
- 服务会按当前分组的兼容规则处理 Anthropic `model`；实际模型以当前分组模型列表和用量明细为准。
- 部分兼容路径会以流式方式处理请求；客户端传 `stream:false` 时，服务会聚合后返回非流式 Anthropic Messages 响应。
- 该兼容入口适合 Claude Code/Anthropic SDK 接入 OpenAI 或 Grok 分组；Grok 分组需要开启 Messages ingress 能力。

---

## count_tokens 行为

`POST /v1/messages/count_tokens` 用于正式发送前估算输入 token:

- `/v1/messages` 原生支持 Claude/Anthropic 分组;OpenAI/Grok 分组在开启 Messages ingress 时会经网关转换支持。
- `/v1/messages/count_tokens` 对 OpenAI/Grok 分组固定 404;其他 Anthropic-compatible 分组是否支持由平台能力决定，也可能返回 404。
- 它是辅助估算端点，不等同于正式对话；主 `/v1/messages` 成功而 count_tokens 404 时，通常只是客户端 token 估算回退。
- 请求体使用 Messages 形态,可包含 `system`、`messages`、`tools`、`thinking` 等字段;部分不适合计数的字段会在上游请求前清理。
- 返回 Anthropic 形态,核心字段为 `input_tokens`。

```bash
curl https://api.clomio.ai/v1/messages/count_tokens \
  -H "Authorization: Bearer 你的密钥" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-6",
    "messages": [{"role": "user", "content": "这段话有多少 token?"}]
  }'
```

返回:

```json
{ "input_tokens": 11 }
```

---

## 实战场景

### 场景一:工具调用与工具结果回传

第一轮让模型选择工具:

```json
{
  "model": "claude-sonnet-4-6",
  "max_tokens": 1024,
  "messages": [{"role":"user","content":"北京现在天气如何?"}],
  "tools": [{
    "name": "get_weather",
    "description": "查询城市天气",
    "input_schema": {
      "type": "object",
      "properties": {"city": {"type":"string"}},
      "required": ["city"]
    }
  }],
  "tool_choice": {"type":"auto"}
}
```

若响应 `stop_reason:"tool_use"`,把工具结果作为下一轮 `user` 消息回传:

```json
{
  "model": "claude-sonnet-4-6",
  "max_tokens": 1024,
  "messages": [
    {"role":"user","content":"北京现在天气如何?"},
    {"role":"assistant","content":[{"type":"tool_use","id":"toolu_1","name":"get_weather","input":{"city":"北京"}}]},
    {"role":"user","content":[{"type":"tool_result","tool_use_id":"toolu_1","content":"{\"temp\":\"28C\",\"condition\":\"晴\"}"}]}
  ]
}
```

### 场景二:缓存控制长上下文

```json
{
  "model": "claude-sonnet-4-6",
  "max_tokens": 1024,
  "system": [{
    "type": "text",
    "text": "下面是长期稳定的项目背景和编码规范...",
    "cache_control": {"type":"ephemeral","ttl":"1h"}
  }],
  "messages": [{
    "role": "user",
    "content": [{"type":"text","text":"基于这些规范,检查这个补丁。"}]
  }]
}
```

响应 usage 中如出现 `cache_creation_input_tokens` 或 `cache_read_input_tokens`,表示上游返回了缓存写入/读取用量。

### 场景三:Extended thinking + output_config

```bash
curl https://api.clomio.ai/v1/messages \
  -H "Authorization: Bearer 你的密钥" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-6",
    "max_tokens": 4096,
    "thinking": {"type":"enabled","budget_tokens":2000},
    "output_config": {"effort":"high"},
    "messages": [{"role":"user","content":"分析这个并发 bug 的可能根因,最后给出修复顺序。"}]
  }'
```

响应 `content` 可能同时包含 `thinking` 与最终 `text` block;流式时对应 `thinking_delta` 和 `text_delta`。

### 场景四:发送前先估价,超长就提示

```python
from anthropic import Anthropic
client = Anthropic(api_key="你的密钥", base_url="https://api.clomio.ai")

def ask(text, budget=4000):
    n = client.messages.count_tokens(
        model="claude-sonnet-4-6",
        messages=[{"role": "user", "content": text}],
    ).input_tokens
    if n > budget:
        return f"输入约 {n} token,超过预算 {budget},请精简后再问。"
    msg = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1024,
        messages=[{"role": "user", "content": text}],
    )
    return msg.content[0].text

print(ask("帮我把这段话润色一下:今天我很开心"))
```

---

> 命令行装 Claude Code 见 [Claude Code 接入](#/claude-code);OpenAI SDK 客户端可用 [Chat Completions](#/api-chat) 或 [Responses](#/api-responses)。

## 字段约束速查

| 字段 | 可选值/范围 | 说明 |
|---|---|---|
| `model` | 当前分组可见的 Claude/Grok/OpenAI 模型 | 必填 |
| `max_tokens` | 正整数 | 必填，包含 thinking 和最终输出预算 |
| `messages[].role` | `user` / `assistant` | 系统指令使用顶层 `system` |
| `content` | string 或 block 数组 | 支持 `text`、`image`、`document`、`tool_use`、`tool_result` |
| `stream` | `true` / `false` | 流式返回 Anthropic SSE 事件 |
| `thinking.type` | `enabled` / `adaptive` / `disabled` | `enabled` 还需 `budget_tokens` 正整数 |
| `output_config.effort` | `low` / `medium` / `high` | 模型支持时生效 |
| `tool_choice.type` | `auto` / `any` / `tool` | `tool` 时填写 `name` |
| `system` | string 或 text block 数组 | 系统提示 |

## 完整错误目录

| HTTP | 典型错误 | 处理 |
|---:|---|---|
| 400 | `Request body is empty`、`Failed to parse request body`、`model is required` | 修正 JSON 和必填字段 |
| 400 | `max_tokens must be greater than 0`、thinking budget 不合法 | 使用正整数且不超过模型上下文 |
| 400 | content block 类型未知或字段缺失 | 按 `text/image/document/tool_use/tool_result` 结构发送 |
| 401 | `Invalid API key` | 使用对应平台 Key |
| 403 | `This group does not allow /v1/messages dispatch` | 开启 Messages ingress 或更换分组 |
| 404 | 不支持模型/路径 | 查看 `/v1/models` |
| 413 | body 超过网关限制 | 压缩图片、拆分上下文 |
| 429 | 额度、RPM、并发或上游限速 | 退避重试 |
| 502/503 | 上游认证失败或服务暂时不可用 | 保存 `x-request-id` 和错误体 |
