Calling an LLM API with Python: Your First Request
Introduction
The best way to understand LLMs is to call one from code. This lesson uses the Anthropic Python SDK to send a request, add a system prompt, hold a multi-turn conversation, inspect token usage, and handle errors. The same ideas apply to other providers, though names differ.
Prerequisites
- Python 3.10 or newer
- An API key from your provider, stored in an environment variable (never in code)
Step-by-Step Guide
Step 1: Install the SDK and set your key
Install the package and export your key as the ANTHROPIC_API_KEY environment variable. The client reads it automatically, so you never hard-code a secret.
pip install anthropic
# macOS / Linux
export ANTHROPIC_API_KEY="your-key-here"
# Windows (PowerShell)
# $env:ANTHROPIC_API_KEY = "your-key-here"Step 2: Send your first request
A request names a model, sets max_tokens, and sends a list of messages. The response content is a list of blocks, so read the text from blocks whose type is text. Use a current model ID from your provider's documentation. Set a generous max_tokens: some models spend tokens on internal reasoning before the visible answer, and a small limit can cut the answer short.
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
messages=[{"role": "user", "content": "What is the capital of France?"}],
)
for block in response.content:
if block.type == "text":
print(block.text)Step 3: Add a system prompt
The system prompt sets the role, tone, and rules for the whole conversation, separately from the user's messages.
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
system="You are a patient tutor. Explain ideas simply and give one example.",
messages=[{"role": "user", "content": "What is a Python decorator?"}],
)Step 4: Hold a multi-turn conversation
The API is stateless: it remembers nothing between calls. To continue a conversation, send the full history each time, appending each assistant reply and the next user message.
history = []
def chat(user_message: str) -> str:
history.append({"role": "user", "content": user_message})
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
messages=history,
)
reply = next((b.text for b in response.content if b.type == "text"), "")
history.append({"role": "assistant", "content": reply})
return reply
print(chat("My name is Alice."))
print(chat("What is my name?")) # the history makes this workStep 5: Check usage, stop reason, and errors
Log token usage to watch cost, and check stop_reason: end_turn means it finished, max_tokens means it was cut off. Catch the SDK's typed exceptions, most specific first, instead of one broad handler.
print(response.usage.input_tokens, response.usage.output_tokens)
print(response.stop_reason) # end_turn, max_tokens, tool_use, ...
try:
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
messages=[{"role": "user", "content": "Hello"}],
)
except anthropic.RateLimitError:
print("Rate limited. Retry later.")
except anthropic.APIStatusError as e:
print("API error:", e.status_code)
except anthropic.APIConnectionError:
print("Network problem.")FAQs
- Why is the conversation history sent every time?
- The model has no memory between requests. Your code holds the conversation and resends it, which is also why long chats cost more per turn.
- Do I need to implement retries myself?
- Usually not. The official SDK automatically retries connection errors and rate-limit or server errors a couple of times with backoff. Add your own logic only for behavior beyond that.
Summary
A request is a model, a token limit, and messages. Add a system prompt for behavior, resend history for multi-turn chats, give max_tokens plenty of room, and handle errors with typed exceptions.
Comments
Log in or create a free account to join the discussion.