{"slug": "building-your-first-llm-api-call-in-python-step-by-step", "title": "Building your first LLM API call in Python (step by step)", "summary": "A developer published a step-by-step guide for making a first LLM API call in Python, walking through setting up a virtual environment, installing the Anthropic SDK and python-dotenv, and calling Claude via the messages.create endpoint. The tutorial script loads an API key from a .env file, creates an Anthropic client, sends a prompt to the claude-haiku-4-5 model with a 1024-token cap, and prints the response while logging token usage.", "body_md": "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](https://heymeraki.substack.com/p/aie_10-introduction-to-ai-engineering?r=8ei6qe&utm_campaign=post&utm_medium=web), it’ll make this make more sense.\n\nIn 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.**\n\n### What we are building\n\nA 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.\n\n### What you need\n\n- A terminal\n- Python installed on your machine\n- An Anthropic API key ( [platform.claude.com](https://platform.claude.com/) , you will need to add a small credit balance as the free tier does not cover API access)\n- A code editor (VS Code is fine if you do not have a preference)\n\n### Setting up\n\nCreate 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.\n\n```\nmkdir ai-engineering\ncd ai-engineering\npython3 -m venv venv\nsource venv/bin/activate\n```\n\nYou will know it worked when you see `(venv)` at the start of your terminal line.\n\nInstall the two libraries you need:\n\n```\npip install anthropic python-dotenv\n```\n\n- `anthropic` is the official Python library for talking to Claude.\n- `python-dotenv` reads your API key from a file so you never have to hardcode it in your script.\n\nCreate a `.env` file and add your key:\n\n```\nANTHROPIC_API_KEY=your_key_here\n```\n\nCreate the script file:\n\n```\nmkdir 01\ntouch 01/first_contact.py\n```\n\nOpen `01/first_contact.py` in your editor. This is where you will build the script, piece by piece.\n\n### **Step 1: load your API key**\n\nThe 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.\n\n``` python\nfrom dotenv import load_dotenv\nimport os\n\nload_dotenv()\n```\n\n- `load_dotenv()` reads your`.env` file and makes everything inside it available to the script.\n- `import os` gives the script access to environment variables, the place where your API key lives after`load_dotenv()` runs.\n\nAfter this line runs, your API key exists in the environment and your code can access it.\n\n### **Step 2: create the client**\n\nBefore 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.\n\nIn 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.\n\n``` python\nfrom anthropic import Anthropic\n\nclient = Anthropic(api_key=os.getenv(\"ANTHROPIC_API_KEY\"))\n```\n\n- `os.getenv(\"ANTHROPIC_API_KEY\")` reads the key from the environment.\n- `Anthropic(api_key=...)` creates the client using that key.\n\n### **Step 3: make the API call**\n\nThis is the call to Claude. You are sending a message and asking for a response.\n\n```\nresponse = client.messages.create(\n    model=\"claude-haiku-4-5\",\n    max_tokens=1024,\n    messages=[\n        {\"role\": \"user\", \"content\": \"What is a large language model? Answer in two sentences.\"}\n    ]\n)\n```\n\nA few things worth noting here:\n\n- `model` specifies which Claude model to use.\n- `max_tokens` sets a ceiling on how long the response can be.\n- 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.\n\n### **Step 4: read the response**\n\nThe 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.\n\n```\ntext = response.content[0].text\ninput_tokens = response.usage.input_tokens\noutput_tokens = response.usage.output_tokens\n```\n\n- `response.content[0].text` is the model’s response as a string.\n- `response.usage` gives you the token counts, how many tokens you sent in and how many the model generated back.\n\n### Step 5: print everything\n\n```\nprint(\"Response:\")\nprint(text)\nprint()\nprint(f\"Input tokens: {input_tokens}\")\nprint(f\"Output tokens: {output_tokens}\")\nprint(f\"Total tokens: {input_tokens + output_tokens}\")\n```\n\nYour final code should look like this:\n\n``` python\nfrom dotenv import load_dotenv\nimport os\nfrom anthropic import Anthropic\n\nload_dotenv()\n\nclient = Anthropic(api_key=os.getenv(\"ANTHROPIC_API_KEY\"))\n\nresponse = client.messages.create(\n    model=\"claude-haiku-4-5\",\n    max_tokens=1024,\n    messages=[\n        {\"role\": \"user\", \"content\": \"What is a large language model? Answer in two sentences.\"}\n    ]\n)\n\ntext = response.content[0].text\ninput_tokens = response.usage.input_tokens\noutput_tokens = response.usage.output_tokens\n\nprint(\"Response:\")\nprint(text)\nprint()\nprint(f\"Input tokens: {input_tokens}\")\nprint(f\"Output tokens: {output_tokens}\")\nprint(f\"Total tokens: {input_tokens + output_tokens}\")\n```\n\n### Run it\n\n```\npython3 01/first_contact.py\n```\n\nYou should see something like this:\n\n```\nResponse:\nA large language model (LLM) is an AI system trained on vast amounts \nof text data to understand and generate human language. It uses deep \nlearning to predict and produce text by identifying patterns in the \ndata it learned from.\n\nInput tokens: 19\nOutput tokens: 51\nTotal tokens: 70\n```\n\n### What you are seeing\n\nThe 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.\n\nThe 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.\n\nNow 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!", "url": "https://wpnews.pro/news/building-your-first-llm-api-call-in-python-step-by-step", "canonical_source": "https://heymeraki.substack.com/p/aie_10-building-it", "published_at": "2026-09-15 15:05:56+00:00", "updated_at": "2026-09-15 15:21:31.682785+00:00", "lang": "en", "topics": ["large-language-models", "ai-tools", "developer-tools", "ai-products"], "entities": ["Anthropic", "Claude", "Python", "VS Code"], "alternates": {"html": "https://wpnews.pro/news/building-your-first-llm-api-call-in-python-step-by-step", "markdown": "https://wpnews.pro/news/building-your-first-llm-api-call-in-python-step-by-step.md", "text": "https://wpnews.pro/news/building-your-first-llm-api-call-in-python-step-by-step.txt", "jsonld": "https://wpnews.pro/news/building-your-first-llm-api-call-in-python-step-by-step.jsonld"}}