Python 88.3%
TypeScript 7.6%
Shell 4.1%
1#!/usr/bin/env python32"""Message Batches lifecycle with the official Python SDK.34STATUS: LIVE_VERIFIED 2026-09-18 (the same HTTP sequence was executed through scripts/live.py; this SDK5variant mirrors it 1:1 — client.messages.batches.create/retrieve/list/results/cancel/delete).6Model: claude-haiku-4-5-20251001, max_tokens 8, 2 requests (~$0.0001 at 50 % batch pricing).7Run: .venv/bin/python examples/anthropic/batch/batch_lifecycle.py8"""9from __future__ import annotations10import sys, time11from pathlib import Path1213ROOT = Path(__file__).resolve().parents[3]14sys.path.insert(0, str(ROOT))15from scripts.live import load_env, log_request # noqa: E402 (loads .env; never prints keys)1617load_env()18import anthropic # noqa: E4021920MODEL = "claude-haiku-4-5-20251001"21client = anthropic.Anthropic()222324def msg(custom_id: str, model: str) -> dict:25 return {"custom_id": custom_id, "params": {"model": model, "max_tokens": 8,26 "messages": [{"role": "user", "content": "Reply with OK."}]}}272829# 1. create (an invalid model is accepted at create time and shows up as an `errored` result)30batch = client.messages.batches.create(requests=[msg("ok-1", MODEL), msg("bad-model-1", "claude-does-not-exist-1")])31log_request("anthropic", "POST", "/v1/messages/batches", 200, 0.0001, "sdk example create")32print("created", batch.id, batch.processing_status, batch.request_counts)3334# 2. retrieve / list35print("retrieve", client.messages.batches.retrieve(batch.id).processing_status)36page = client.messages.batches.list(limit=1)37print("list limit=1 ->", [b.id for b in page.data], "has_more", page.has_more)3839# 3. poll until ended (every 20 s, ≤ 5 min). Observed: ~100 s for 2 tiny requests.40t0 = time.time()41while batch.processing_status != "ended" and time.time() - t0 < 300:42 time.sleep(20)43 batch = client.messages.batches.retrieve(batch.id)44 print(f" {time.time() - t0:5.0f}s {batch.processing_status} {batch.request_counts}")45log_request("anthropic", "GET", "/v1/messages/batches/{id}", 200, 0, f"sdk example polled {time.time() - t0:.0f}s")4647# 4. results — streaming JSONL decoder; unordered, keyed by custom_id48for entry in client.messages.batches.results(batch.id):49 r = entry.result50 if r.type == "succeeded":51 print(entry.custom_id, "succeeded:", r.message.content[0].text, r.message.usage.service_tier)52 elif r.type == "errored":53 print(entry.custom_id, "errored:", r.error.error.type, r.error.error.message)54 else: # canceled | expired55 print(entry.custom_id, r.type)56log_request("anthropic", "GET", "/v1/messages/batches/{id}/results", 200, 0, "sdk example results")5758# 5. delete (only once ended)59print("delete", client.messages.batches.delete(batch.id).type)60log_request("anthropic", "DELETE", "/v1/messages/batches/{id}", 200, 0, "sdk example delete")6162# 6. cancel path63b2 = client.messages.batches.create(requests=[msg("cancel-1", MODEL)])64b2 = client.messages.batches.cancel(b2.id)65print("cancel ->", b2.processing_status, "cancel_initiated_at", b2.cancel_initiated_at)66t0 = time.time()67while b2.processing_status != "ended" and time.time() - t0 < 240:68 time.sleep(15)69 b2 = client.messages.batches.retrieve(b2.id)70print("after cancel:", b2.request_counts)71print("delete #2", client.messages.batches.delete(b2.id).type)72log_request("anthropic", "POST", "/v1/messages/batches/{id}/cancel", 200, 0.0001, "sdk example cancel path + delete")73