Before going any further with this build, a quick note. This build assumes you have read aie_1.0. If you have not, start there, it’ll make this make more sense.
In the previous lesson, we established that an LLM, Large Language Model, is a prediction machine. It has no memory i.e. it is stateless. And as a result, it depends on the context you provide. In this build, we are going to talk to one in code. We’ll call what we build First Contact.
What we are building
A Python script that makes an API call to Anthropic, prints what it gets back and logs how many tokens (the unit a context window is measured in) it used. It is intended to be a simple build so you see how LLM calls work.
What you need
- A terminal
- Python installed on your machine
- An Anthropic API key ( platform.claude.com , you will need to add a small credit balance as the free tier does not cover API access)
- A code editor (VS Code is fine if you do not have a preference)
Setting up
Create a folder for the project and set up a virtual environment. A virtual environment keeps your project's dependencies isolated, you can think of it as a container for everything this project needs, separate from anything else on your machine.
mkdir ai-engineering
cd ai-engineering
python3 -m venv venv
source venv/bin/activate
You will know it worked when you see (venv) at the start of your terminal line.
Install the two libraries you need:
pip install anthropic python-dotenv
anthropicis the official Python library for talking to Claude.python-dotenvreads your API key from a file so you never have to hardcode it in your script.
Create a .env file and add your key:
ANTHROPIC_API_KEY=your_key_here
Create the script file:
mkdir 01
touch 01/first_contact.py
Open 01/first_contact.py in your editor. This is where you will build the script, piece by piece.
Step 1: load your API key
The first thing the script needs to do is read your API key from the .env file. Without it, every call you make to Claude will fail.
from dotenv import load_dotenv
import os
load_dotenv()
load_dotenv()reads your.envfile and makes everything inside it available to the script.import osgives the script access to environment variables, the place where your API key lives afterload_dotenv()runs.
After this line runs, your API key exists in the environment and your code can access it.
Step 2: create the client
Before you can send a message to Claude, you need to create a connection to Anthropic’s API. You can think of it as opening a phone line, you set it up, and every call you make goes through it.
In your code, that connection is something called a client. It holds your credentials, knows where to send your requests and it gives you a way to interact with the API without dealing with any of the complications under the hood.
from anthropic import Anthropic
client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
os.getenv("ANTHROPIC_API_KEY")reads the key from the environment.Anthropic(api_key=...)creates the client using that key.
Step 3: make the API call
This is the call to Claude. You are sending a message and asking for a response.
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=1024,
messages=[
{"role": "user", "content": "What is a large language model? Answer in two sentences."}
]
)
A few things worth noting here:
modelspecifies which Claude model to use.max_tokenssets a ceiling on how long the response can be.- And
messages, that list with the role and content, is the context window in its simplest form. This is what you send to the model and it is all it can see.
Step 4: read the response
The response comes back as an object. You need to pull out the parts that matter, in our case this is the text and the token counts.
text = response.content[0].text
input_tokens = response.usage.input_tokens
output_tokens = response.usage.output_tokens
response.content[0].textis the model’s response as a string.response.usagegives you the token counts, how many tokens you sent in and how many the model generated back.
Step 5: print everything
print("Response:")
print(text)
print()
print(f"Input tokens: {input_tokens}")
print(f"Output tokens: {output_tokens}")
print(f"Total tokens: {input_tokens + output_tokens}")
Your final code should look like this:
from dotenv import load_dotenv
import os
from anthropic import Anthropic
load_dotenv()
client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=1024,
messages=[
{"role": "user", "content": "What is a large language model? Answer in two sentences."}
]
)
text = response.content[0].text
input_tokens = response.usage.input_tokens
output_tokens = response.usage.output_tokens
print("Response:")
print(text)
print()
print(f"Input tokens: {input_tokens}")
print(f"Output tokens: {output_tokens}")
print(f"Total tokens: {input_tokens + output_tokens}")
Run it
python3 01/first_contact.py
You should see something like this:
Response:
A large language model (LLM) is an AI system trained on vast amounts
of text data to understand and generate human language. It uses deep
learning to predict and produce text by identifying patterns in the
data it learned from.
Input tokens: 19
Output tokens: 51
Total tokens: 70
What you are seeing
The response is the prediction machine predicting, like we said in the last lesson, the most likely continuation of your input. Not based on any fact that it knows, it predicted what a two-sentence response to that question should look like based on its training data.
The token counts show what the context window looks like. You sent 19 (in my case) tokens. The model responded with 51. In total, the entire exchange used 70 tokens. That number is what adds up against the context window limit with every call that you make.
Now that you have made your first contact, in the next lesson, we’ll explore everything that went into the call we have just made. We’ll learn what happens when you hit send and learn how to start controlling it. If you have any questions about this build, let me know!