教程Claude Code系列第 1 / 17 篇

第一次直接调 Claude 的接口:从 curl 到 Python,多轮对话、流式、看图,以及通过中转站要改的两处

不通过 Claude Code,自己写几行代码直接调模型,要哪些东西、请求和响应长什么样、多轮对话和流式怎么做。本文按官方的入门文档整理,每一步都通过中转站跑过。要改的只有接口地址和 key 两处。另外测到一个新手很容易踩的坑:max_tokens 给 100,回答是空的。

发布 · 约 9 分钟读完 · 经人工审核()· 本站的内容怎么来的

本站已实测,测试日期:2026-10-13。

本页目录(13 节)
  1. 先分清:两种用法
  2. 一、要准备的两样东西
  3. 二、第一个请求:curl
  4. 三、同一件事,用 Python
  5. 四、一个很容易踩的坑:回答是空的
  6. 五、多轮对话:接口不记事
  7. 六、流式:边生成边显示
  8. 七、给它看图
  9. 八、版本和 beta 头
  10. 九、接下来能做什么
  11. 通过中转站实测到的
  12. 花费
  13. 这次实测没有覆盖到的

这篇教程解决一个问题:不用 Claude Code,想在自己的脚本或程序里直接调 Claude,最少要做哪几件事?

一直用 Claude Code 的人迟早会碰到这个需求:批量处理一批文件、给自己的小工具加一个“问一下模型”的功能、写个定时脚本。这些用不着一整个智能体,一次接口调用就够了。

实测环境
日期 2026-10-13
版本 Anthropic Python SDK 1.13.0,Python 3.12.3,curl
模型 Sonnet 5.5
连接方式 通过酷站AI 中转站,不是直连官方

先分清:两种用法

官方把“用 Claude 做东西”分成两条路:

Messages API Claude Managed Agents
是什么 直接给模型发消息、拿回答 一套现成的、托管在云上的智能体框架
适合 自己写循环,要精细的控制 跑很久的任务、异步的活

这篇讲的是前一种。Claude Code 和 Agent SDK 底下用的也是它。

一、要准备的两样东西

一个接口地址和一把 key。

直连官方的话,地址是 https://api.anthropic.com,key 在官方控制台的 Settings → API keys 里创建,以 sk-ant- 开头,只在创建时显示一次。官方公布的支持地区名单里没有中国大陆、香港和澳门。

通过中转站的话,地址和 key 都换成中转站给你的。后面所有的代码,要改的就是这两处,别的一个字不用动。

把它们放进环境变量,不要写在代码里:

export ANTHROPIC_BASE_URL="中转站给的接口地址"
export ANTHROPIC_API_KEY="中转站给的 key"

官方 SDK 会自动读这两个变量。直连官方时不用设第一个。

二、第一个请求:curl

curl "$ANTHROPIC_BASE_URL/v1/messages" \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-5-5",
    "max_tokens": 300,
    "messages": [{"role": "user", "content": "用一句话解释什么是 API。"}]
  }'

请求里有三样是必须的:

字段 意思
model 用哪个模型
max_tokens 这次最多输出多少 token。必填
messages 对话,一个列表,每条有 role(user 或 assistant)和 content

三个请求头:

请求头 意思
x-api-key 你的 key。也可以写成 Authorization: Bearer 你的key,官方现在把后一种当作正式写法
anthropic-version 接口的版本,目前就是 2023-06-01
content-type 固定是 application/json

实测拿到的响应(删掉了几个暂时用不上的字段):

{
  "id": "msg_011Cfy…",
  "type": "message",
  "role": "assistant",
  "model": "claude-sonnet-5-5",
  "content": [
    {"type": "text", "text": "API(应用程序编程接口)是一套预先定义好的规则和约定,让不同的软件之间可以互相请求数据或调用功能,而无需了解对方的内部实现。"}
  ],
  "stop_reason": "end_turn",
  "usage": {"input_tokens": 48, "output_tokens": 63}
}

要看的三处:

  • content 是一个列表,不是一个字符串。里面每一块有自己的类型,这次只有一块文字。
  • stop_reason 说明它为什么停。end_turn 是自己说完了。
  • usage 是这次用了多少 token,计费按它算。

三、同一件事,用 Python

pip install anthropic
import anthropic

client = anthropic.Anthropic()          # 自动读环境变量里的地址和 key

message = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=300,
    messages=[{"role": "user", "content": "用一句话解释什么是 API。"}],
)

text = "".join(block.text for block in message.content if block.type == "text")
print(text)
print(message.stop_reason, message.usage.input_tokens, message.usage.output_tokens)

取文字时按类型挑,不要写 message.content[0].text。现在的模型回答前面可能多一个思考块,第一块不一定是文字。

官方还有 TypeScript、Go、Java、C#、PHP、Ruby 的 SDK,用法是同一套。

四、一个很容易踩的坑:回答是空的

本站在测“加系统提示”时,把 max_tokens 随手写成了 100:

max_tokens=100 :stop_reason=max_tokens  内容块=['thinking']  output=100(思考 100)  文字=''
max_tokens=1000:stop_reason=end_turn    内容块=['text']      output=31(思考 0)    文字='吾无从知天时,君可观窗外云日,或查天气,再决出门与否。'

同一个请求,第一次模型先思考,100 个 token 全花在了思考上,文字一个字都没有,而这 100 个 token 照样计费。第二次它没有思考,31 个 token 就答完了。

要不要思考是模型每次自己决定的,你事先不知道。所以:

  • max_tokens 留宽一些。 它是上限,不是你要付的数;没用完的不收钱。
  • 每次都看 stop_reason。 是 max_tokens 就说明被截断了。

思考的事在《Claude 的思考和 effort 怎么调》里讲得更细。

五、多轮对话:接口不记事

这是从聊天界面转过来的人最容易想错的地方:接口是无状态的,它不记得上一次请求。 想让它“接着聊”,要自己把之前的对话都发过去。

history = [{"role": "user", "content": "我叫小周,在做一个记账的小程序。记住这两点,回一个“好”。"}]
reply = client.messages.create(model="claude-sonnet-5-5", max_tokens=1000, messages=history)

history.append({"role": "assistant", "content": reply.content})     # 把它的回答原样放回去
history.append({"role": "user", "content": "我叫什么?在做什么?一句话。"})
reply2 = client.messages.create(model="claude-sonnet-5-5", max_tokens=1000, messages=history)

实测:

第 2 轮(带着历史):你叫小周,正在做一个记账的小程序。
同一个问题,不带历史:我不知道你叫什么,也看不出你在做什么……
各轮 input_tokens:66、86、51

两点:

  • 把助手的回答放回去时,整个 content 原样放,不要只取文字。里面可能有思考块和工具调用,带工具时少了它们会出错。
  • 对话越长,每一轮的输入越多,也越贵。 第 2 轮的输入已经包含了第 1 轮的全部内容。长对话要靠提示缓存和压缩来控制。

系统提示不放在 messages 里,单独用 system 字段:

client.messages.create(
    model="claude-sonnet-5-5", max_tokens=1000,
    system="你是一个只用文言文回答的助手,回答不超过二十个字。",
    messages=[{"role": "user", "content": "今天适合出门吗?"}],
)

以前有一种写法是在最后放一条 assistant 消息、写上回答的开头让它接着写(预填)。Claude 4.6 及之后的模型不支持了,官方接口会返回 400。

六、流式:边生成边显示

回答长的时候,等它全部生成完再显示,用户要干等。流式是让它生成一点就发一点。

用 SDK 最省事:

with client.messages.stream(
    model="claude-sonnet-5-5", max_tokens=1000,
    messages=[{"role": "user", "content": "用两句话解释什么是流式输出。"}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
    final = stream.get_final_message()       # 完整的消息对象,和非流式拿到的一样

实测这两句话分 23 段到达,第一段在 1.9 秒,最后一段在 2.9 秒。把 23 段拼起来,和 get_final_message() 里的文字完全一致。

不需要逐段显示、只是怕长请求超时的话,可以只用最后那一行:让 SDK 替你把流读完,拿到的是一个完整的消息。SDK 在 max_tokens 很大时会要求你必须用流式。

自己发 HTTP 的话,请求里加 "stream": true,响应是一串事件。实测的顺序:

message_start → content_block_start → ping → content_block_delta×2 → content_block_stop → message_delta → message_stop
event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"一、二、三、四、"}}
事件 内容
message_start 开头。一个内容为空的消息对象
content_block_start 一个内容块开始
content_block_delta 这个块的一小段增量。文字是 text_delta,工具参数是 input_json_delta,思考是 thinking_delta
content_block_stop 这个块结束
message_delta 快结束时来。stop_reason 和最终的输出 token 数在这里
message_stop 结束
ping 保持连接用的,随时可能出现,忽略它

两条要记的规矩:

  • 遇到不认识的事件类型,跳过,不要报错。 官方保留了以后加新事件的权利。
  • 报错也可能出现在流里。 响应已经是 200 了,中途还可能来一个 error 事件,比如服务过载。

流中途断了怎么续:把已经收到的那部分存下来,再发一个请求让它从断的地方接着写。Claude 4.6 及之后的模型上,做法是加一条用户消息请它继续;思考块和工具调用是续不了的,只能从最近的一段文字接。

七、给它看图

图片放在 content 里,和文字并列,用 base64 编码:

message = client.messages.create(
    model="claude-sonnet-5-5", max_tokens=1000,
    messages=[{"role": "user", "content": [
        {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": 图片的base64字符串}},
        {"type": "text", "text": "这张图左半边和右半边各是什么颜色?一句话。"},
    ]}],
)

本站用代码生成了一张左红右蓝的小图发过去,回答是“左半边是红色,右半边是蓝色”,输入计了 73 个 token。

八、版本和 beta 头

版本。 anthropic-version 目前只有 2023-06-01 这一个在用的值。官方的承诺是:同一个版本下,已有的输入和输出参数不会变;但会加新的可选参数、往输出里加新的字段、加新的事件类型和枚举值。所以你的代码要能容忍响应里多出不认识的东西。

beta 头。 还在测试的功能要在请求里点名才能用:

anthropic-beta: 功能名1,功能名2

用 SDK 的话,走 client.beta 这个入口,功能名放在 betas 里:

client.beta.messages.create(
    model="claude-sonnet-5-5", max_tokens=1000,
    betas=["context-management-2025-06-27"],
    messages=[...],
)

每个功能的文档里写着它的 beta 名。测试中的功能可能改、可能撤,价格和限流也可能不同。

九、接下来能做什么

接口的能力,官方分成五块:

包括什么 本站的文章
模型的能力 思考、effort、结构化输出、引用、看图、读 PDF 思考和 effort
工具 让它调你写的函数,或者用官方的搜索、代码执行
工具的基础设施 工具多的时候怎么按需加载
上下文管理 缓存、压缩、清理 提示缓存、压缩和上下文编辑
文件 上传文件,在多次请求里复用

另外几篇用得上的:选哪个模型、多少钱,见《Claude 现在有哪些模型》;请求失败了怎么看,见《报错、限流和停止原因》。

顺带一提:官方文档里有一页专门“写给 Claude 看”的接口速查(API usage primer)。让 Claude 帮你写调接口的代码时,把那一页贴给它,它就不会用过时的写法。Claude Code 里自带的 /claude-api skill 做的是同一件事。

通过中转站实测到的

这篇里的每一段代码,通过酷站AI 都跑通了:

功能 结果
两种带 key 的写法(x-api-key 和 Authorization: Bearer) 都认
非流式、流式 正常,流式的事件顺序和文档一致
多轮、system 正常
图片输入 正常
client.models.list() 返回 16 个模型
client.messages.count_tokens() 能调,但数字和实际计费对不上,别用它估花费
client.beta.messages.create() 能调
异步客户端同时发三个请求 正常

和直连官方不一样的地方,前面几篇各自写了,这里只列和入门有关的三条:

  • max_tokens 一定要带。 漏了它,这家中转站返回的是一个让你“60 秒后重试”的 503,重试多少次都一样。
  • 模型名写完整。 claude-sonnet-5-5 这样的,别名用不了。能用哪些模型以中转站的列表为准。
  • 自己直接调接口并且要用缓存的话,请求里带一个固定的 metadata.user_id,否则缓存基本不命中。

花费

这一轮三十来次请求,都是很短的问答,按官方价估算不到 0.05 美元。

这次实测没有覆盖到的

  • 官方接口没有测,本站没有官方的 key。创建 key 的步骤是照文档写的。
  • 只用了 Python 和 curl。 其他语言的 SDK 没有试。
  • 流式的断线续传、流里的报错事件没有碰到,也没有去造。
  • PDF、用网址给图片、文件接口没有试。这家中转站没有开文件接口。
  • Managed Agents 完全没有涉及。

来源

通过 API 中转站使用这些模型?到 Veridrop 免费检测中转站给你的是不是它声称的模型,或者看看中转站排行榜前 100 名。

相关文章