第二章:原始请求

大多数教程都会让你执行 pip install anthropic。我们不打算这么做。

SDK 掩盖了真相。它们增加了一层又一层的抽象,让“Hello World“变得轻而易举,却让调试“Error 400“成为噩梦。学会了 SDK,你只是学会了 SDK 本身。学会了原始 HTTP 请求,你才真正掌握了每一个 SDK 背后的底层协议。

我们将只使用 requests 库,直接向 Claude 发送消息。Claude 是 Anthropic 的旗舰大语言模型,在编程任务方面是能力最强的模型之一。

获取 API Key

要与 Claude 通信,你需要一个 API Key。这是一串很长的字符,作用类似于密码,与你的计费账户绑定。

  1. 前往 Anthropic 控制台。1
  2. 注册并添加支付方式(最低充值 $5)。
  3. 创建一个新的 API Key,并将其命名为 nanocode
  4. 复制该 Key(它以 sk-ant-... 开头)。
An icon of a warning1

警告: 请像对待密码一样保管好这个 Key。任何持有它的人都可以花掉你的钱。

保险库(.env)

我们需要一个安全的地方来存储这个 Key。切勿将 Key 直接写入代码。

在你的项目根目录下创建一个名为 .env 的文件:

1 touch .env

打开它并粘贴你的密钥:

1 ANTHROPIC_API_KEY=sk-ant-api03-...

我们在第 1 章安装 python-dotenv 正是为了这个目的——它会读取 .env 文件并将其中的值加载到 os.environ 中。

请求的结构

要与 LLM 通信,我们需要向以下地址发送一个 HTTP POST 请求:

https://api.anthropic.com/v1/messages

这个请求需要三个要素:请求头中的身份验证信息(你的 API 密钥)、请求体中的配置参数(使用哪个模型、多少个 token),以及消息本身。

请求头

Anthropic 要求提供三个请求头:

请求头 用途
x-api-key 你的私有密钥 身份验证
anthropic-version 2023-06-01 API 版本
content-type application/json 格式

载荷

“Messages API” 期望接收一个由消息字典组成的列表:

1 "messages": [
2     {"role": "user", "content": "Hello, world!"}
3 ]

每条消息都有一个 role(值为 "user""assistant")和 content(文本)。

代码

创建一个名为 test_api.py 的文件。这是一个“冒烟测试“,用来验证我们的连接是否正常。之后我们会将其删除。

背景说明: 我们编写的是线性的、过程式代码。没有函数,没有类。我们想直接看到最原始的底层实现。

代码:

 1 import os
 2 import requests
 3 import json
 4 from dotenv import load_dotenv
 5 
 6 # 1. Load the vault
 7 load_dotenv()
 8 api_key = os.getenv("ANTHROPIC_API_KEY")
 9 
10 # Basic check so we don't crash with a confusing "NoneType" error later
11 if not api_key:
12     print("Error: ANTHROPIC_API_KEY not found in .env")
13     exit(1)
14 
15 # 2. Define the target
16 url = "https://api.anthropic.com/v1/messages"
17 
18 # 3. Authenticate
19 headers = {
20     "x-api-key": api_key,
21     "anthropic-version": "2023-06-01",
22     "content-type": "application/json"
23 }
24 
25 # 4. Construct the payload
26 payload = {
27     "model": "claude-sonnet-4-6",
28     "max_tokens": 4096,
29     "messages": [
30         {"role": "user", "content": "Hello, are you ready to code?"}
31     ]
32 }
33 
34 # 5. Fire! (No safety net)
35 print("📡 Sending request to Claude...")
36 response = requests.post(url, headers=headers, json=payload, timeout=120)
37 
38 # 6. Inspect the raw result
39 print(f"Status: {response.status_code}")
40 
41 if response.status_code == 200:
42     # Success: Print the beautiful JSON
43     print("Response:")
44     print(json.dumps(response.json(), indent=2))
45 else:
46     # Failure: Print the ugly raw text so we can debug
47     print("Error:", response.text)

代码详解:

  • 第 7 行: load_dotenv() 会找到 .env 文件,并将其中的变量加载到 os.environ 中。
  • 第 8 行: 我们在这里获取 API 密钥。切记不要将其硬编码到代码里。
  • 第 11-13 行: 基本的有效性检查。如果没有这一步,缺失的密钥会在 headers 字典中引发令人困惑的 NoneType 错误。
  • 第 21 行: anthropic-version 请求头是必填项。若省略,API 将拒绝你的请求。
  • 第 27 行: claude-sonnet-4-6 指定了我们要使用的模型。
  • 第 28 行: max_tokens 是必填项。它用于限制响应长度,防止费用失控。
  • 第 36 行: 我们以 2 分钟的超时时间发送请求,没有使用 try/except——如果网络断开,就让 Python 崩溃。你需要看到它在哪里出错了。
  • 第 41-47 行: 检查状态码。200 表示成功(以美化格式输出 JSON)。其他任何状态码都意味着我们打印原始错误文本以便调试。

运行程序

1 python test_api.py

如果一切正常,你应该会看到:

Status: 200
Response:
{
  "id": "msg_01...",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "Hello! Yes, I'm ready to code..."
    }
  ],
  "stop_reason": "end_turn",
  "usage": {
    "input_tokens": 15,
    "output_tokens": 81
  }
}

故障排查

错误 原因 解决方法
401 Unauthorized API 密钥错误 检查 .env 是否已加载。打印 os.environ.get("ANTHROPIC_API_KEY") 进行验证。
400 Bad Request JSON 格式错误 是否忘记了 max_tokensmessages 是列表吗?
429 Rate Limit 请求过多或额度不足 稍等片刻,或向账户充值。

清理工作

我们已经证明可以和这个“大脑“对话了。删除 test_api.py——我们不再需要它了。

An icon of a info-circle1

旁注: 这个 test_api.py 是一次性代码——只用一次的冒烟测试。真正的自动化测试(使用 FakeBrain 和 pytest)会在第 3 章介绍。验证 API 连接正常后,你应该删除这个文件。

An icon of a info-circle1

旁注: 要监控你的消费情况,可以查看 Anthropic Console 中的“使用情况“选项卡。截至 2026 年初,使用 Claude Sonnet 进行一次包含 20-30 轮对话的典型编程会话,费用约为 $0.10-$0.50。响应 JSON 底部的 usage 字段会显示精确的令牌数量——你可以记录这些数据,以便通过编程方式追踪费用。

小结

这就是一次原始的 API 调用:请求头、JSON 有效载荷、响应解析。你和底层网络之间没有任何抽象层。当出现问题时(这是迟早的事),你能准确知道是哪一层出了故障——因为本来就只有一层。

有一个问题:Claude 完全没有记忆。每次请求都是一片空白。我们将通过在每一轮对话中重放完整的对话历史,来模拟出记忆的效果。


  1. https://console.anthropic.com/settings/keys↩︎