批处理


批处理是一种高效处理大量请求的强大方法。批处理允许您将多个请求一起提交进行异步处理,而不是逐个处理请求并立即响应。这种模式在以下情况下特别有用:

  • 您需要处理大量数据
  • 不需要即时响应
  • 您希望优化成本效率
  • 您正在运行大规模评估或分析

Message Batches API 是 Anthropic 对这种模式的首次实现。

Note

此功能不符合零数据保留(ZDR)条件。数据按照该功能的标准保留策略进行保留。


Message Batches API

Message Batches API 是一种强大、经济高效的方式,用于异步处理大量 Messages 请求。这种方法非常适合不需要即时响应的任务,大多数批处理在不到 1 小时内完成,同时降低成本 50% 并提高吞吐量。

除了本指南外,您还可以直接探索 API 参考

Message Batches API 的工作原理

当您向 Message Batches API 发送请求时:

  1. 系统使用提供的 Messages 请求创建一个新的 Message Batch。
  2. 然后批处理被异步处理,每个请求独立处理。
  3. 您可以轮询批处理的状态,并在所有请求处理完成后检索结果。

这对于不需要即时结果的批量操作特别有用,例如:

  • 大规模评估:高效处理数千个测试用例。
  • 内容审核:异步分析大量用户生成的内容。
  • 数据分析:为大型数据集生成见解或摘要。
  • 批量内容生成:为各种目的创建大量文本(例如,产品描述、文章摘要)。

批处理限制

  • 一个 Message Batch 最多可包含 100,000 个 Message 请求或 256 MB 大小,以先达到的限制为准。
  • 系统会尽快处理每个批处理,大多数批处理在 1 小时内完成。您可以在所有消息处理完成后或 24 小时后(以先到者为准)访问批处理结果。如果处理在 24 小时内未完成,批处理将过期。
  • 批处理结果在创建后 29 天内可用。之后,您仍然可以查看批处理,但其结果将不再可供下载。
  • 批处理限定在工作区范围内。您可以查看您的 API 密钥所属工作区内创建的所有批处理(及其结果)。
  • 速率限制同时适用于 Batches API HTTP 请求和批处理中等待处理的请求总数。请参阅 Message Batches API 速率限制。此外,处理速度可能会因当前需求和请求量而降低。在这种情况下,您可能会看到更多请求在 24 小时后过期。
  • 由于高吞吐量和并发处理,批处理可能会略微超出您工作区配置的支出限制
  • 每个批处理请求必须设置至少为 1max_tokens。批处理内不支持 max_tokens: 0cache 预热),因为在批处理期间写入的临时 cache 条目可能会在后续请求运行之前过期。

支持的模型

所有活跃模型都支持 Message Batches API。

可以批处理的内容

任何您可以对 Messages API 发出的请求都可以包含在批处理中。包括:

  • 视觉
  • 工具使用
  • 系统消息
  • 多轮对话
  • 任何 beta 功能

由于批处理中的每个请求都是独立处理的,您可以在单个批处理中混合不同类型的请求。

Tip

由于批处理可能需要超过 5 分钟的时间处理,在处理具有共享上下文的批处理时,请考虑使用 1 小时 cache 持续时间配合 prompt caching,以获得更好的 cache 命中率。


定价

Batches API 提供显著的成本节约。所有使用量按标准 API 价格的 50% 计费。

模型批处理输入批处理输出
Claude Opus 4.7$2.50 / MTok$12.50 / MTok
Claude Opus 4.6$2.50 / MTok$12.50 / MTok
Claude Opus 4.5$2.50 / MTok$12.50 / MTok
Claude Opus 4.1$7.50 / MTok$37.50 / MTok
Claude Opus 4(已弃用$7.50 / MTok$37.50 / MTok
Claude Sonnet 4.6$1.50 / MTok$7.50 / MTok
Claude Sonnet 4.5$1.50 / MTok$7.50 / MTok
Claude Sonnet 4(已弃用$1.50 / MTok$7.50 / MTok
Claude Haiku 4.5$0.50 / MTok$2.50 / MTok
Claude Haiku 3.5(已退役,Bedrock 和 Vertex AI 除外$0.40 / MTok$2 / MTok

如何使用 Message Batches API

准备并创建您的批处理

一个 Message Batch 由一系列创建 Message 的请求组成。单个请求的结构包括:

  • 用于标识 Messages 请求的唯一 custom_id。必须为 1 到 64 个字符,仅包含字母数字字符、连字符和下划线(匹配 ^[a-zA-Z0-9_-]{1,64}$)。
  • 包含标准 Messages API 参数的 params 对象

您可以通过将此列表传入 requests 参数来创建批处理

curl https://api.anthropic.com/v1/messages/batches \
     --header "x-api-key: $ANTHROPIC_API_KEY" \
     --header "anthropic-version: 2023-06-01" \
     --header "content-type: application/json" \
     --data \
'{
    "requests": [
        {
            "custom_id": "my-first-request",
            "params": {
                "model": "claude-opus-4-7",
                "max_tokens": 1024,
                "messages": [
                    {"role": "user", "content": "Hello, world"}
                ]
            }
        },
        {
            "custom_id": "my-second-request",
            "params": {
                "model": "claude-opus-4-7",
                "max_tokens": 1024,
                "messages": [
                    {"role": "user", "content": "Hi again, friend"}
                ]
            }
        }
    ]
}'
ant messages:batches create <<'YAML'
requests:
  - custom_id: my-first-request
    params:
      model: claude-opus-4-7
      max_tokens: 1024
      messages:
        - role: user
          content: Hello, world
  - custom_id: my-second-request
    params:
      model: claude-opus-4-7
      max_tokens: 1024
      messages:
        - role: user
          content: Hi again, friend
YAML
import anthropic
from anthropic.types.message_create_params import MessageCreateParamsNonStreaming
from anthropic.types.messages.batch_create_params import Request

client = anthropic.Anthropic()

message_batch = client.messages.batches.create(
    requests=[
        Request(
            custom_id="my-first-request",
            params=MessageCreateParamsNonStreaming(
                model="claude-opus-4-7",
                max_tokens=1024,
                messages=[
                    {
                        "role": "user",
                        "content": "Hello, world",
                    }
                ],
            ),
        ),
        Request(
            custom_id="my-second-request",
            params=MessageCreateParamsNonStreaming(
                model="claude-opus-4-7",
                max_tokens=1024,
                messages=[
                    {
                        "role": "user",
                        "content": "Hi again, friend",
                    }
                ],
            ),
        ),
    ]
)

print(message_batch)
import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic();

const messageBatch = await anthropic.messages.batches.create({
  requests: [
    {
      custom_id: "my-first-request",
      params: {
        model: "claude-opus-4-7",
        max_tokens: 1024,
        messages: [{ role: "user", content: "Hello, world" }]
      }
    },
    {
      custom_id: "my-second-request",
      params: {
        model: "claude-opus-4-7",
        max_tokens: 1024,
        messages: [{ role: "user", content: "Hi again, friend" }]
      }
    }
  ]
});

console.log(messageBatch);
using Anthropic;
using Anthropic.Models.Messages;
using Anthropic.Models.Messages.Batches;

AnthropicClient client = new();

var batch = await client.Messages.Batches.Create(new BatchCreateParams
{
    Requests =
    [
        new()
        {
            CustomID = "my-first-request",
            Params = new()
            {
                Model = Model.ClaudeOpus4_7,
                MaxTokens = 1024,
                Messages =
                [
                    new() { Role = Role.User, Content = "Hello, world" }
                ]
            }
        },
        new()
        {
            CustomID = "my-second-request",
            Params = new()
            {
                Model = Model.ClaudeOpus4_7,
                MaxTokens = 1024,
                Messages =
                [
                    new() { Role = Role.User, Content = "Hi again, friend" }
                ]
            }
        }
    ]
});

Console.WriteLine(batch);
package main

import (
	"context"
	"fmt"

	"github.com/anthropics/anthropic-sdk-go"
)

func main() {
	client := anthropic.NewClient()

	batch, _ := client.Messages.Batches.New(context.Background(),
		anthropic.MessageBatchNewParams{
			Requests: []anthropic.MessageBatchNewParamsRequest{
				{
					CustomID: "my-first-request",
					Params: anthropic.MessageBatchNewParamsRequestParams{
						Model:     anthropic.ModelClaudeOpus4_7,
						MaxTokens: 1024,
						Messages: []anthropic.MessageParam{
							anthropic.NewUserMessage(
								anthropic.NewTextBlock("Hello, world"),
							),
						},
					},
				},
				{
					CustomID: "my-second-request",
					Params: anthropic.MessageBatchNewParamsRequestParams{
						Model:     anthropic.ModelClaudeOpus4_7,
						MaxTokens: 1024,
						Messages: []anthropic.MessageParam{
							anthropic.NewUserMessage(
								anthropic.NewTextBlock("Hi again, friend"),
							),
						},
					},
				},
			},
		})

	fmt.Println(batch.ID)
}
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.Model;
import com.anthropic.models.messages.batches.*;

public class BatchExample {

  public static void main(String[] args) {
    AnthropicClient client = AnthropicOkHttpClient.fromEnv();

    BatchCreateParams params = BatchCreateParams.builder()
      .addRequest(
        BatchCreateParams.Request.builder()
          .customId("my-first-request")
          .params(
            BatchCreateParams.Request.Params.builder()
              .model(Model.CLAUDE_OPUS_4_7)
              .maxTokens(1024)
              .addUserMessage("Hello, world")
              .build()
          )
          .build()
      )
      .addRequest(
        BatchCreateParams.Request.builder()
          .customId("my-second-request")
          .params(
            BatchCreateParams.Request.Params.builder()
              .model(Model.CLAUDE_OPUS_4_7)
              .maxTokens(1024)
              .addUserMessage("Hi again, friend")
              .build()
          )
          .build()
      )
      .build();

    MessageBatch messageBatch = client.messages().batches().create(params);

    System.out.println(messageBatch);
  }
}
<?php

use Anthropic\Client;

$client = new Client(
    apiKey: getenv("ANTHROPIC_API_KEY")
);

$batch = $client->messages->batches->create(
    requests: [
        [
            'custom_id' => 'my-first-request',
            'params' => [
                'model' => 'claude-opus-4-7',
                'max_tokens' => 1024,
                'messages' => [
                    ['role' => 'user', 'content' => 'Hello, world']
                ]
            ]
        ],
        [
            'custom_id' => 'my-second-request',
            'params' => [
                'model' => 'claude-opus-4-7',
                'max_tokens' => 1024,
                'messages' => [
                    ['role' => 'user', 'content' => 'Hi again, friend']
                ]
            ]
        ]
    ],
);

echo $batch->id;
require "anthropic"

client = Anthropic::Client.new

batch = client.messages.batches.create(
  requests: [
    {
      custom_id: "my-first-request",
      params: {
        model: "claude-opus-4-7",
        max_tokens: 1024,
        messages: [
          { role: "user", content: "Hello, world" }
        ]
      }
    },
    {
      custom_id: "my-second-request",
      params: {
        model: "claude-opus-4-7",
        max_tokens: 1024,
        messages: [
          { role: "user", content: "Hi again, friend" }
        ]
      }
    }
  ]
)

puts batch

在此示例中,两个独立的请求被一起批处理进行异步处理。每个请求都有一个唯一的 custom_id,并包含您用于 Messages API 调用的标准参数。

Tip

使用 Messages API 测试您的批处理请求

每个消息请求的 params 对象的验证是异步执行的,验证错误在整个批处理处理结束后返回。您可以通过首先使用 Messages API 验证请求结构来确保正确构建输入。

当批处理首次创建时,响应的处理状态为 in_progress

{
  "id": "msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d",
  "type": "message_batch",
  "processing_status": "in_progress",
  "request_counts": {
    "processing": 2,
    "succeeded": 0,
    "errored": 0,
    "canceled": 0,
    "expired": 0
  },
  "ended_at": null,
  "created_at": "2024-09-24T18:37:24.100435Z",
  "expires_at": "2024-09-25T18:37:24.100435Z",
  "cancel_initiated_at": null,
  "results_url": null
}

跟踪您的批处理

Message Batch 的 processing_status 字段指示批处理所处的处理阶段。它从 in_progress 开始,然后在批处理中的所有请求处理完成后更新为 ended,结果已准备就绪。您可以通过访问控制台或使用检索端点来监控批处理状态。

轮询 Message Batch 完成

要轮询 Message Batch,您需要其 id,该 id 在创建批处理时的响应中提供,或通过列出批处理获得。您可以实现一个轮询循环,定期检查批处理状态,直到处理结束:

#!/bin/sh
MESSAGE_BATCH_ID=$(curl -s https://api.anthropic.com/v1/messages/batches \
  --header "x-api-key: $ANTHROPIC_API_KEY" \
  --header "anthropic-version: 2023-06-01" \
  --header "content-type: application/json" \
  --data '{
    "requests": [{
      "custom_id": "test-1",
      "params": {
        "model": "claude-opus-4-7",
        "max_tokens": 100,
        "messages": [{"role": "user", "content": "Hi"}]
      }
    }]
  }' | jq -r '.id')

until [[ $(curl -s "https://api.anthropic.com/v1/messages/batches/$MESSAGE_BATCH_ID" \
          --header "x-api-key: $ANTHROPIC_API_KEY" \
          --header "anthropic-version: 2023-06-01" \
          | grep -o '"processing_status":[[:space:]]*"[^"]*"' \
          | cut -d'"' -f4) == "ended" ]]; do
    echo "批处理 $MESSAGE_BATCH_ID 仍在处理中..."
    break
    sleep 60
done

echo "批处理 $MESSAGE_BATCH_ID 已完成处理"
#!/bin/bash
MESSAGE_BATCH_ID=$(ant messages:batches create \
  --transform id --raw-output <<'YAML'
requests:
  - custom_id: test-1
    params:
      model: claude-opus-4-7
      max_tokens: 100
      messages:
        - role: user
          content: Hi
YAML
)

until [[ $(ant messages:batches retrieve \
          --message-batch-id "$MESSAGE_BATCH_ID" \
          --transform processing_status --raw-output) == "ended" ]]; do
    echo "批处理 $MESSAGE_BATCH_ID 仍在处理中..."
    break
    sleep 60
done

echo "批处理 $MESSAGE_BATCH_ID 已完成处理"
import anthropic
import time

client = anthropic.Anthropic()

MESSAGE_BATCH_ID = "msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d"

message_batch = None
while True:
    message_batch = client.messages.batches.retrieve(MESSAGE_BATCH_ID)
    if message_batch.processing_status == "ended":
        break

    print(f"批处理 {MESSAGE_BATCH_ID} 仍在处理中...")
    time.sleep(60)
print(message_batch)
import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic();

const messageBatchId = "msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d";

let messageBatch;
while (true) {
  messageBatch = await anthropic.messages.batches.retrieve(messageBatchId);
  if (messageBatch.processing_status === "ended") {
    break;
  }

  console.log(`批处理 ${messageBatchId} 仍在处理中... 等待`);
  await new Promise((resolve) => setTimeout(resolve, 60_000));
}
console.log(messageBatch);
using Anthropic;
using Anthropic.Models.Messages.Batches;

AnthropicClient client = new();
string messageBatchId = Environment.GetEnvironmentVariable("MESSAGE_BATCH_ID");

MessageBatch messageBatch = null;
while (true)
{
    messageBatch = await client.Messages.Batches.Retrieve(messageBatchId);
    if (messageBatch.ProcessingStatus == "ended")
    {
        break;
    }

    Console.WriteLine({{CONTENT}}quot;批处理 {messageBatchId} 仍在处理中...");
    await Task.Delay(60000);
}
Console.WriteLine(messageBatch);
package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/anthropics/anthropic-sdk-go"
)

func main() {
	client := anthropic.NewClient()
	messageBatchID := os.Getenv("MESSAGE_BATCH_ID")

	var messageBatch *anthropic.MessageBatch
	for {
		var err error
		messageBatch, err = client.Messages.Batches.Get(context.TODO(), messageBatchID)
		if err != nil {
			log.Fatal(err)
		}
		if messageBatch.ProcessingStatus == "ended" {
			break
		}

		fmt.Printf("批处理 %s 仍在处理中...\n", messageBatchID)
		time.Sleep(60 * time.Second)
	}
	fmt.Println(messageBatch)
}
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.batches.MessageBatch;

public class MessageBatchPolling {
    public static void main(String[] args) throws InterruptedException {
        AnthropicClient client = AnthropicOkHttpClient.fromEnv();
        String messageBatchId = "msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d";

        MessageBatch messageBatch = null;
        while (true) {
            messageBatch = client.messages().batches().retrieve(messageBatchId);
            if (messageBatch.processingStatus().equals(MessageBatch.ProcessingStatus.ENDED)) {
                break;
            }

            System.out.println("批处理 " + messageBatchId + " 仍在处理中...");
            Thread.sleep(60000);
        }
        System.out.println(messageBatch);
    }
}
<?php

use Anthropic\Client;

$client = new Client(apiKey: getenv("ANTHROPIC_API_KEY"));
$messageBatchId = getenv("MESSAGE_BATCH_ID");

$messageBatch = null;
while (true) {
    $messageBatch = $client->messages->batches->retrieve(
        messageBatchID: $messageBatchId,
    );
    if ($messageBatch->processingStatus === "ended") {
        break;
    }

    echo "批处理 {$messageBatchId} 仍在处理中...\n";
    sleep(60);
}
echo json_encode($messageBatch, JSON_PRETTY_PRINT);
require "anthropic"

client = Anthropic::Client.new

message_batch_id = ENV["MESSAGE_BATCH_ID"]
message_batch = nil
loop do
  message_batch = client.messages.batches.retrieve(message_batch_id)
  break if message_batch.processing_status == :ended

  puts "批处理 #{message_batch_id} 仍在处理中..."
  sleep 60
end
puts message_batch

列出所有 Message Batches

您可以使用列出端点列出工作区中的所有 Message Batches。API 支持分页,会根据需要自动获取额外的页面:

#!/bin/sh

if ! command -v jq &> /dev/null; then
    echo "错误:此脚本需要 jq。请先安装它。"
    exit 1
fi

BASE_URL="https://api.anthropic.com/v1/messages/batches"

has_more=true
after_id=""

while [ "$has_more" = true ]; do
    # 如果存在 after_id,则构造带参数的 URL
    if [ -n "$after_id" ]; then
        url="${BASE_URL}?limit=20&after_id=${after_id}"
    else
        url="$BASE_URL?limit=20"
    fi

    response=$(curl -s "$url" \
              --header "x-api-key: $ANTHROPIC_API_KEY" \
              --header "anthropic-version: 2023-06-01")

    # 使用 jq 提取值
    has_more=$(echo "$response" | jq -r '.has_more')
    after_id=$(echo "$response" | jq -r '.last_id')

    # 处理并打印 data 数组中的每个条目
    echo "$response" | jq -c '.data[]' | while read -r entry; do
        echo "$entry" | jq '.'
    done
done
# 根据需要自动获取更多页面
ant messages:batches list --limit 20
import anthropic

client = anthropic.Anthropic()

# 根据需要自动获取更多页面
for message_batch in client.messages.batches.list(limit=20):
    print(message_batch)
import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic();

// 根据需要自动获取更多页面
for await (const messageBatch of anthropic.messages.batches.list({
  limit: 20
})) {
  console.log(messageBatch);
}
using System;
using System.Threading.Tasks;
using Anthropic;
using Anthropic.Models.Messages.Batches;

class Program
{
    static async Task Main(string[] args)
    {
        AnthropicClient client = new();

        var parameters = new BatchListParams
        {
            Limit = 20
        };

        // 根据需要自动获取更多页面
        var page = await client.Messages.Batches.List(parameters);
        await foreach (var messageBatch in page.Paginate())
        {
            Console.WriteLine(messageBatch);
        }
    }
}
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/anthropics/anthropic-sdk-go"
)

func main() {
	client := anthropic.NewClient()

	// 根据需要自动获取更多页面
	iter := client.Messages.Batches.ListAutoPaging(context.TODO(), anthropic.MessageBatchListParams{
		Limit: anthropic.Int(20),
	})

	for iter.Next() {
		messageBatch := iter.Current()
		fmt.Println(messageBatch)
	}

	if err := iter.Err(); err != nil {
		log.Fatal(err)
	}
}
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.batches.*;

public class BatchListExample {

  public static void main(String[] args) {
    AnthropicClient client = AnthropicOkHttpClient.fromEnv();

    // 根据需要自动获取更多页面
    for (MessageBatch messageBatch : client
      .messages()
      .batches()
      .list(BatchListParams.builder().limit(20).build())
      .autoPager()) {
      System.out.println(messageBatch);
    }
  }
}
<?php

use Anthropic\Client;

$client = new Client(apiKey: getenv("ANTHROPIC_API_KEY"));

// 根据需要自动获取更多页面
foreach ($client->messages->batches->list(limit: 20)->pagingEachItem() as $messageBatch) {
    echo $messageBatch->id . "\n";
}
require "anthropic"

client = Anthropic::Client.new

# 根据需要自动获取更多页面
client.messages.batches.list(limit: 20).auto_paging_each do |message_batch|
  puts message_batch
end

检索批处理结果

批处理结束后,批处理中的每个 Messages 请求都有一个结果。有 4 种结果类型:

结果类型描述
succeeded请求成功。包含消息结果。
errored请求遇到错误,消息未创建。可能的错误包括无效请求和内部服务器错误。您不会为这些请求付费。
canceled用户在此请求发送到模型之前取消了批处理。您不会为这些请求付费。
expired批处理在此请求发送到模型之前达到了 24 小时过期时间。您不会为这些请求付费。

您可以通过批处理的 request_counts 查看结果概览,它显示了有多少请求达到了这四种状态中的每一种。

批处理结果可在 Message Batch 的 results_url 属性处下载,如果组织权限允许,也可在控制台中下载。由于结果可能很大,建议流式获取结果而不是一次性下载。

#!/bin/sh
curl "https://api.anthropic.com/v1/messages/batches/msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d" \
  --header "anthropic-version: 2023-06-01" \
  --header "x-api-key: $ANTHROPIC_API_KEY" \
  | grep -o '"results_url":[[:space:]]*"[^"]*"' \
  | cut -d'"' -f4 \
  | while read -r url; do
    curl -s "$url" \
      --header "anthropic-version: 2023-06-01" \
      --header "x-api-key: $ANTHROPIC_API_KEY" \
      | sed 's/}{/}\n{/g' \
      | while IFS= read -r line
    do
      result_type=$(echo "$line" | sed -n 's/.*"result":[[:space:]]*{[[:space:]]*"type":[[:space:]]*"\([^"]*\)".*/\1/p')
      custom_id=$(echo "$line" | sed -n 's/.*"custom_id":[[:space:]]*"\([^"]*\)".*/\1/p')
      error_type=$(echo "$line" | sed -n 's/.*"error":[[:space:]]*{[[:space:]]*"type":[[:space:]]*"\([^"]*\)".*/\1/p')

      case "$result_type" in
        "succeeded")
          echo "成功! $custom_id"
          ;;
        "errored")
          if [ "$error_type" = "invalid_request_error" ]; then
            # 需要在重新发送请求之前修复请求体
            echo "验证错误:$custom_id"
          else
            # 可以直接重试请求
            echo "服务器错误:$custom_id"
          fi
          ;;
        "expired")
          echo "已过期:$line"
          ;;
      esac
    done
  done

ant messages:batches results \
  --message-batch-id msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d \
  --transform '{custom_id,"type":result.type,"error":result.error.error.type}' \
  --format jsonl \
  | while IFS= read -r line; do
    custom_id=${line#*'"custom_id":"'}; custom_id=${custom_id%%'"'*}
    case "$line" in
      *'"type":"succeeded"'*)
        printf '成功! %s\n' "$custom_id" ;;
      *'"type":"errored"'*)
        case "$line" in
          *'"error":"invalid_request_error"'*)
            printf '验证错误 %s\n' "$custom_id" ;;
          *)
            printf '服务器错误 %s\n' "$custom_id" ;;
        esac ;;
      *'"type":"expired"'*)
        printf '请求已过期 %s\n' "$custom_id" ;;
    esac
  done
import anthropic

client = anthropic.Anthropic()

# 以内存高效的块流式获取结果文件,一次处理一个
for result in client.messages.batches.results(
    "msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d",
):
    match result.result.type:
        case "succeeded":
            print(f"成功! {result.custom_id}")
        case "errored":
            if result.result.error.error.type == "invalid_request_error":
                # 需要在重新发送请求之前修复请求体
                print(f"验证错误 {result.custom_id}")
            else:
                # 可以直接重试请求
                print(f"服务器错误 {result.custom_id}")
        case "expired":
            print(f"请求已过期 {result.custom_id}")
import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic();

// 以内存高效的块流式获取结果文件,一次处理一个
for await (const result of await anthropic.messages.batches.results(
  "msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d"
)) {
  switch (result.result.type) {
    case "succeeded":
      console.log(`成功! ${result.custom_id}`);
      break;
    case "errored":
      if (result.result.error.type === "invalid_request_error") {
        // 需要在重新发送请求之前修复请求体
        console.log(`验证错误:${result.custom_id}`);
      } else {
        // 可以直接重试请求
        console.log(`服务器错误:${result.custom_id}`);
      }
      break;
    case "expired":
      console.log(`请求已过期:${result.custom_id}`);
      break;
  }
}
using Anthropic;
using Anthropic.Models.Messages.Batches;

AnthropicClient client = new();

await foreach (var result in client.Messages.Batches.ResultsStreaming("msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d"))
{
    switch (result.Result.Type)
    {
        case "succeeded":
            Console.WriteLine({{CONTENT}}quot;成功! {result.CustomID}");
            break;
        case "errored":
            if (result.Result.Error?.Type == "invalid_request")
            {
                Console.WriteLine({{CONTENT}}quot;验证错误:{result.CustomID}");
            }
            else
            {
                Console.WriteLine({{CONTENT}}quot;服务器错误:{result.CustomID}");
            }
            break;
        case "expired":
            Console.WriteLine({{CONTENT}}quot;请求已过期:{result.CustomID}");
            break;
    }
}
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/anthropics/anthropic-sdk-go"
)

func main() {
	client := anthropic.NewClient()

	stream := client.Messages.Batches.ResultsStreaming(context.TODO(), "msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d")

	for stream.Next() {
		result := stream.Current()

		switch variant := result.Result.AsAny().(type) {
		case anthropic.MessageBatchSucceededResult:
			fmt.Printf("成功! %s\n", result.CustomID)
		case anthropic.MessageBatchErroredResult:
			fmt.Printf("错误: %s - %s\n", result.CustomID, variant.Error.Error.Message)
		case anthropic.MessageBatchExpiredResult:
			fmt.Printf("请求已过期: %s\n", result.CustomID)
		}
	}

	if err := stream.Err(); err != nil {
		log.Fatal(err)
	}
}
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.core.http.StreamResponse;
import com.anthropic.models.messages.batches.BatchResultsParams;
import com.anthropic.models.messages.batches.MessageBatchIndividualResponse;

public class BatchResultsExample {

  public static void main(String[] args) {
    AnthropicClient client = AnthropicOkHttpClient.fromEnv();

    // 以内存高效的块流式获取结果文件,一次处理一个
    try (
      StreamResponse<MessageBatchIndividualResponse> streamResponse = client
        .messages()
        .batches()
        .resultsStreaming(
          BatchResultsParams.builder()
            .messageBatchId("msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d")
            .build()
        )
    ) {
      streamResponse
        .stream()
        .forEach(result -> {
          if (result.result().isSucceeded()) {
            System.out.println("成功! " + result.customId());
          } else if (result.result().isErrored()) {
            if (result.result().asErrored().error().error().isInvalidRequestError()) {
              // 需要在重新发送请求之前修复请求体
              System.out.println("验证错误: " + result.customId());
            } else {
              // 可以直接重试请求
              System.out.println("服务器错误: " + result.customId());
            }
          } else if (result.result().isExpired()) {
            System.out.println("请求已过期: " + result.customId());
          }
        });
    }
  }
}
<?php

use Anthropic\Client;

$client = new Client(apiKey: getenv("ANTHROPIC_API_KEY"));

foreach ($client->messages->batches->resultsStream(messageBatchID: 'msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d') as $result) {
    switch ($result->result->type) {
        case "succeeded":
            echo "成功! {$result->customID}\n";
            break;
        case "errored":
            if ($result->result->error->error->type === "invalid_request_error") {
                echo "验证错误: {$result->customID}\n";
            } else {
                echo "服务器错误: {$result->customID}\n";
            }
            break;
        case "expired":
            echo "请求已过期: {$result->customID}\n";
            break;
    }
}
require "anthropic"

client = Anthropic::Client.new

client.messages.batches.results_streaming("msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d").each do |result|
  case result.result.type
  when :succeeded
    puts "成功! #{result.custom_id}"
  when :errored
    if result.result.error.type == :invalid_request
      puts "验证错误: #{result.custom_id}"
    else
      puts "服务器错误: #{result.custom_id}"
    end
  when :expired
    puts "请求已过期: #{result.custom_id}"
  end
end

结果为 .jsonl 格式,其中每行是一个有效的 JSON 对象,表示 Message Batch 中单个请求的结果。对于每个流式结果,您可以根据其 custom_id 和结果类型执行不同的操作。以下是一组示例结果:

{"custom_id":"my-second-request","result":{"type":"succeeded","message":{"id":"msg_014VwiXbi91y3JMjcpyGBHX5","type":"message","role":"assistant","model":"claude-opus-4-7","content":[{"type":"text","text":"Hello again! It's nice to see you. How can I assist you today? Is there anything specific you'd like to chat about or any questions you have?"}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":11,"output_tokens":36}}}}
{"custom_id":"my-first-request","result":{"type":"succeeded","message":{"id":"msg_01FqfsLoHwgeFbguDgpz48m7","type":"message","role":"assistant","model":"claude-opus-4-7","content":[{"type":"text","text":"Hello! How can I assist you today? Feel free to ask me any questions or let me know if there's anything you'd like to chat about."}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":10,"output_tokens":34}}}}

如果您的结果有错误,其 result.error 将被设置为标准的错误格式

Tip

批处理结果可能与输入顺序不匹配

批处理结果可以以任何顺序返回,可能与创建批处理时的请求顺序不匹配。在上面的示例中,第二个批处理请求的结果在第一个之前返回。要正确匹配结果与对应的请求,请始终使用 custom_id 字段。

取消 Message Batch

您可以使用取消端点取消当前正在处理的 Message Batch。取消后,批处理的 processing_status 将立即变为 canceling。您可以使用上面描述的相同轮询技术等待取消完成。已取消的批处理最终状态为 ended,可能包含取消前已处理请求的部分结果。

#!/bin/sh
MESSAGE_BATCH_ID=$(curl -s https://api.anthropic.com/v1/messages/batches \
  --header "x-api-key: $ANTHROPIC_API_KEY" \
  --header "anthropic-version: 2023-06-01" \
  --header "content-type: application/json" \
  --data '{
    "requests": [{
      "custom_id": "test-1",
      "params": {
        "model": "claude-opus-4-7",
        "max_tokens": 100,
        "messages": [{"role": "user", "content": "Hi"}]
      }
    }]
  }' | jq -r '.id')
curl --request POST https://api.anthropic.com/v1/messages/batches/$MESSAGE_BATCH_ID/cancel \
    --header "x-api-key: $ANTHROPIC_API_KEY" \
    --header "anthropic-version: 2023-06-01"
#!/bin/bash
MESSAGE_BATCH_ID=$(ant messages:batches create \
  --transform id --raw-output <<'YAML'
requests:
  - custom_id: test-1
    params:
      model: claude-opus-4-7
      max_tokens: 100
      messages:
        - role: user
          content: Hi
YAML
)
ant messages:batches cancel --message-batch-id "$MESSAGE_BATCH_ID"
import anthropic

client = anthropic.Anthropic()

MESSAGE_BATCH_ID = "msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d"

message_batch = client.messages.batches.cancel(
    MESSAGE_BATCH_ID,
)
print(message_batch)
import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic();

const messageBatch = await anthropic.messages.batches.cancel(MESSAGE_BATCH_ID);
console.log(messageBatch);
using Anthropic;
using Anthropic.Models.Messages.Batches;

AnthropicClient client = new();
string messageBatchId = Environment.GetEnvironmentVariable("MESSAGE_BATCH_ID");

var messageBatch = await client.Messages.Batches.Cancel(messageBatchId);
Console.WriteLine(messageBatch);
package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/anthropics/anthropic-sdk-go"
)

func main() {
	client := anthropic.NewClient()
	messageBatchID := os.Getenv("MESSAGE_BATCH_ID")

	messageBatch, err := client.Messages.Batches.Cancel(context.TODO(), messageBatchID)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(messageBatch)
}
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.batches.*;

public class BatchCancelExample {

  public static void main(String[] args) {
    AnthropicClient client = AnthropicOkHttpClient.fromEnv();

    MessageBatch messageBatch = client
      .messages()
      .batches()
      .cancel("msgbatch_01HkcTjaV5uDC8jWR4ZsDV8d");
    System.out.println(messageBatch);
  }
}
<?php

use Anthropic\Client;

$client = new Client(apiKey: getenv("ANTHROPIC_API_KEY"));

$messageBatch = $client->messages->batches->cancel(
    messageBatchID: 'msgbatch_example_id',
);
echo $messageBatch;
require "anthropic"

client = Anthropic::Client.new

message_batch_id = ENV.fetch("MESSAGE_BATCH_ID")
message_batch = client.messages.batches.cancel(message_batch_id)
puts message_batch

响应将显示批处理处于 canceling 状态:

{
  "id": "msgbatch_013Zva2CMHLNnXjNJJKqJ2EF",
  "type": "message_batch",
  "processing_status": "canceling",
  "request_counts": {
    "processing": 2,
    "succeeded": 0,
    "errored": 0,
    "canceled": 0,
    "expired": 0
  },
  "ended_at": null,
  "created_at": "2024-09-24T18:37:24.100435Z",
  "expires_at": "2024-09-25T18:37:24.100435Z",
  "cancel_initiated_at": "2024-09-24T18:39:03.114875Z",
  "results_url": null
}

在 Message Batches 中使用 prompt caching

Message Batches API 支持 prompt caching,让您可以降低批处理请求的成本和处理时间。Prompt caching 和 Message Batches 的定价折扣可以叠加,在同时使用两个功能时提供更大的成本节约。但是,由于批处理请求是异步并发处理的,cache 命中以尽力而为的方式提供。用户通常会经历 30% 到 98% 的 cache 命中率,具体取决于其流量模式。

要在批处理请求中最大化 cache 命中的可能性:

  1. 在批处理中的每个 Message 请求中包含相同的 cache_control
  2. 保持稳定的请求流,防止 cache 条目在 5 分钟生命周期后过期
  3. 构建请求以共享尽可能多的缓存内容

在批处理中实现 prompt caching 的示例:

curl https://api.anthropic.com/v1/messages/batches \
     --header "x-api-key: $ANTHROPIC_API_KEY" \
     --header "anthropic-version: 2023-06-01" \
     --header "content-type: application/json" \
     --data \
'{
    "requests": [
        {
            "custom_id": "my-first-request",
            "params": {
                "model": "claude-opus-4-7",
                "max_tokens": 1024,
                "system": [
                    {
                        "type": "text",
                        "text": "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
                    },
                    {
                        "type": "text",
                        "text": "<the entire contents of Pride and Prejudice>",
                        "cache_control": {"type": "ephemeral"}
                    }
                ],
                "messages": [
                    {"role": "user", "content": "Analyze the major themes in Pride and Prejudice."}
                ]
            }
        },
        {
            "custom_id": "my-second-request",
            "params": {
                "model": "claude-opus-4-7",
                "max_tokens": 1024,
                "system": [
                    {
                        "type": "text",
                        "text": "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
                    },
                    {
                        "type": "text",
                        "text": "<the entire contents of Pride and Prejudice>",
                        "cache_control": {"type": "ephemeral"}
                    }
                ],
                "messages": [
                    {"role": "user", "content": "Write a summary of Pride and Prejudice."}
                ]
            }
        }
    ]
}'
ant messages:batches create <<'YAML'
requests:
  - custom_id: my-first-request
    params:
      model: claude-opus-4-7
      max_tokens: 1024
      system:
        - type: text
          text: >
            You are an AI assistant tasked with analyzing literary works. Your
            goal is to provide insightful commentary on themes, characters, and
            writing style.
        - type: text
          text: "<the entire contents of Pride and Prejudice>"
          cache_control:
            type: ephemeral
      messages:
        - role: user
          content: Analyze the major themes in Pride and Prejudice.
  - custom_id: my-second-request
    params:
      model: claude-opus-4-7
      max_tokens: 1024
      system:
        - type: text
          text: >
            You are an AI assistant tasked with analyzing literary works. Your
            goal is to provide insightful commentary on themes, characters, and
            writing style.
        - type: text
          text: "<the entire contents of Pride and Prejudice>"
          cache_control:
            type: ephemeral
      messages:
        - role: user
          content: Write a summary of Pride and Prejudice.
YAML
import anthropic
from anthropic.types.message_create_params import MessageCreateParamsNonStreaming
from anthropic.types.messages.batch_create_params import Request

client = anthropic.Anthropic()

message_batch = client.messages.batches.create(
    requests=[
        Request(
            custom_id="my-first-request",
            params=MessageCreateParamsNonStreaming(
                model="claude-opus-4-7",
                max_tokens=1024,
                system=[
                    {
                        "type": "text",
                        "text": "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n",
                    },
                    {
                        "type": "text",
                        "text": "<the entire contents of Pride and Prejudice>",
                        "cache_control": {"type": "ephemeral"},
                    },
                ],
                messages=[
                    {
                        "role": "user",
                        "content": "Analyze the major themes in Pride and Prejudice.",
                    }
                ],
            ),
        ),
        Request(
            custom_id="my-second-request",
            params=MessageCreateParamsNonStreaming(
                model="claude-opus-4-7",
                max_tokens=1024,
                system=[
                    {
                        "type": "text",
                        "text": "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n",
                    },
                    {
                        "type": "text",
                        "text": "<the entire contents of Pride and Prejudice>",
                        "cache_control": {"type": "ephemeral"},
                    },
                ],
                messages=[
                    {
                        "role": "user",
                        "content": "Write a summary of Pride and Prejudice.",
                    }
                ],
            ),
        ),
    ]
)
import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic();

const messageBatch = await anthropic.messages.batches.create({
  requests: [
    {
      custom_id: "my-first-request",
      params: {
        model: "claude-opus-4-7",
        max_tokens: 1024,
        system: [
          {
            type: "text",
            text: "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
          },
          {
            type: "text",
            text: "<the entire contents of Pride and Prejudice>",
            cache_control: { type: "ephemeral" }
          }
        ],
        messages: [
          { role: "user", content: "Analyze the major themes in Pride and Prejudice." }
        ]
      }
    },
    {
      custom_id: "my-second-request",
      params: {
        model: "claude-opus-4-7",
        max_tokens: 1024,
        system: [
          {
            type: "text",
            text: "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
          },
          {
            type: "text",
            text: "<the entire contents of Pride and Prejudice>",
            cache_control: { type: "ephemeral" }
          }
        ],
        messages: [{ role: "user", content: "Write a summary of Pride and Prejudice." }]
      }
    }
  ]
});
using Anthropic;
using Anthropic.Models.Messages;
using Anthropic.Models.Messages.Batches;

AnthropicClient client = new()
{
    ApiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY")
};

var messageBatch = await client.Messages.Batches.Create(new BatchCreateParams
{
    Requests =
    [
        new()
        {
            CustomID = "my-first-request",
            Params = new()
            {
                Model = Model.ClaudeOpus4_7,
                MaxTokens = 1024,
                System = new List<TextBlockParam>
                {
                    new()
                    {
                        Text = "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
                    },
                    new()
                    {
                        Text = "<the entire contents of Pride and Prejudice>",
                        CacheControl = new()
                    }
                },
                Messages =
                [
                    new() { Role = Role.User, Content = "Analyze the major themes in Pride and Prejudice." }
                ]
            }
        },
        new()
        {
            CustomID = "my-second-request",
            Params = new()
            {
                Model = Model.ClaudeOpus4_7,
                MaxTokens = 1024,
                System = new List<TextBlockParam>
                {
                    new()
                    {
                        Text = "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
                    },
                    new()
                    {
                        Text = "<the entire contents of Pride and Prejudice>",
                        CacheControl = new()
                    }
                },
                Messages =
                [
                    new() { Role = Role.User, Content = "Write a summary of Pride and Prejudice." }
                ]
            }
        }
    ]
});
package main

import (
	"context"
	"log"

	"github.com/anthropics/anthropic-sdk-go"
)

func main() {
	client := anthropic.NewClient()

	messageBatch, err := client.Messages.Batches.New(context.TODO(), anthropic.MessageBatchNewParams{
		Requests: []anthropic.MessageBatchNewParamsRequest{
			{
				CustomID: "my-first-request",
				Params: anthropic.MessageBatchNewParamsRequestParams{
					Model:     anthropic.ModelClaudeOpus4_7,
					MaxTokens: 1024,
					System: []anthropic.TextBlockParam{
						{
							Text: "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n",
						},
						{
							Text:         "<the entire contents of Pride and Prejudice>",
							CacheControl: anthropic.NewCacheControlEphemeralParam(),
						},
					},
					Messages: []anthropic.MessageParam{
						anthropic.NewUserMessage(anthropic.NewTextBlock("Analyze the major themes in Pride and Prejudice.")),
					},
				},
			},
			{
				CustomID: "my-second-request",
				Params: anthropic.MessageBatchNewParamsRequestParams{
					Model:     anthropic.ModelClaudeOpus4_7,
					MaxTokens: 1024,
					System: []anthropic.TextBlockParam{
						{
							Text: "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n",
						},
						{
							Text:         "<the entire contents of Pride and Prejudice>",
							CacheControl: anthropic.NewCacheControlEphemeralParam(),
						},
					},
					Messages: []anthropic.MessageParam{
						anthropic.NewUserMessage(anthropic.NewTextBlock("Write a summary of Pride and Prejudice.")),
					},
				},
			},
		},
	})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("%+v\n", messageBatch)
}
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.CacheControlEphemeral;
import com.anthropic.models.messages.Model;
import com.anthropic.models.messages.TextBlockParam;
import com.anthropic.models.messages.batches.*;
import java.util.List;

public class BatchExample {

  public static void main(String[] args) {
    AnthropicClient client = AnthropicOkHttpClient.fromEnv();

    BatchCreateParams createParams = BatchCreateParams.builder()
      .addRequest(
        BatchCreateParams.Request.builder()
          .customId("my-first-request")
          .params(
            BatchCreateParams.Request.Params.builder()
              .model(Model.CLAUDE_OPUS_4_7)
              .maxTokens(1024)
              .systemOfTextBlockParams(
                List.of(
                  TextBlockParam.builder()
                    .text(
                      "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
                    )
                    .build(),
                  TextBlockParam.builder()
                    .text("<the entire contents of Pride and Prejudice>")
                    .cacheControl(CacheControlEphemeral.builder().build())
                    .build()
                )
              )
              .addUserMessage("Analyze the major themes in Pride and Prejudice.")
              .build()
          )
          .build()
      )
      .addRequest(
        BatchCreateParams.Request.builder()
          .customId("my-second-request")
          .params(
            BatchCreateParams.Request.Params.builder()
              .model(Model.CLAUDE_OPUS_4_7)
              .maxTokens(1024)
              .systemOfTextBlockParams(
                List.of(
                  TextBlockParam.builder()
                    .text(
                      "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
                    )
                    .build(),
                  TextBlockParam.builder()
                    .text("<the entire contents of Pride and Prejudice>")
                    .cacheControl(CacheControlEphemeral.builder().build())
                    .build()
                )
              )
              .addUserMessage("Write a summary of Pride and Prejudice.")
              .build()
          )
          .build()
      )
      .build();

    MessageBatch messageBatch = client.messages().batches().create(createParams);
  }
}
<?php

use Anthropic\Client;

$client = new Client(apiKey: getenv("ANTHROPIC_API_KEY"));

$messageBatch = $client->messages->batches->create(
    requests: [
        [
            'custom_id' => 'my-first-request',
            'params' => [
                'model' => 'claude-opus-4-7',
                'max_tokens' => 1024,
                'system' => [
                    [
                        'type' => 'text',
                        'text' => 'You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n'
                    ],
                    [
                        'type' => 'text',
                        'text' => '<the entire contents of Pride and Prejudice>',
                        'cache_control' => ['type' => 'ephemeral']
                    ]
                ],
                'messages' => [
                    ['role' => 'user', 'content' => 'Analyze the major themes in Pride and Prejudice.']
                ]
            ]
        ],
        [
            'custom_id' => 'my-second-request',
            'params' => [
                'model' => 'claude-opus-4-7',
                'max_tokens' => 1024,
                'system' => [
                    [
                        'type' => 'text',
                        'text' => 'You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n'
                    ],
                    [
                        'type' => 'text',
                        'text' => '<the entire contents of Pride and Prejudice>',
                        'cache_control' => ['type' => 'ephemeral']
                    ]
                ],
                'messages' => [
                    ['role' => 'user', 'content' => 'Write a summary of Pride and Prejudice.']
                ]
            ]
        ]
    ],
);
require "anthropic"

client = Anthropic::Client.new

message_batch = client.messages.batches.create(
  requests: [
    {
      custom_id: "my-first-request",
      params: {
        model: "claude-opus-4-7",
        max_tokens: 1024,
        system: [
          {
            type: "text",
            text: "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
          },
          {
            type: "text",
            text: "<the entire contents of Pride and Prejudice>",
            cache_control: { type: "ephemeral" }
          }
        ],
        messages: [
          { role: "user", content: "Analyze the major themes in Pride and Prejudice." }
        ]
      }
    },
    {
      custom_id: "my-second-request",
      params: {
        model: "claude-opus-4-7",
        max_tokens: 1024,
        system: [
          {
            type: "text",
            text: "You are an AI assistant tasked with analyzing literary works. Your goal is to provide insightful commentary on themes, characters, and writing style.\n"
          },
          {
            type: "text",
            text: "<the entire contents of Pride and Prejudice>",
            cache_control: { type: "ephemeral" }
          }
        ],
        messages: [
          { role: "user", content: "Write a summary of Pride and Prejudice." }
        ]
      }
    }
  ]
)

在此示例中,批处理中的两个请求都包含相同的系统消息和标记了 cache_control 的《傲慢与偏见》全文,以增加 cache 命中的可能性。

扩展输出(beta)

output-300k-2026-03-24 beta 头将使用 Claude Opus 4.7、Claude Opus 4.6 或 Claude Sonnet 4.6 的批处理请求的 max_tokens 上限提高到 300,000。包含此头以在单轮中生成远超标准限制(根据模型为 64k 到 128k)的输出。

Note

扩展输出仅在 Message Batches API 上可用,不在同步 Messages API 上可用。它在 Claude API 和 AWS 上的 Claude Platform 上受支持,目前在 Amazon Bedrock、Vertex AI 或 Microsoft Foundry 上不可用。

将扩展输出用于长篇生成,如书籍长度的草稿和技术文档、详尽的结构化数据提取、大型代码生成脚手架和长推理链。

单次 300k token 的生成可能需要超过一小时才能完成,因此请在 24 小时处理窗口内规划您的批处理提交。标准批处理定价(标准 API 价格的 50%)适用。

curl https://api.anthropic.com/v1/messages/batches \
     --header "x-api-key: $ANTHROPIC_API_KEY" \
     --header "anthropic-version: 2023-06-01" \
     --header "anthropic-beta: output-300k-2026-03-24" \
     --header "content-type: application/json" \
     --data \
'{
    "requests": [
        {
            "custom_id": "long-form-request",
            "params": {
                "model": "claude-opus-4-7",
                "max_tokens": 300000,
                "messages": [
                    {"role": "user", "content": "Write a comprehensive technical guide to building distributed systems, covering architecture patterns, consistency models, fault tolerance, and operational best practices."}
                ]
            }
        }
    ]
}'
ant beta:messages:batches create --beta output-300k-2026-03-24 <<'YAML'
requests:
  - custom_id: long-form-request
    params:
      model: claude-opus-4-7
      max_tokens: 300000
      messages:
        - role: user
          content: >-
            Write a comprehensive technical guide to building distributed
            systems, covering architecture patterns, consistency models,
            fault tolerance, and operational best practices.
YAML
import anthropic
from anthropic.types.beta.message_create_params import MessageCreateParamsNonStreaming
from anthropic.types.beta.messages.batch_create_params import Request

client = anthropic.Anthropic()

message_batch = client.beta.messages.batches.create(
    betas=["output-300k-2026-03-24"],
    requests=[
        Request(
            custom_id="long-form-request",
            params=MessageCreateParamsNonStreaming(
                model="claude-opus-4-7",
                max_tokens=300_000,
                messages=[
                    {
                        "role": "user",
                        "content": "Write a comprehensive technical guide to building distributed systems, covering architecture patterns, consistency models, fault tolerance, and operational best practices.",
                    }
                ],
            ),
        ),
    ],
)

print(message_batch)
import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic();

const messageBatch = await anthropic.beta.messages.batches.create({
  betas: ["output-300k-2026-03-24"],
  requests: [
    {
      custom_id: "long-form-request",
      params: {
        model: "claude-opus-4-7",
        max_tokens: 300000,
        messages: [
          {
            role: "user",
            content:
              "Write a comprehensive technical guide to building distributed systems, covering architecture patterns, consistency models, fault tolerance, and operational best practices."
          }
        ]
      }
    }
  ]
});

console.log(messageBatch);
using Anthropic;
using Anthropic.Models.Beta.Messages;
using Anthropic.Models.Beta.Messages.Batches;

AnthropicClient client = new();

var batch = await client.Beta.Messages.Batches.Create(new BatchCreateParams
{
    Betas = ["output-300k-2026-03-24"],
    Requests =
    [
        new()
        {
            CustomID = "long-form-request",
            Params = new()
            {
                Model = "claude-opus-4-7",
                MaxTokens = 300_000,
                Messages =
                [
                    new() { Role = Role.User, Content = "Write a comprehensive technical guide to building distributed systems, covering architecture patterns, consistency models, fault tolerance, and operational best practices." }
                ]
            }
        }
    ]
});

Console.WriteLine(batch);
package main

import (
	"context"
	"fmt"

	"github.com/anthropics/anthropic-sdk-go"
)

func main() {
	client := anthropic.NewClient()

	batch, err := client.Beta.Messages.Batches.New(context.Background(),
		anthropic.BetaMessageBatchNewParams{
			Betas: []anthropic.AnthropicBeta{"output-300k-2026-03-24"},
			Requests: []anthropic.BetaMessageBatchNewParamsRequest{
				{
					CustomID: "long-form-request",
					Params: anthropic.BetaMessageBatchNewParamsRequestParams{
						Model:     anthropic.ModelClaudeOpus4_7,
						MaxTokens: 300_000,
						Messages: []anthropic.BetaMessageParam{
							anthropic.NewBetaUserMessage(
								anthropic.NewBetaTextBlock("Write a comprehensive technical guide to building distributed systems, covering architecture patterns, consistency models, fault tolerance, and operational best practices."),
							),
						},
					},
				},
			},
		})
	if err != nil {
		panic(err)
	}

	fmt.Println(batch.ID)
}
import com.anthropic.client.AnthropicClient;
import com.anthropic.client.okhttp.AnthropicOkHttpClient;
import com.anthropic.models.messages.Model;
import com.anthropic.models.beta.messages.batches.*;

void main() {
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  BatchCreateParams params = BatchCreateParams.builder()
    .addBeta("output-300k-2026-03-24")
    .addRequest(
      BatchCreateParams.Request.builder()
        .customId("long-form-request")
        .params(
          BatchCreateParams.Request.Params.builder()
            .model(Model.CLAUDE_OPUS_4_7)
            .maxTokens(300_000L)
            .addUserMessage("Write a comprehensive technical guide to building distributed systems, covering architecture patterns, consistency models, fault tolerance, and operational best practices.")
            .build()
        )
        .build()
    )
    .build();

  BetaMessageBatch messageBatch = client.beta().messages().batches().create(params);

  IO.println(messageBatch);
}
<?php

use Anthropic\Client;

$client = new Client();

$batch = $client->beta->messages->batches->create(
    betas: ['output-300k-2026-03-24'],
    requests: [
        [
            'custom_id' => 'long-form-request',
            'params' => [
                'model' => 'claude-opus-4-7',
                'max_tokens' => 300_000,
                'messages' => [
                    ['role' => 'user', 'content' => 'Write a comprehensive technical guide to building distributed systems, covering architecture patterns, consistency models, fault tolerance, and operational best practices.']
                ]
            ]
        ]
    ],
);

echo $batch->id;
require "anthropic"

client = Anthropic::Client.new

batch = client.beta.messages.batches.create(
  betas: ["output-300k-2026-03-24"],
  requests: [
    {
      custom_id: "long-form-request",
      params: {
        model: "claude-opus-4-7",
        max_tokens: 300_000,
        messages: [
          { role: "user", content: "Write a comprehensive technical guide to building distributed systems, covering architecture patterns, consistency models, fault tolerance, and operational best practices." }
        ]
      }
    }
  ]
)

puts batch

有效批处理的最佳实践

要充分利用 Batches API:

  • 定期监控批处理状态,并为失败的请求实现适当的重试逻辑。
  • 使用有意义的 custom_id 值,以便轻松匹配结果和请求,因为顺序不保证。
  • 考虑将非常大的数据集拆分为多个批处理,以便更好地管理。
  • 使用 Messages API 对单个请求结构进行干运行,以避免验证错误。

排查常见问题

如果遇到意外行为:

  • 验证批处理请求总大小不超过 256 MB。如果请求大小太大,您可能会收到 413 request_too_large 错误。
  • 检查您是否对批处理中的所有请求使用了支持的模型
  • 确保批处理中的每个请求都有唯一的 custom_id
  • 确认自批处理 created_at(而非处理 ended_at)时间以来不超过 29 天。如果超过 29 天,结果将不再可查看。
  • 确认批处理未被取消。

请注意,批处理中一个请求的失败不会影响其他请求的处理。


批处理存储和隐私

  • 工作区隔离:批处理在其创建的工作区内隔离。只能由与该工作区关联的 API 密钥或在控制台中具有查看工作区批处理权限的用户访问。

  • 结果可用性:批处理结果在批处理创建后 29 天内可用,为检索和处理提供充足的时间。


数据保留

批处理在批处理创建后最多存储请求和响应数据 29 天。您可以在处理后随时使用 DELETE /v1/messages/batches/{batch_id} 端点删除消息批处理。要删除正在进行的批处理,请先取消它。异步处理需要在服务器端存储输入和输出,直到批处理完成和结果检索。

有关所有功能的 ZDR 资格,请参阅 API 和数据保留

常见问题

批处理需要多长时间处理?

批处理最多可能需要 24 小时处理,但许多批处理会更快完成。实际处理时间取决于批处理的大小、当前需求和您的请求量。批处理可能会过期并在 24 小时内未完成。

Batches API 是否适用于所有模型?

有关支持的模型列表,请参阅上文

我能否将 Message Batches API 与其他 API 功能一起使用?

是的,Message Batches API 支持 Messages API 中可用的所有功能,包括 beta 功能。但是,批处理请求不支持流式传输。

Message Batches API 如何影响定价?

Message Batches API 对所有使用量提供比标准 API 价格低 50% 的折扣。这适用于输入 token、输出 token 和任何特殊 token。有关定价的更多信息,请访问定价页面

我能否在提交后更新批处理?

不能,一旦批处理提交后就无法修改。如果需要进行更改,您应该取消当前批处理并提交一个新的。请注意,取消可能不会立即生效。

Message Batches API 有速率限制吗?它们与 Messages API 速率限制如何交互?

Message Batches API 除了对需要处理的请求数量有限制外,还有基于 HTTP 请求的速率限制。请参阅 Message Batches API 速率限制。使用 Batches API 不会影响 Messages API 中的速率限制。

如何处理批处理请求中的错误?

当您检索结果时,每个请求都会有一个 result 字段,指示它是 succeedederroredcanceled 还是 expired。对于 errored 结果,将提供额外的错误信息。请在 API 参考中查看错误响应对象。

Message Batches API 如何处理隐私和数据分离?

Message Batches API 设计了强大的隐私和数据分离措施:

  1. 批处理及其结果在其创建的工作区内隔离。这意味着只能由来自同一工作区的 API 密钥访问。
  2. 批处理中的每个请求都是独立处理的,请求之间没有数据泄漏。
  3. 结果仅在有限时间内可用(29 天),并遵循 Anthropic 的数据保留政策
  4. 可以在组织级别或按工作区禁用在控制台中下载批处理结果。

我能否在 Message Batches API 中使用 prompt caching?

是的,可以在 Message Batches API 中使用 prompt caching。但是,由于异步批处理请求可以并发和以任何顺序处理,cache 命中以尽力而为的方式提供。