Using a real model
Everything so far ran on a stand-in you wrote in lesson 14. Swapping in a real model is two lines, and nothing else in any program you have written changes.
Install the provider you want
Each provider is a separate small package. Pick one.
pip install "langchain[anthropic]"
pip install "langchain[openai]"
pip install "langchain[google-genai]"
pip install "langchain[groq]"Put the key in the environment
Never in the file. An environment variable keeps it out of your code and out of your repository.
export ANTHROPIC_API_KEY=your-key-hereThe two lines
One import and one call. init_chat_model takes a single string and gives you back a chat model, in place of the two lines that made a PretendModel.
from langchain.chat_models import init_chat_model
model = init_chat_model("anthropic:claude-sonnet-5")The string is the provider, a colon, and the model name. Change it and you change providers, and nothing else in your graph notices.
| Provider | String | Free tier |
|---|---|---|
| Anthropic | anthropic:claude-sonnet-5 | No |
| OpenAI | openai:gpt-5 | No |
google_genai:gemini-2.5-flash | Yes, generous | |
| Groq | groq:llama-3.3-70b-versatile | Yes, and fast |
If you want to try this without paying anything, Google and Groq both give away enough to finish this course several times over.
That is genuinely all
Take lesson 18, change the two lines that build the model, and it is a real agent. The tool, the nodes, the conditional edge, the backwards edge and the checkpointer are all untouched.
from langchain.chat_models import init_chat_model
model = init_chat_model("anthropic:claude-sonnet-5").bind_tools([lookup_order])What changes is the behaviour, not the code. A real model reads the docstring you wrote in lesson 16 and decides for itself, so it will use tools you did not expect and skip ones you did. That is when the docstring advice from that lesson starts to matter.
The thing that only works now
Structured output, mentioned at the end of lesson 19, needs a model that really understands tools. With a real one it is a single call.
from pydantic import BaseModel
class Triage(BaseModel):
category: str
urgent: bool
sorted_ticket = model.with_structured_output(Triage).invoke(messages)
print(sorted_ticket.category, sorted_ticket.urgent)You get back an object with the fields you asked for, already checked, rather than a paragraph you have to pick apart.
Two things that will surprise you
It costs money per message. The whole conversation goes on every turn, so a long thread costs more each time. Lesson 21 is the answer, and it stops being theoretical here.
It is not deterministic. The same question can produce a different answer twice. Your graph is still exactly as predictable as before, but the node that calls the model is not, which is what makes approvals from lesson 24 worth having.
- Get a free key from Groq or Google and run lesson 18 against it.
- Ask it something with no order id and see how a real model handles it.
- Change the provider string to a second provider and confirm nothing else needs touching.
Every expert started right here.