Messages
Anthropic 原生消息接口。Claude 模型用它,相比 OpenAI 的 Chat Completions,区别在 system 顶层独立、content 支持 block 数组、工具调用走 tool_use / tool_result。
协议边界
这是 Anthropic 请求/响应格式。Claude 与 Deepseek 分组是主要使用场景;部分 OpenAI 分组也可能通过网关转换支持 /v1/messages,但是否开放取决于分组配置。
Endpoint
POST https://api.sakrylle.com/v1/messages请求头
| 名称 | 必填 | 说明 |
|---|---|---|
Authorization | 是 | Bearer sk-xxxxxxxxxxxxxxxx |
Content-Type | 是 | application/json |
anthropic-version | 否 | 与 Anthropic 官方一致,例如 2023-06-01。直传上游。 |
Accept | 否 | 流式可写 text/event-stream |
请求体参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | 是 | Claude 模型 ID,例如 claude-haiku-4-5-20251001 |
messages | array | 是 | 对话历史,每项 role 为 user 或 assistant,content 为字符串或 block 数组 |
max_tokens | integer | 是 | 最大输出 token 数 |
system | string | array | 否 | 系统提示,顶层字段(不放进 messages) |
stream | boolean | 否 | 默认 false;为 true 时返回 SSE |
temperature | number | 否 | 0–1 |
top_p | number | 否 | 核采样概率 |
top_k | integer | 否 | top-k 采样 |
stop_sequences | array | 否 | 停止序列 |
tools | array | 否 | 工具定义,每项含 name、description、input_schema |
tool_choice | object | 否 | {"type":"auto"} / {"type":"any"} / {"type":"tool","name":"..."} |
metadata | object | 否 | 例如 {"user_id":"..."} |
网关只校验
model必填,其余字段透传上游。
请求体示例
json
{
"model": "claude-haiku-4-5-20251001",
"max_tokens": 1024,
"system": "你是一个简洁的中文助手。",
"messages": [
{ "role": "user", "content": "你好,介绍一下你自己。" }
]
}响应示例
json
{
"id": "msg_xxxxxxxxxxxxxxxxxxxxxxxx",
"type": "message",
"role": "assistant",
"model": "claude-haiku-4-5-20251001",
"content": [
{ "type": "text", "text": "你好!我是 Claude,一个由 Anthropic 训练的助手。" }
],
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 24,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0,
"output_tokens": 18
}
}工具调用示例
请求里声明 tools:
json
{
"model": "claude-haiku-4-5-20251001",
"max_tokens": 1024,
"tools": [
{
"name": "get_weather",
"description": "查询某个城市的当前天气",
"input_schema": {
"type": "object",
"properties": {
"city": { "type": "string" }
},
"required": ["city"]
}
}
],
"messages": [
{ "role": "user", "content": "上海现在天气怎么样?" }
]
}模型决定调用工具时,响应 content 含 tool_use block:
json
{
"id": "msg_xxxxxxxxxxxxxxxxxxxxxxxx",
"type": "message",
"role": "assistant",
"model": "claude-haiku-4-5-20251001",
"content": [
{
"type": "tool_use",
"id": "toolu_xxxxxxxxxxxxxxxx",
"name": "get_weather",
"input": { "city": "上海" }
}
],
"stop_reason": "tool_use",
"usage": { "input_tokens": 312, "output_tokens": 47 }
}把工具结果以 tool_result block 写回 messages 继续对话:
json
{
"model": "claude-haiku-4-5-20251001",
"max_tokens": 1024,
"messages": [
{ "role": "user", "content": "上海现在天气怎么样?" },
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_xxxxxxxxxxxxxxxx",
"name": "get_weather",
"input": { "city": "上海" }
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_xxxxxxxxxxxxxxxx",
"content": "晴,26°C"
}
]
}
]
}流式响应示例
stream: true 时返回 SSE,事件类型固定。最简骨架:
event: message_start
data: {"type":"message_start","message":{"id":"msg_xxx","type":"message","role":"assistant","model":"claude-haiku-4-5-20251001","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":24,"output_tokens":0}}}
event: content_block_start
data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}}
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"你好"}}
event: content_block_stop
data: {"type":"content_block_stop","index":0}
event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"input_tokens":24,"output_tokens":18}}
event: message_stop
data: {"type":"message_stop"}错误
400 invalid_request_error— 缺model/ 请求体非 JSON / 解析失败401 authentication_error— API Key 无效403 billing_error— 余额或订阅限额不足403 permission_error— 分组限制 Claude Code 客户端时拒绝其他客户端429 rate_limit_error— 触发并发或速率限制502 upstream_error— 上游连续失败,请稍后重试
更多错误码见 错误处理。
代码示例
bash
curl https://api.sakrylle.com/v1/messages \
-H "Authorization: Bearer sk-xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-haiku-4-5-20251001",
"max_tokens": 1024,
"messages": [
{"role": "user", "content": "你好"}
]
}'python
from anthropic import Anthropic
client = Anthropic(
api_key="sk-xxxxxxxxxxxxxxxx",
base_url="https://api.sakrylle.com",
)
msg = client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=1024,
system="你是一个简洁的中文助手。",
messages=[{"role": "user", "content": "你好"}],
)
print(msg.content[0].text)javascript
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
apiKey: "sk-xxxxxxxxxxxxxxxx",
baseURL: "https://api.sakrylle.com",
});
const msg = await client.messages.create({
model: "claude-haiku-4-5-20251001",
max_tokens: 1024,
messages: [{ role: "user", content: "你好" }],
});
console.log(msg.content[0].text);go
package main
import (
"context"
"fmt"
"github.com/anthropics/anthropic-sdk-go"
"github.com/anthropics/anthropic-sdk-go/option"
)
func main() {
client := anthropic.NewClient(
option.WithAPIKey("sk-xxxxxxxxxxxxxxxx"),
option.WithBaseURL("https://api.sakrylle.com/"),
)
msg, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
Model: anthropic.F(anthropic.Model("claude-haiku-4-5-20251001")),
MaxTokens: anthropic.F(int64(1024)),
Messages: anthropic.F([]anthropic.MessageParam{
anthropic.NewUserMessage(anthropic.NewTextBlock("你好")),
}),
})
if err != nil {
panic(err)
}
fmt.Println(msg.Content[0].Text)
}rust
use reqwest::Client;
use serde_json::json;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let client = Client::new();
let resp: serde_json::Value = client
.post("https://api.sakrylle.com/v1/messages")
.bearer_auth("sk-xxxxxxxxxxxxxxxx")
.header("anthropic-version", "2023-06-01")
.json(&json!({
"model": "claude-haiku-4-5-20251001",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "你好"}]
}))
.send()
.await?
.json()
.await?;
println!("{resp:#}");
Ok(())
}java
import java.net.URI;
import java.net.http.*;
public class Messages {
public static void main(String[] args) throws Exception {
String body = """
{"model":"claude-haiku-4-5-20251001","max_tokens":1024,
"messages":[{"role":"user","content":"你好"}]}
""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.sakrylle.com/v1/messages"))
.header("Authorization", "Bearer sk-xxxxxxxxxxxxxxxx")
.header("Content-Type", "application/json")
.header("anthropic-version", "2023-06-01")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());
}
}csharp
using System.Net.Http.Headers;
using System.Text;
var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "sk-xxxxxxxxxxxxxxxx");
http.DefaultRequestHeaders.Add("anthropic-version", "2023-06-01");
var payload = """
{"model":"claude-haiku-4-5-20251001","max_tokens":1024,
"messages":[{"role":"user","content":"你好"}]}
""";
var resp = await http.PostAsync(
"https://api.sakrylle.com/v1/messages",
new StringContent(payload, Encoding.UTF8, "application/json"));
Console.WriteLine(await resp.Content.ReadAsStringAsync());