Stage 01 · FoundationsModule 4 of 26~4h

Claude API Basics

Call the Claude API from Python with confidence.

← All modules in this stage

Calling messages.create once is easy. Wrapping it in code that doesn't fall over the first time the network blips, you hit a rate limit, or a user types something weird — that's this module.

By the end of this module you'll have

Time: about 1 hour for the basics, ~4 hours with all three notebooks.

Prerequisites: Modules 1, 2, and 3.


Stream a response (so users don't stare at a blank screen)

messages.create waits until the entire response is ready. For anything user-facing, that's a poor experience. Use messages.stream instead:

from anthropic import Anthropic
from dotenv import load_dotenv

load_dotenv()
client = Anthropic()

with client.messages.stream(
    model="claude-sonnet-4-6",
    max_tokens=600,
    messages=[{"role": "user", "content": "Write a 6-sentence pep talk for someone learning to code."}],
) as stream:
    for text_delta in stream.text_stream:
        print(text_delta, end="", flush=True)
    print()
    final = stream.get_final_message()

print(f"\n[done] {final.usage.input_tokens} in / {final.usage.output_tokens} out")

text_stream yields the text fragments as they arrive. get_final_message() returns the full message object once the stream closes — that's where usage lives.


Errors you'll actually hit

The Anthropic SDK raises a small set of exceptions. Handle them on purpose:

from anthropic import (
    Anthropic,
    APIConnectionError,    # network problem on your side
    APITimeoutError,       # request took too long
    RateLimitError,        # 429 — slow down
    APIStatusError,        # 4xx/5xx with a status code
    AuthenticationError,   # 401 — bad key
    BadRequestError,       # 400 — your prompt or args are wrong
)

A minimal but honest call site:

try:
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=400,
        messages=[{"role": "user", "content": user_input}],
    )
except AuthenticationError:
    raise SystemExit("Bad ANTHROPIC_API_KEY — check your .env file.")
except BadRequestError as e:
    # Fix the request shape; do not retry.
    raise SystemExit(f"Bad request: {e}")
except RateLimitError:
    # Retry with backoff (see below).
    raise
except (APIConnectionError, APITimeoutError):
    # Network-y; retry with backoff.
    raise

Two key rules:

  1. Never retry on BadRequestError or AuthenticationError. Those won't fix themselves.
  2. Always retry with backoff on RateLimitError, APIConnectionError, APITimeoutError.

A tiny retry wrapper

import time, random
from anthropic import Anthropic, RateLimitError, APIConnectionError, APITimeoutError

client = Anthropic()
TRANSIENT = (RateLimitError, APIConnectionError, APITimeoutError)

def call_with_retry(messages, *, model="claude-sonnet-4-6", max_attempts=4):
    for attempt in range(max_attempts):
        try:
            return client.messages.create(
                model=model,
                max_tokens=600,
                messages=messages,
            )
        except TRANSIENT:
            if attempt == max_attempts - 1:
                raise
            # Exponential backoff with jitter: ~1s, 2s, 4s plus 0–1s randomness.
            time.sleep((2 ** attempt) + random.random())

Things this does not do (and you might want later, but not yet):

Do the simple thing first.


What to log (and what not to)

Log enough to debug a bad reply tomorrow. Log nothing that endangers users.

Log this Avoid logging this
Model id, latency, input/output token counts Full user prompts containing PII
Whether you got a refusal or a normal reply API keys, even hashed
The first 200 chars of the user message (truncated, hashed if sensitive) Long prompt bodies in flat files indefinitely
Error type and request ID Anything you can't justify in a privacy review

Try changing one thing


Going deeper: open the notebooks


Module checklist


Next module

Module 5 · Tokens & Limits — what the numbers in response.usage actually cost you and how to keep them under control.