So you've got a Claude API key and a vague idea that you want to use it for something. Maybe a chatbot. Maybe parsing. Maybe automation. The problem is most tutorials are either "hello world" garbage or they dive into prompt engineering theory that doesn't help you ship anything.
Here's what actually works. Five patterns I've seen developers successfully throw into production without losing their minds.
1. Structured Output for Data Extraction
Stop writing regex. Stop parsing XML. Use the API's built-in structured output.
from anthropic import Anthropic
client = Anthropic()
response = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
thinking={"type": "enabled", "budget_tokens": 5000},
messages=[
{
"role": "user",
"content": """Extract invoice data from this text:
Invoice #2024-1001
Customer: ACME Corp
Amount: $5,234.50
Date: August 20, 2024"""
}
],
system="Return JSON with fields: invoice_id, customer, amount, date"
)
# Actually get structured JSON back, not a rambling paragraph
The thinking parameter above gives Claude time to reason through the task. It costs more but it works. Your success rate on messy data jumps from 70% to 95%.
2. Batch Processing for Cost Optimization
If you're processing thousands of items, batching is your friend. Real savings.
import json
from anthropic import Anthropic
client = Anthropic()
# Create batch requests
requests = []
for i, text in enumerate(your_dataset):
requests.append({
"custom_id": f"request-{i}",
"params": {
"model": "claude-3-5-sonnet-20241022",
"max_tokens": 500,
"messages": [
{
"role": "user",
"content": f"Summarize this: {text}"
}
]
}
})
# Submit batch
batch = client.messages.batch.create(requests=requests)
# Process results later (much cheaper than real-time)
results = client.messages.batch.retrieve(batch.id)
Batches run asynchronously and cost 50% less. Perfect for overnight jobs.
3. Conversation Memory Without Storing Everything
Cache your system prompt and frequently-referenced context to save tokens and money.
conversation_history = []
def chat_with_context(user_message, context_docs):
conversation_history.append({
"role": "user",
"content": user_message
})
response = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
system=[
{
"type": "text",
"text": "You are a helpful assistant focused on this knowledge base."
},
{
"type": "text",
"text": f"Context: {context_docs}",
"cache_control": {"type": "ephemeral"}
}
],
messages=conversation_history
)
conversation_history.append({
"role": "assistant",
"content": response.content[0].text
})
return response.content[0].text
The cache_control flag tells Claude to reuse that context. If you're running the same query multiple times against the same knowledge base, you're cutting costs by 30-40%.
4. Vision for Real-world Automation
Screenshot parsing, document analysis, visual QA — Claude's vision is genuinely useful.
import base64
import json
def analyze_screenshot(image_path):
with open(image_path, "rb") as img_file:
image_data = base64.standard_b64encode(img_file.read()).decode("utf-8")
response = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
messages=[
{
"role": "user",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": image_data,
},
},
{
"type": "text",
"text": "Extract all form field labels and values from this screenshot. Return as JSON."
}
],
}
],
)
return response.content[0].text
Use this for automated testing, document processing, UI feedback — anything that needs visual understanding without training a model.
5. Streaming for Real-time UX
If your users are waiting for a response, stream it. Feels faster, actually is faster.
def stream_response(user_input):
with client.messages.stream(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
messages=[
{"role": "user", "content": user_input}
]
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)
yield text
Browsers, terminals, chat apps — all start showing the response before Claude finishes thinking. Your app feels snappier even on high-latency connections.
Real-World Gotchas
Token counting before you send. Use client.beta.messages.count_tokens() to check your request size first. Saves embarrassing overages.
Rate limits sneak up. Implement exponential backoff. Don't hammer the API when you hit a 429.
Model updates happen. Your "claude-3-5-sonnet-20241022" will eventually be old. Pin specific versions in production, test new models in staging.
Context length is not infinite. 200k tokens sounds huge until you're parsing a 50-page PDF. Chunk your data strategically.
What This Isn't
This isn't a guide to prompt engineering tricks or system prompt hacks. That stuff changes weekly and honestly most of it doesn't matter. These patterns work because they're about how you use the API, not what words you put in the prompt.
Want more practical patterns like this? Check out LearnAI Weekly — actual code, actual results, no fluff.
Ship it. 🚀
Top comments (0)