1. Setup and First Success
Welcome to your journey into building AI agents with Python! By the end of this chapter, you'll have made your first successful call to a Large Language Model (LLM) and understood exactly what happened behind the scenes. This is your foundation for everything that follows.
Prerequisites
Audience & Assumptions
This book is written for Python developers who want to build AI agents but have no prior experience with LLMs or AI frameworks. We assume you're comfortable with:
- Python fundamentals: functions, classes, imports, basic data structures
- Python 3.10+: You should have Python 3.10 or higher installed on your system
- Virtual environments: creating and activating venvs with
python -m venv - Package management: installing packages with
pip - Environment variables: setting and reading environment variables in your shell
- API keys: understanding what API keys are and how to obtain them from service providers
If any of these concepts are unfamiliar, we recommend reviewing them separately before continuing. The Python documentation and tutorials on virtual environments and pip are excellent starting points.
What we DON'T assume: You don't need any background in machine learning, neural networks, transformers, or AI theory. We'll explain LLM-specific concepts as we encounter them, always connecting them to familiar programming patterns.
Model Convention
Throughout this book, we'll use GPT-5-mini as our default model for examples. Here's why:
- Widely available: OpenAI's API is accessible globally with straightforward signup
- Reasonable speed: With minimal reasoning effort, responses arrive quickly enough for iterative development
- Cost-effective: At $0.25 per million input tokens and $2.00 per million output tokens (as of 2026), it's affordable for learning and experimentation
- Sufficient capability: It handles the vast majority of practical AI agent tasks well
When you see code examples without an explicit model specified, assume we're using GPT-5-mini. In Chapter 2, we'll explore the full landscape of available models (Claude, Gemini, and other GPT variants) and discuss when you might choose alternatives based on context window size, cost, or specialized capabilities.
1.1) What is an LLM?
Before we write any code, let's establish what we're actually working with. A Large Language Model (LLM) is a neural network trained on massive amounts of text data to predict what text should come next in a sequence.
Think of it like an extremely sophisticated autocomplete system. When you type on your phone and it suggests the next word, that's a simple version of what LLMs do. But LLMs operate at a scale and sophistication that enables them to:
- Generate coherent, contextually appropriate responses to questions
- Write code, essays, emails, and other structured content
- Translate between languages
- Summarize long documents
- Extract information from unstructured text
- And much more
How LLMs Differ from Traditional Software
Traditional software follows explicit rules you program:
def calculate_discount(price, customer_type):
if customer_type == "premium":
return price * 0.8 # 20% discount
elif customer_type == "regular":
return price * 0.95 # 5% discount
else:
return priceThis function always produces the same output for the same inputs. The logic is deterministic and transparent.
LLMs work differently. Instead of explicit rules, they use patterns learned from training data to generate responses. You provide input text (called a prompt), and the model generates output text (called a completion or response).
# Conceptual example - we'll write real code soon
response = llm.generate("What's a good discount for premium customers?")
# Output might be: "Premium customers typically receive 15-25% discounts..."The LLM doesn't have a hardcoded discount percentage. It generates a response based on patterns it learned during training. This means:
- Responses can vary: The same prompt might produce slightly different responses each time
- Behavior is learned, not programmed: You guide the model with prompts rather than writing explicit logic
- Capabilities emerge from scale: The model can handle tasks it wasn't explicitly trained for
Key Terminology
Let's define terms you'll encounter constantly:
- Prompt: The input text you send to the model. Think of it as the "question" or "instruction"
- Completion/Response: The text the model generates in response to your prompt
- Token: The basic unit LLMs work with. Roughly, 1 token ≈ 4 characters or ¾ of a word. "Hello world" is about 2 tokens
- Context window: The maximum amount of text (in tokens) the model can process at once. GPT-5-mini has a 400K token context window
- Temperature: A parameter controlling randomness. Lower (0.0-0.3) = more focused and deterministic. Higher (0.7-1.0) = more creative and varied
What LLMs Can and Cannot Do
Understanding what LLMs reliably do—and what they only appear to do—is essential for building robust AI agents.
LLMs are excellent at:
- Understanding and generating natural language: They can parse intent, generate coherent responses, and handle complex phrasing
"I want a refund" → Recognizes intent: refund_request
"Summarize this document" → Produces concise summary- Following instructions in prompts: When given clear directions, they can produce structured outputs like JSON or formatted text
"Convert to JSON: John Smith, 32, lives in Boston"
→ {"name": "John Smith", "age": 32, "city": "Boston"}-
Recognizing patterns in text: Sentiment analysis, categorization, and information extraction work reliably
-
Generating code and structured content: Can write valid Python, SQL, or other formatted output when properly prompted
-
Step-by-step reasoning: When explicitly instructed to "think step-by-step," they break down problems methodically
LLM Limitations:
- Not a database: They don't retrieve facts—they generate statistically plausible text. They can confidently state incorrect information that sounds authoritative.
"When was Python 4.0 released?"
→ Might generate "Python 4.0 was released in 2023" (false, but plausible)- Not a calculator: They predict what an answer should look like rather than computing it. Simple arithmetic often works; complex math fails unpredictably.
"What's 8,247 × 6,839?" → May produce wrong result that looks reasonable-
Not deterministic: The same prompt can produce different outputs each time. This variability is controlled by the temperature parameter.
-
Not always accurate: They generate plausible-sounding text regardless of factual correctness. "Hallucinations"—detailed, confident, yet completely fabricated information—occur frequently.
The key insight: Build agents that combine LLMs (for understanding and decision-making) with traditional tools (for calculation, data retrieval, and factual operations). We'll implement this pattern starting in Chapter 13, where the LLM decides when to use a calculator rather than attempting math itself.
What You'll Learn
In this book, you'll learn to build AI agents - systems where the LLM autonomously decides which actions to take to achieve goals, rather than following predetermined logic. We'll explore this paradigm deeply in Chapter 2.
1.2) Install Dependencies
Let's set up your development environment. We'll create a clean project structure and install LangChain, the framework we'll use to build AI agents.
Verify Python Installation
First, ensure Python is installed on your system. We recommend Python 3.10 or higher (as of 2026, Python 3.13 or 3.14 are good choices).
Check your Python version:
python --version
# or
python3 --versionYou should see output like Python 3.13.x or Python 3.14.x.
If Python is not installed:
-
macOS:
- Download from python.org
- Or use Homebrew:
brew install python@3.14
-
Windows:
- Download from python.org
- Check "Add Python to PATH" during installation
-
Linux:
- Ubuntu/Debian:
sudo apt update && sudo apt install python3.14 - Fedora:
sudo dnf install python3.14
- Ubuntu/Debian:
After installation, verify again with python --version.
Note: On some systems, you may need to use python3 instead of python. Throughout this book, if python doesn't work, try python3.
Create Your Project
Open your terminal and create a new directory for your project:
mkdir agentic-ai-project
cd agentic-ai-projectCreate a virtual environment to isolate dependencies:
python -m venv venvActivate the virtual environment:
# On macOS/Linux:
source venv/bin/activate
# On Windows:
venv\Scripts\activateYou should see (venv) appear in your terminal prompt, indicating the virtual environment is active.
Install LangChain and OpenAI
We'll install LangChain's OpenAI integration, which includes everything needed to work with OpenAI's models:
pip install langchain-openaiThis installs langchain-openai along with its dependencies, including langchain-core (the core LangChain abstractions) and the OpenAI Python client. You should see output confirming the installation of multiple packages.
Verify the installation:
pip show langchain-openaiYou should see details about the installed package, including its version number and location. This confirms the installation was successful.
Get Your OpenAI API Key
To call OpenAI's models, you need an API key:
- Go to platform.openai.com
- Sign up or log in
- Navigate to API Keys in your account settings
- Click "Create new secret key"
- Copy the key (it starts with
sk-)
⚠️ Security Warning: Treat this key like a password. Never commit it to version control or share it publicly. Anyone with your key can make API calls that will be billed to your account.
Set Your API Key as an Environment Variable
The recommended way to provide your API key is through an environment variable:
# On macOS/Linux:
export OPENAI_API_KEY='sk-your-actual-key-here'
# On Windows (Command Prompt):
set OPENAI_API_KEY=sk-your-actual-key-here
# On Windows (PowerShell):
$env:OPENAI_API_KEY='sk-your-actual-key-here'Note: This setting is temporary and will be lost when you close the terminal. For a permanent solution, you can either:
- Add the export command to your shell configuration file (
.bashrc,.zshrc, etc.) - Use a
.envfile (we'll set this up in Chapter 3 for better project organization)
For now, the temporary setting is sufficient to continue.
Verify it's set:
# On macOS/Linux:
echo $OPENAI_API_KEY
# On Windows (Command Prompt):
echo %OPENAI_API_KEY%
# On Windows (PowerShell):
echo $env:OPENAI_API_KEYYou should see your API key printed. If not, repeat the export/set command and ensure there are no typos.
1.3) Your First LLM Call
Now for the exciting part - let's make your first call to an LLM. Create a file called first_call.py:
# first_call.py
from langchain_openai import ChatOpenAI
# Initialize the LLM
llm = ChatOpenAI(model="gpt-5-mini")
# Send a prompt and get a response
response = llm.invoke("What is LangChain?")
# Print the response
print(response.content)Run it:
python first_call.pyYou should see output similar to this (exact wording may vary):
LangChain is a framework designed to simplify the development of applications powered by large language models (LLMs). It provides tools and abstractions for building chains of LLM calls, integrating external data sources, managing prompts, and creating agents that can interact with various APIs and databases. LangChain makes it easier to build complex AI applications by providing reusable components and patterns.Congratulations! You just made your first LLM call. Let's break down what happened in this code.
Troubleshooting: If you see an error:
AuthenticationError: API key is invalid or not set → Check yourOPENAI_API_KEYenvironment variable (see section 1.2)RateLimitError: Requests too fast or usage limit exceeded → Wait a few seconds and retry, or check usage at platform.openai.com/usageAPIConnectionError: Network connectivity issue → Check your internet connection
Understanding the Code
Import the LLM wrapper:
from langchain_openai import ChatOpenAIChatOpenAI is LangChain's wrapper around OpenAI's chat models. It handles API authentication, request formatting, and response parsing for you.
Initialize the model:
llm = ChatOpenAI(model="gpt-5-mini")This creates an instance configured to use GPT-5-mini. Behind the scenes, LangChain reads your OPENAI_API_KEY environment variable for authentication. You could also pass the key explicitly:
llm = ChatOpenAI(model="gpt-5-mini", api_key="sk-your-key")But using environment variables is more secure and flexible.
Invoke the model:
response = llm.invoke("What is LangChain?")The invoke() method sends your prompt to OpenAI's API and waits for the complete response. This is a synchronous call - your program pauses until the response arrives.
Access the response content:
print(response.content)The response object contains several fields. The .content field holds the actual text generated by the model. We'll explore other fields in the next section.
Try Different Prompts
Modify the prompt to see how the model responds to different inputs:
# first_call.py
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-5-mini")
# Try different prompts
prompts = [
"Explain Python decorators in one sentence.",
"What's 15 * 23?",
"List three benefits of using type hints in Python.",
]
for prompt in prompts:
response = llm.invoke(prompt)
print(f"Prompt: {prompt}")
print(f"Response: {response.content}\n")The model handles different types of requests - explanations, calculations, and structured lists. You'll notice that responses can vary slightly if you run the same prompt multiple times. This is normal behavior - we'll explore why this happens and how to control it in Chapter 2.
1.4) What Just Happened? (Request → Model → Response Flow)
Let's examine exactly what happened when you called llm.invoke(). Understanding this flow is crucial for building reliable AI agents.
The Complete Request-Response Cycle
Let's trace through each step:
Step 1: Your Code Calls invoke()
response = llm.invoke("What is LangChain?")The invoke() method is your main interface to the LLM. You pass in a prompt string, and it returns a response object containing the model's answer. Behind this simple call, several steps happen automatically.
Step 2: LangChain Formats the Request
LangChain transforms your string into a structured API request. Behind the scenes, it creates a JSON payload like this:
{
"model": "gpt-5-mini",
"messages": [
{
"role": "user",
"content": "What is LangChain?"
}
],
"temperature": 1.0
}The messages array is how chat models receive input. Each message has a role (user, assistant, or system) and content (the text). We'll explore message roles in Chapter 4.
Step 3: API Call to OpenAI
LangChain sends an HTTPS POST request to OpenAI's API endpoint:
POST https://api.openai.com/v1/chat/completions
Authorization: Bearer sk-your-api-key
Content-Type: application/json
{request payload}Your API key authenticates the request. OpenAI's servers receive the request and route it to the specified model.
Step 4: Model Processes the Prompt
GPT-5-mini receives your prompt and generates a response token by token. The model:
- Converts your text into tokens (numerical representations)
- Processes tokens through its neural network layers
- Predicts the most likely next token
- Repeats until it generates a complete response or hits a stopping condition
This happens on OpenAI's servers - your code just waits for the result.
Step 5: API Returns the Response
OpenAI's API sends back a JSON response:
{
"id": "chatcmpl-8x7y9z",
"object": "chat.completion",
"created": 1704067200,
"model": "gpt-5-mini",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "LangChain is a framework designed to simplify..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 12,
"completion_tokens": 58,
"total_tokens": 70
}
}Key fields:
- message.content: The generated text
- usage: Token counts for billing and monitoring
- finish_reason: Why generation stopped ("stop" = natural completion, "length" = hit token limit)
Step 6: LangChain Parses the Response
LangChain converts the JSON into a Python object you can work with:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-5-mini")
response = llm.invoke("What is LangChain?")
# Explore the response object
print(f"Content: {response.content}")
print(f"Type: {type(response)}")
print(f"Response metadata: {response.response_metadata}")Output:
Content: LangChain is a framework designed to simplify...
Type: <class 'langchain_core.messages.ai.AIMessage'>
Response metadata: {'token_usage': {'completion_tokens': 58, 'prompt_tokens': 12, 'total_tokens': 70}, 'model_name': 'gpt-5-mini', 'finish_reason': 'stop'}The response is an AIMessage object with several useful attributes:
- content: The generated text (what you usually want)
- response_metadata: Token usage, model name, finish reason
- id: Unique identifier for this response
- usage_metadata: Detailed token breakdown
Understanding Token Usage
Before looking at token counts, a quick note: tokens are the basic units LLMs process. In English, text typically uses slightly more than 1 token per word (e.g., "explain quantum computing" = 3 words, 4-5 tokens), but non-English languages like Korean or Chinese require significantly more tokens to represent the same text. We'll explore tokens in more detail in Chapter 2.
Let's examine token consumption more closely:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-5-mini")
response = llm.invoke("Explain quantum computing in simple terms.")
usage = response.response_metadata['token_usage']
print(f"Input tokens: {usage['prompt_tokens']}")
print(f"Output tokens: {usage['completion_tokens']}")
print(f"Total tokens: {usage['total_tokens']}")Output:
Input tokens: 11
Output tokens: 95
Total tokens: 106Note: prompt_tokens = input tokens (your prompt), completion_tokens = output tokens (model's response), total_tokens = sum of both.
Token consumption varies based on:
- Prompt length: Longer prompts use more input tokens
- Response detail: Detailed responses generate more output tokens
- Language complexity: Technical terms and code may tokenize differently
For example, a short prompt like "What's 2+2?" might use only 5-6 input tokens and 8-10 output tokens, while "Write a detailed essay about the history of Python programming language" could use 15-20 input tokens and 500+ output tokens.
Cost calculation for the example above:
At GPT-5-mini's pricing ($0.25 per million input tokens, $2.00 per million output tokens):
- Input: 11 tokens × $0.25 / 1,000,000 = $0.00000275
- Output: 95 tokens × $2.00 / 1,000,000 = $0.00019
- Total: ~$0.0002 (two hundredths of a cent)
You pay for both input and output tokens, but output tokens cost more (8× in this case).
What You've Learned
You now understand the complete lifecycle of an LLM call:
- Your code provides a prompt string
- LangChain formats it into an API request with authentication
- OpenAI's API routes the request to the model
- The model generates a response token by token
- The API returns structured JSON with the response and metadata
- LangChain parses it into a Python object
- Your code accesses the content and metadata
You've also learned:
- How to inspect response objects and extract metadata
- How token usage affects costs
This foundation prepares you for Chapter 2, where we'll explore how LLMs actually work under the hood, compare different models, and learn prompt engineering techniques to get better results.