Claudio.Batches (Claudio v0.5.0)

View Source

Client for the Anthropic Message Batches API.

The Batches API allows you to process multiple Messages API requests asynchronously in a single batch operation. This is ideal for large-scale, non-urgent processing scenarios where you need to process thousands or millions of requests.

Features

  • Process up to 100,000 requests per batch
  • Maximum batch size of 256 MB
  • Asynchronous processing (up to 24 hours)
  • All Messages API features supported (streaming, tools, caching, etc.)
  • Results provided as downloadable .jsonl file
  • Support for beta features via client configuration

Limits and Quotas

  • Request limit: 100,000 requests per batch
  • Size limit: 256 MB per batch
  • Processing time: Up to 24 hours
  • Rate limits: Applied separately from Messages API

Batch Lifecycle

  1. Creating: Batch is being created and validated
  2. In progress: Batch is being processed
  3. Ended: Processing complete (check request_counts for results)
  4. Results available for download as JSONL

Complete Example

alias Claudio.Batches

# Create a batch of requests
requests = [
  %{
    custom_id: "req-1",
    params: %{
      model: "claude-3-5-sonnet-20241022",
      max_tokens: 1024,
      messages: [%{role: "user", content: "Hello"}]
    }
  },
  %{
    custom_id: "req-2",
    params: %{
      model: "claude-3-5-sonnet-20241022",
      max_tokens: 1024,
      messages: [%{role: "user", content: "Hi there"}]
    }
  }
]

# Submit batch
{:ok, batch} = Batches.create(client, requests)
IO.puts("Batch ID: #{batch["id"]}")

# Wait for completion with progress updates
{:ok, completed} = Batches.wait_for_completion(client, batch["id"], fn status ->
  counts = status["request_counts"]
  IO.puts("Progress: #{counts["succeeded"]}/#{counts["processing"]}")
end)

# Download results
{:ok, results_jsonl} = Batches.get_results(client, batch["id"])

# Parse JSONL results
results = String.split(results_jsonl, "

", trim: true)

|> Enum.map(&Jason.decode!/1)

# Process each result
Enum.each(results, fn result ->
  case result do
    %{"result" => %{"type" => "succeeded", "message" => message}} ->
      IO.puts("Success: #{result["custom_id"]}")

    %{"result" => %{"type" => "errored", "error" => error}} ->
      IO.puts("Error: #{error["message"]}")
  end
end)

Polling vs Wait

You can either manually poll for status or use wait_for_completion/3:

# Manual polling
{:ok, status} = Batches.get(client, batch_id)

case status["processing_status"] do
  "ended" -> IO.puts("Complete!")
  "in_progress" -> IO.puts("Still processing...")
  "canceling" -> IO.puts("Canceling...")
end

# Automatic waiting (recommended)
{:ok, completed} = Batches.wait_for_completion(
  client,
  batch_id,
  &progress_callback/1,
  poll_interval: 5_000  # Check every 5 seconds
)
{:ok, batches} = Batches.list(client)

# Cancel a batch
{:ok, _} = Batches.cancel(client, batch.id)

Summary

Functions

Cancels a batch that is currently in progress.

Creates a new message batch.

Deletes a batch and its results.

Retrieves information about a specific batch.

Retrieves the results of a completed batch.

Lists all batches for the account.

Waits for a batch to complete, polling at regular intervals.

Types

batch()

@type batch() :: %{
  id: String.t(),
  type: String.t(),
  processing_status: batch_status(),
  request_counts: map(),
  ended_at: String.t() | nil,
  created_at: String.t(),
  expires_at: String.t(),
  results_url: String.t() | nil
}

batch_request()

@type batch_request() :: %{custom_id: String.t(), params: map()}

batch_status()

@type batch_status() :: :in_progress | :canceling | :ended

Functions

cancel(client, batch_id)

@spec cancel(Req.Request.t(), String.t()) ::
  {:ok, map()} | {:error, Claudio.APIError.t()}

Cancels a batch that is currently in progress.

Note: Requests that have already started processing will complete, but no new requests from the batch will be started.

Example

{:ok, batch} = Claudio.Batches.cancel(client, "batch_123")
# batch.processing_status will be "canceling" or "ended"

create(client, requests)

@spec create(Req.Request.t(), [batch_request()]) ::
  {:ok, map()} | {:error, Claudio.APIError.t()}

Creates a new message batch.

Parameters

  • client - Req request configured with authentication
  • requests - List of batch requests, each with a custom_id and params

Example

requests = [
  %{
    "custom_id" => "my-request-1",
    "params" => %{
      "model" => "claude-3-5-sonnet-20241022",
      "max_tokens" => 1024,
      "messages" => [%{"role" => "user", "content" => "Hello"}]
    }
  }
]

{:ok, batch} = Claudio.Batches.create(client, requests)

delete(client, batch_id)

@spec delete(Req.Request.t(), String.t()) ::
  {:ok, map()} | {:error, Claudio.APIError.t()}

Deletes a batch and its results.

Note: This will delete both the batch metadata and any result files. This action cannot be undone.

Example

{:ok, _} = Claudio.Batches.delete(client, "batch_123")

get(client, batch_id)

@spec get(Req.Request.t(), String.t()) ::
  {:ok, map()} | {:error, Claudio.APIError.t()}

Retrieves information about a specific batch.

Example

{:ok, batch} = Claudio.Batches.get(client, "batch_123")
IO.inspect(batch.processing_status)
IO.inspect(batch.request_counts)

get_results(client, batch_id)

@spec get_results(Req.Request.t(), String.t()) ::
  {:ok, [map()]} | {:error, Claudio.APIError.t()}

Retrieves the results of a completed batch.

Returns a list of result objects, each containing the custom_id and either a successful result or an error.

Example

{:ok, results} = Claudio.Batches.get_results(client, "batch_123")

Enum.each(results, fn result ->
  case result do
    %{"custom_id" => id, "result" => result} ->
      IO.puts("Success for #{id}")
      IO.inspect(result)

    %{"custom_id" => id, "error" => error} ->
      IO.puts("Error for #{id}")
      IO.inspect(error)
  end
end)

list(client, opts \\ [])

@spec list(
  Req.Request.t(),
  keyword()
) :: {:ok, map()} | {:error, Claudio.APIError.t()}

Lists all batches for the account.

Options

  • :limit - Number of batches to return (default: 20, max: 100)
  • :before_id - Get batches before this ID (for pagination)
  • :after_id - Get batches after this ID (for pagination)

Example

# List first 50 batches
{:ok, response} = Claudio.Batches.list(client, limit: 50)

# Paginate through results
{:ok, next_page} = Claudio.Batches.list(client, after_id: response.last_id)

wait_for_completion(client, batch_id, opts \\ [])

@spec wait_for_completion(Req.Request.t(), String.t(), keyword()) ::
  {:ok, map()} | {:error, term()}

Waits for a batch to complete, polling at regular intervals.

Options

  • :poll_interval - Seconds between status checks (default: 30)
  • :timeout - Maximum seconds to wait (default: 86400 = 24 hours)
  • :callback - Function called with batch status on each poll

Example

{:ok, final_batch} = Claudio.Batches.wait_for_completion(
  client,
  batch_id,
  poll_interval: 60,
  timeout: 3600,
  callback: fn status ->
    IO.puts("Status: #{status.processing_status}")
    IO.inspect(status.request_counts)
  end
)

{:ok, results} = Claudio.Batches.get_results(client, final_batch.id)