Day 1 - Your First OpenAI API Call and Chaining LLM Calls in Python
Week 1 · Day 1 · Lecture 8. Setup is behind you. This is the first real call to an LLM from Python — and then the first thing that starts to look agentic: feeding one model's output into the next call.
Lab file: 1_foundations/1_lab1.ipynb
1. Messages: the format OpenAI expects
Every request is a Python list of dictionaries. Each dictionary has a role and content.
messages = [{"role": "user", "content": "Tell me a fun fact"}]
role says who is speaking — user is you. content is the message itself. That is the whole structure, and it does not get more complicated later; it only gets longer.
2. Making the call
response = openai.chat.completions.create(
model="gpt-5-nano",
messages=messages
)
print(response.choices[0].message.content)
Two arguments: which model, and the messages. What comes back is a response object, and the text lives at response.choices[0].message.content.
That nesting is worth reading once, slowly. choices is a list because the API can return several completions; you almost always want the first. Then .message.content is the text itself.
Check the model name in the lab notebook and use whatever it specifies — model names change, and the notebook is kept current.
3. Chaining: the first step towards agentic AI
One call is a query. Two calls, where the first one's answer becomes the second one's input, is a chain — and that is the seed of everything in this course.
The lab does it like this:
# Call 1 - ask the model to invent a hard question
question = "Please propose a hard, challenging question to assess someone's IQ. Respond only with the question."
messages = [{"role": "user", "content": question}]
response = openai.chat.completions.create(model="gpt-5-mini", messages=messages)
question = response.choices[0].message.content # the model's output...
# Call 2 - ...becomes the next call's input
messages = [{"role": "user", "content": question}]
response = openai.chat.completions.create(model="gpt-5-mini", messages=messages)
answer = response.choices[0].message.content
Notice what happened: no human wrote the second prompt. The model did. That is the whole idea — an LLM's output driving the next step. Add a loop and some tools and you have an agent.
4. A note on Cursor
Cursor autocompletes most of this before you finish typing. Press Tab to accept. It is genuinely useful, but on your first pass it is worth typing a few lines yourself so the structure sticks.
Exercise

Now try this commercial application, as a three-call chain:
- Ask the LLM to pick a business area that might be worth exploring for an Agentic AI opportunity.
- Ask it to present a pain-point in that industry — something challenging that might be ripe for an Agentic solution.
- A third call proposes the Agentic AI solution.
This is covered properly in later labs, so do not worry if you are unsure — just give it a try.
You are done when
- You can build a
messageslist from memory. - You can call the API and pull the text out of the response.
- You have run a chain where one call's output feeds the next.
- You can explain why chaining is the first step towards an agent.
Resource links
1_foundations/1_lab1.ipynb— the lab for this lecture- OpenAI Chat Completions API reference
- OpenAI models list — check current model names
guides/06_python_foundations.ipynb— lists and dictionaries, if the message format is newguides/09_ai_apis_and_ollama.ipynb— the same call against free providers- OpenAI usage dashboard
Next
Day 2 asks the question this lecture has been circling: what actually is an agent, and how does a workflow differ from one?