Build a Study Buddy with Claude API
Connect Python to Claude's API to build a multi-turn AI study chatbot.
Introduction
30 Second Summary
Every AI-powered app you use, from customer support bots to code assistants, connects to a large language model through an API. Learning how this connection works is the foundational skill behind building any AI feature.
In this project, you will build a command-line Study Buddy powered by Claude's API. You'll send prompts, handle multi-turn conversations, and stream responses in real-time.
What You'll Build
A Python script that makes API calls to Claude's Messages API to create an interactive study buddy chatbot with streaming responses.
By the end of this project, you'll have:
- A working Python app that sends prompts to Claude and receives intelligent LLM responses.
- A multi-turn chatbot that maintains conversation history and uses a custom system prompt to shape Claude's personality.
- A streaming response handler that displays text as it generates, token by token.
- Secret Mission: Add conversation saving and loading so your study sessions persist between runs.
Are there any prerequisites?
None. This guide includes full setup instructions for Python, VS Code, and the Anthropic SDK. New Anthropic accounts receive free credits, so you can complete this project without paying.
Set Up Your Development Environment
Before you can build your Study Buddy chatbot, you need the right tools installed on your machine. Python is the language you'll write your app in, and the Anthropic SDK is the library that connects your code to Claude's brain.
In this step, you'll install Python, set up VS Code as your editor, and create an isolated project folder with everything your app needs.
In this step, get ready to:
- Install Python 3.9 or newer.
- Set up VS Code with a new project folder.
- Create a virtual environment and install the Anthropic SDK.
Check your Python installation
The Anthropic SDK requires Python 3.9 or newer. Let's confirm you have the right version installed.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Terminal (macOS) or PowerShell (Windows) and press Enter to open it.
Check your Python version by running this command:
macOS
python3 --version
Windows
python --version
✔️ I see version 3.9 or higher
You're all set. Your Python installation meets the requirements for this project.
ⓧ I see an older version
You have Python installed, but it's too old for the Anthropic SDK. Download the latest version from the official Python website.
- Go to python.org/downloads and download the latest version.
- Run the installer and follow the prompts.
- On Windows, make sure to check Add python.exe to PATH during installation.
- Close and reopen your terminal, then run the version check command again to confirm.
ⓧ Command not found
Python isn't installed on your machine yet. Let's install it now.
- Go to python.org/downloads and download the latest version for your operating system.
- Run the installer and follow the prompts.
- On Windows, make sure to check Add python.exe to PATH during installation.
- Close and reopen your terminal, then run the version check command again to confirm you see 3.9 or higher.
Set up VS Code and your project folder
VS Code is the code editor you'll use to write and run your Study Buddy app. You'll also create a dedicated folder to keep your project files organized.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Visual Studio Code and press Enter to open it.
✔️ I see VS Code open
VS Code is ready to go.
ⓧ I don't have VS Code installed
Download VS Code from the official website.
- Go to code.visualstudio.com and download the installer for your operating system.
- Run the installer and follow the prompts.
- Once installed, open VS Code using the search bar instructions above.
Now open the integrated terminal inside VS Code.
- Press Ctrl+` (Windows) or Cmd+` (macOS) to toggle the terminal panel.
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir study-buddy
cd study-buddy
- Confirm the folder was created by running:
pwd
You should see a path ending in study-buddy in your terminal output.
Now open this folder in VS Code so the editor knows where your project lives.
- In VS Code, click File in the top menu bar.
- Click Open Folder.
- Navigate to your Desktop and select the study-buddy folder, then click Open.
You should see study-buddy in the Explorer sidebar on the left. Your integrated terminal also now opens inside this folder by default.
Don't see the folder in the sidebar?
Make sure you selected the study-buddy folder itself, not the Desktop. The folder name should appear at the top of the Explorer sidebar.
If your terminal is no longer in the right directory, close it with Ctrl+` (Windows) or Cmd+` (macOS) and reopen it. It should now open inside study-buddy.
help me open a project folder in VS Code
Create a virtual environment and install the Anthropic SDK
A virtual environment is an isolated space for your project's packages. It keeps this project's dependencies separate from other Python projects on your machine.
- Make sure your terminal is open inside the study-buddy folder (press Ctrl+` or Cmd+` if you don't see it).
- Create your virtual environment by running this command:
macOS
python3 -m venv venv
Windows
python -m venv venv
What does this command do?
python3 -m venv venv tells Python to create a virtual environment in a folder called venv inside your project. This folder stores a private copy of Python and any packages you install.
- Activate the virtual environment by running:
macOS
source venv/bin/activate
Windows
venv\Scripts\activate
You should see (venv) appear at the beginning of your terminal prompt. This confirms the virtual environment is active.
Don't see (venv) in your prompt?
On Windows, you may see a security error about running scripts. Run Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned in PowerShell, then try the activate command again.
On macOS, make sure you typed source before the path. Without it, the command won't modify your current terminal session.
help me activate my Python virtual environment
- Install the Anthropic SDK by running:
pip install anthropic
What does this install?
The anthropic package is Anthropic's official Python SDK. It gives you pre-built functions for sending messages to Claude, handling streaming responses, and managing authentication.
You should see output showing packages being downloaded and installed, ending with a success message.
Seeing a permission error or install failure?
Make sure (venv) appears in your prompt before running pip install. If you see a permission error, it usually means the virtual environment is not active.
If you see a message about pip not being found, try pip3 install anthropic instead.
help me install the anthropic package with pip
Your development environment is fully set up. Next up, you'll grab your API key from Anthropic and make your first call to Claude.
Get Your API Key and Make Your First Call
Your development environment is ready. Now it's time to connect your Python app to Claude's brain.
Every AI-powered application talks to a model through an API. To authenticate your requests, you need an API key. In this step, you'll create your Anthropic account, grab your key, and write a Python script that sends a message to Claude and prints the response.
In this step, get ready to:
- Create your Anthropic account and generate an API key.
- Set your API key as an environment variable.
- Write and run your first script that talks to Claude.
Create your Anthropic account and get an API key
Anthropic provides free credits for new accounts, so you can complete this project at no cost.
- Open your browser and go to console.anthropic.com.
- Click Sign Up and create a free account using your email or Google account.
- Once logged in, click API Keys in the left sidebar.
- Click Create Key.
- Give your key a name (like study-buddy) and click Create Key.
- Copy your API key immediately and save it somewhere safe. You will not be able to see it again after closing this dialog.
Keep your API key secret
Never share your API key publicly or commit it to version control. Treat it like a password. Anyone with your key can make API calls billed to your account.
Set the ANTHROPIC_API_KEY environment variable
The Anthropic SDK automatically reads the ANTHROPIC_API_KEY environment variable when you create a client. This means you can keep the key out of your code entirely.
- Set the environment variable in your terminal by running this command (replace your-api-key-here with the key you just copied):
macOS
export ANTHROPIC_API_KEY='your-api-key-here'
Windows
$env:ANTHROPIC_API_KEY="your-api-key-here"
Why an environment variable?
Storing your key in an environment variable keeps it out of your source code. If you ever share your project or push it to GitHub, the key stays safe on your machine instead of being exposed in your files.
Key only lasts for this terminal session
The export (or $env:) command sets the variable for the current terminal session only. If you close your terminal and open a new one, you'll need to run the command again.
How do I make this permanent?
Write your first script
Time to write some Python. You'll create a script that sends a single message to Claude and prints the response.
- In VS Code, create a new file called study_buddy.py in your project folder.
- Add the following code to study_buddy.py:
import os
from anthropic import Anthropic
# Create a client - reads ANTHROPIC_API_KEY from the environment automatically
client = Anthropic()
# Send a single message to Claude and get a response
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=1024,
messages=[
{"role": "user", "content": "Hello! Can you help me study for an exam?"}
]
)
# Print Claude's response text
print(response.content[0].text)
What does this code do?
This script does three things in sequence.
- Anthropic() creates a client that handles authentication. It automatically finds your ANTHROPIC_API_KEY environment variable.
- client.messages.create() sends a request to Claude's Messages API. You pass the model name, a token limit, and a list of messages.
- response.content[0].text extracts the text from Claude's reply. The response is structured as a list of content blocks, and you grab the first one.
- Save study_buddy.py.
- Run the script in your terminal by running:
python study_buddy.py
You should see Claude respond with a helpful message about studying for exams. The exact wording will vary each time you run it.
Seeing an authentication error?
- Make sure you set the ANTHROPIC_API_KEY environment variable in the same terminal session where you're running the script.
- Check that your API key is correct. Go back to the Anthropic Console and verify it matches what you pasted.
- On macOS, if you used python and it didn't work, try python3 instead.
Why is my Anthropic API key not working?
✔️ Awesome, I've got everything!
Great. Double check you've saved your file.
ⓧ I'd like to double check the full code
import os
from anthropic import Anthropic
client = Anthropic()
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=1024,
messages=[
{"role": "user", "content": "Hello! Can you help me study for an exam?"}
]
)
print(response.content[0].text)
You just made your first API call to Claude. Your script can now send any prompt and get an intelligent response back. Next up, you'll turn this one-shot script into a full conversation with memory.
Add a System Prompt and Multi-Turn Conversations
Your script can talk to Claude. Right now though, every conversation starts from scratch and Claude has no idea who it's supposed to be.
In this step, you'll give Claude a personality with a system prompt and teach your app to remember what's been said. The Messages API is stateless, so your code needs to manage the conversation history itself.
In this step, get ready to:
- Add a system prompt that shapes Claude into a study buddy tutor.
- Build a conversation history list that accumulates messages.
- Create an interactive loop for multi-turn conversations with context memory.
Add a system prompt and conversation history
A system prompt is a special instruction that tells Claude how to behave across an entire conversation. Instead of including this in your messages list, the Anthropic SDK accepts it as a separate system parameter.
You'll also need a list to accumulate messages, since the API doesn't remember previous turns on its own.
- In VS Code, open study_buddy.py and replace all of the existing code with the following:
import os
from anthropic import Anthropic
def main():
# Create the Anthropic client (reads ANTHROPIC_API_KEY from environment)
client = Anthropic()
# System prompt shapes Claude's personality for the entire conversation
system_prompt = (
"You are a friendly and knowledgeable study buddy. "
"You help students understand concepts by explaining things clearly, "
"asking guiding questions, and providing examples. "
"Keep your responses concise but thorough. "
"If a student seems confused, try explaining from a different angle. "
"Encourage them and celebrate their progress."
)
# This list will store the full conversation so Claude remembers context
conversation_history = []
# Welcome banner
print("=" * 50)
print(" Welcome to Study Buddy!")
print(" Powered by Claude AI")
print("=" * 50)
print("\nI'm your AI study buddy. Ask me anything!")
print("Type 'quit' or 'exit' to end the session.\n")
What does this code do?
You've restructured the script into a main() function, which is a standard Python pattern for runnable scripts.
- system_prompt defines Claude's personality. It's a plain string passed separately from the messages list. Claude reads this before every response.
- conversation_history starts empty. You'll append each user message and Claude's replies here so the API receives the full context on every call.
Why is the Messages API stateless?
Unlike a chat window that "remembers" what you said, the API treats every request as independent. Your code is responsible for sending the full conversation each time.
This gives you complete control over what Claude sees. You could summarize old messages to save tokens, or inject context from other sources.
You won't see a change yet. The next chunk adds the conversation loop that uses this setup.
Create the interactive conversation loop
The loop reads user input, sends the full conversation history to Claude, and appends both the user message and Claude's reply for the next turn.
- In study_buddy.py, add the following code directly below the welcome banner prints, still inside the main() function:
while True:
user_input = input("You: ").strip()
# Skip empty inputs
if not user_input:
continue
# Let the user exit gracefully
if user_input.lower() in ("quit", "exit"):
print("\nGoodbye! Happy studying!")
break
# Add the user's message to conversation history
conversation_history.append({
"role": "user",
"content": user_input
})
# Send the full conversation to Claude with the system prompt
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=1024,
system=system_prompt,
messages=conversation_history,
)
# Extract and display Claude's response
assistant_message = response.content[0].text
print(f"\nStudy Buddy: {assistant_message}\n")
# Add Claude's response to history so it remembers next turn
conversation_history.append({
"role": "assistant",
"content": assistant_message
})
if __name__ == "__main__":
main()
What does this code do?
- while True creates an infinite loop that keeps the conversation going until the user types quit or exit.
- Each user message gets appended to conversation_history as a dict with role: "user". Claude's reply gets appended with role: "assistant".
- The system parameter passes your system prompt separately from the messages list. Claude reads it as a persistent instruction.
- if __name__ == "__main__" ensures main() only runs when you execute the script directly.
- Save study_buddy.py.
- Run your script by executing the following command in your terminal:
python study_buddy.py
- You should see the welcome banner printed, then a You: prompt waiting for input.
- Type a question like What is photosynthesis? and press Enter.
- Ask a follow-up like Can you give me an example? to confirm Claude remembers the topic.
- Type quit to exit.
Not getting a response?
- Make sure your ANTHROPIC_API_KEY environment variable is still set in the same terminal session. If you opened a new terminal, you need to export it again.
- Check your indentation. The while True loop must be indented inside main(). Python is sensitive to whitespace.
- If you see NameError: name 'main' is not defined, make sure the if __name__ block is at the bottom of the file with no indentation.
Help me debug my Study Buddy script
Double check your code
✔️ Awesome, I've got everything!
Great. Make sure you've saved study_buddy.py before moving on.
ⓧ I'd like to double check the full code
import os
from anthropic import Anthropic
def main():
client = Anthropic()
system_prompt = (
"You are a friendly and knowledgeable study buddy. "
"You help students understand concepts by explaining things clearly, "
"asking guiding questions, and providing examples. "
"Keep your responses concise but thorough. "
"If a student seems confused, try explaining from a different angle. "
"Encourage them and celebrate their progress."
)
conversation_history = []
print("=" * 50)
print(" Welcome to Study Buddy!")
print(" Powered by Claude AI")
print("=" * 50)
print("\nI'm your AI study buddy. Ask me anything!")
print("Type 'quit' or 'exit' to end the session.\n")
while True:
user_input = input("You: ").strip()
if not user_input:
continue
if user_input.lower() in ("quit", "exit"):
print("\nGoodbye! Happy studying!")
break
conversation_history.append({
"role": "user",
"content": user_input
})
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=1024,
system=system_prompt,
messages=conversation_history,
)
assistant_message = response.content[0].text
print(f"\nStudy Buddy: {assistant_message}\n")
conversation_history.append({
"role": "assistant",
"content": assistant_message
})
if __name__ == "__main__":
main()
Your Study Buddy now has a personality and remembers your conversation. Next up, you'll make the responses feel more natural by streaming them token by token instead of waiting for the full reply.
Add Streaming Responses
Your Study Buddy can hold full conversations and remember context. There's one thing that feels off though. Claude composes the entire response behind the scenes before displaying anything.
For long explanations, that means staring at a blank screen. In this step, you'll switch to streaming responses so Claude's words appear token by token as they're generated.
In this step, get ready to:
- Replace the synchronous API call with a streaming version.
- Handle stream events to print tokens in real-time.
- Verify that clean exit still works with streaming.
Replace the synchronous call with streaming
The Messages API supports two modes. The synchronous mode you used in Step 3 waits for the full response before returning. The streaming mode sends text back in small chunks as Claude generates them.
- In study_buddy.py, find this block of code inside your while True loop:
response = client.messages.create(
model="claude-haiku-4-5",
max_tokens=1024,
system=system_prompt,
messages=conversation_history,
)
assistant_message = response.content[0].text
print(f"\nStudy Buddy: {assistant_message}\n")
conversation_history.append({
"role": "assistant",
"content": assistant_message
})
- Delete this entire block (from response = client.messages.create( down through the conversation_history.append() call) and replace it with this streaming version:
# Print the label before streaming begins
print("\nStudy Buddy: ", end="", flush=True)
# Stream Claude's response token by token
with client.messages.stream(
model="claude-haiku-4-5",
max_tokens=1024,
system=system_prompt,
messages=conversation_history,
) as stream:
full_response = ""
# Print each text chunk as it arrives
for text in stream.text_stream:
print(text, end="", flush=True)
full_response += text
print("\n")
# Store the complete response in conversation history
conversation_history.append({
"role": "assistant",
"content": full_response
})
What does this code do?
print("\nStudy Buddy: ", end="", flush=True) prints the response label without a newline, so Claude's streamed text appears on the same line. The flush=True forces the text to display immediately instead of waiting in a buffer.
client.messages.stream() opens a streaming connection to Claude. Instead of waiting for the full response, it yields text chunks as Claude generates them. The with block ensures the connection is properly closed when streaming finishes.
stream.text_stream is an iterator that delivers each text chunk. You print each one immediately and accumulate them into full_response so the full message can be stored in conversation history after streaming completes.
Why streaming instead of waiting?
The synchronous messages.create() call blocks until Claude finishes generating. For a short answer that takes 2 seconds, the learner stares at nothing for 2 seconds then sees everything at once.
Streaming starts displaying text within milliseconds. This is the same technique ChatGPT and Claude's web interface use to feel responsive. It makes conversations feel natural rather than transactional.
- Save study_buddy.py.
- Run your script by running:
python study_buddy.py
- Ask a question like What is photosynthesis? and watch the response. You should see Claude's words appear one by one in real-time instead of all at once.
- Type quit to verify clean exit. You should see Goodbye! Happy studying! and the program ends.
Not seeing token-by-token output?
If the response still appears all at once, check that you're using client.messages.stream() and not client.messages.create(). Also confirm both print() calls inside the loop have end="" and flush=True.
If you see an error about stream not having text_stream, make sure your with statement ends with as stream: and uses client.messages.stream() (not client.messages.create()).
help me debug my streaming Study Buddy
✔️ Awesome, I've got everything!
Great. Double check you've saved your file before moving on.
ⓧ I'd like to double check the full code
import os
from anthropic import Anthropic
def main():
client = Anthropic()
system_prompt = (
"You are a friendly and knowledgeable study buddy. "
"You help students understand concepts by explaining things clearly, "
"asking guiding questions, and providing examples. "
"Keep your responses concise but thorough. "
"If a student seems confused, try explaining from a different angle. "
"Encourage them and celebrate their progress."
)
conversation_history = []
print("=" * 50)
print(" Welcome to Study Buddy!")
print(" Powered by Claude AI")
print("=" * 50)
print("\nI'm your AI study buddy. Ask me anything!")
print("Type 'quit' or 'exit' to end the session.\n")
while True:
user_input = input("You: ").strip()
if not user_input:
continue
if user_input.lower() in ("quit", "exit"):
print("\nGoodbye! Happy studying!")
break
conversation_history.append({
"role": "user",
"content": user_input
})
print("\nStudy Buddy: ", end="", flush=True)
with client.messages.stream(
model="claude-haiku-4-5",
max_tokens=1024,
system=system_prompt,
messages=conversation_history,
) as stream:
full_response = ""
for text in stream.text_stream:
print(text, end="", flush=True)
full_response += text
print("\n")
conversation_history.append({
"role": "assistant",
"content": full_response
})
if __name__ == "__main__":
main()
Secret mission
Save and Load Conversations
Your study sessions disappear every time you close the terminal. What if you could pick up exactly where you left off? Build a persistence layer that saves conversations to JSON files and lets you load previous sessions on demand.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs locally and the Anthropic API only charges when you make calls, so there are no ongoing costs from leaving resources in place.
Resources you used:
- Project folder with study_buddy.py and Python virtual environment.
- ANTHROPIC_API_KEY environment variable.
- Anthropic API key (stored in the Anthropic Console).
Keep everything running
No action needed. Choose this if you plan to keep experimenting with your Study Buddy or want to build more projects with the Anthropic API.
- Your project folder stays on your Desktop.
- Your API key remains active for future use.
- Your environment variable persists until you close the terminal session (or permanently if you added it to your shell profile).
Pause - I'll come back to this later
Remove the environment variable from your current session to keep your key out of active memory. Your project files and API key stay intact for when you return.
- Unset the environment variable in your terminal by running:
macOS
unset ANTHROPIC_API_KEY
Windows
Remove-Item Env:ANTHROPIC_API_KEY
- If you added the export line to your shell profile (like .zshrc or .bashrc), remove that line as well.
- When you come back, reactivate your virtual environment and set the environment variable again.
Delete - I don't want to use this again
Remove all project resources and revoke your API key so nothing remains.
- Unset the environment variable:
macOS
unset ANTHROPIC_API_KEY
Windows
Remove-Item Env:ANTHROPIC_API_KEY
- If you added the export line to your shell profile (like .zshrc or .bashrc), remove that line.
- Delete the project folder by running:
macOS
cd ~/Desktop
rm -rf study-buddy
Windows
cd ~\Desktop
Remove-Item -Recurse -Force study-buddy
- Delete your API key from the Anthropic Console. Go to console.anthropic.com, navigate to your API keys in Account Settings, and disable or delete the key you created for this project.
That's a Wrap!
That's a Wrap!
Nice work! You just built an AI-powered study buddy from scratch using Python and the Claude API.
You've learned how to:
- Connected a Python app to Claude's Messages API using the official Anthropic SDK and authenticated with an API key.
- Built multi-turn conversations with full context memory by managing a conversation history list.
- Added streaming responses so Claude's replies appear in real-time, token by token.
- Secret Mission: Made conversations persistent with JSON file saving and loading so study sessions survive between runs.
Ready to quiz yourself?