LangChain Tutorial: Build Your First LLM App
This LangChain tutorial builds a small meeting-notes assistant in four steps, using a free local model: a chat model, a prompt chain, structured output validated by Pydantic, and an agent with one tool. Everything ran, and the output also shows the mistakes a small model makes and how to catch them.
GloryTecks Team
Training & Placement Faculty
Last updated: 3 October 2026
LangChain is a Python library for building applications on top of language models. Its value is in the parts it gives you: a common interface to many model providers, prompt templates, chains, structured output and agents. This tutorial uses each of them once, to build a small assistant that turns meeting notes into a summary and a list of action items.
It uses a local model through Ollama, so it runs on a laptop with no account or API key. The same code works with a hosted model by changing one line.
Set up
LangChain needs Python 3.10 or later and installs with pip, with each model provider in its own package (LangChain: install). For a local model, the Ollama integration is langchain-ollama, and the model name must match one you have downloaded (LangChain: ChatOllama).
pip install -U langchain langchain-ollama
ollama pull llama3.2For running models locally, see the Ollama tutorial.
The application
The script has four parts, each adding one LangChain idea.
from datetime import date
from langchain.agents import create_agent
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama import ChatOllama
from pydantic import BaseModel, Field
# 1. A chat model. Swapping providers means changing this line, not the rest of the app.
model = ChatOllama(model="llama3.2", temperature=0, seed=42)
reply = model.invoke("In one sentence, what is a meeting action item?")
print("1. invoke")
print(reply.content)
print(reply.usage_metadata)
# 2. A prompt template piped into the model and a parser: a chain
prompt = ChatPromptTemplate.from_messages([
("system", "You summarise meeting notes for people who missed the meeting. Reply in at most {words} words."),
("human", "{notes}"),
])
summarise = prompt | model | StrOutputParser()
NOTES = [
"Anil will update the pricing page by Friday 9 October. Meera owns the newsletter draft, due 12 October. "
"Nobody has picked up the broken sign-up form yet.",
"Budget review moved to next week. Joseph to send the revised forecast to finance by 14 October.",
"Fatima demoed the new search. Team agreed to ship it after Anil fixes the two layout bugs, by 16 October.",
]
print("\n2. a chain")
print(summarise.invoke({"notes": NOTES[0], "words": 25}))
# 3. Structured output: the model's reply is parsed and validated into Python objects
class ActionItem(BaseModel):
owner: str = Field(description="Person responsible, or 'unassigned'")
task: str = Field(description="What has to be done")
due: str | None = Field(description="Due date as written in the notes, or null")
class ActionItems(BaseModel):
items: list[ActionItem]
extract = prompt.partial(words="100") | model.with_structured_output(ActionItems)
print("\n3. structured output for three sets of notes, as one batch")
for notes, result in zip(NOTES, extract.batch([{"notes": n} for n in NOTES], config={"max_concurrency": 1})):
print("-", notes[:60] + "...")
for item in result.items:
print(f" {item.owner:<11} | {item.task:<46} | {item.due}")
# 4. An agent: the model decides when to call a Python function
def days_between(start: str, end: str) -> int:
"""Count the days from start to end. Dates are in YYYY-MM-DD format."""
return (date.fromisoformat(end) - date.fromisoformat(start)).days
agent = create_agent(model, tools=[days_between],
system_prompt="Today is 2026-10-03. Use the tools for any date arithmetic.")
state = agent.invoke({"messages": [{"role": "user", "content": "How many days are left until 16 October 2026?"}]})
print("\n4. an agent with one tool")
for message in state["messages"]:
calls = getattr(message, "tool_calls", None)
text = f"calls {calls[0]['name']}({calls[0]['args']})" if calls else " ".join(str(message.content).split())
print(f"{message.type:>6}: {text}")1. invoke
A meeting action item is a specific task or responsibility assigned to an individual or group at the end of a meeting, with clear deadlines and expectations for completion.
{'input_tokens': 36, 'output_tokens': 32, 'total_tokens': 68}
2. a chain
Key action items: Anil to update pricing page by Oct 6, Meera to finalize newsletter draft by Oct 12, and fix broken sign-up form.
3. structured output for three sets of notes, as one batch
- Anil will update the pricing page by Friday 9 October. Meera...
Anil | Update pricing page | Friday, 9 October
Meera | Finalize newsletter draft | 12 October
Unknown | Fix broken sign-up form | N/A
- Budget review moved to next week. Joseph to send the revised...
Joseph | Send revised forecast to finance by 14 October | 14/10/2023
Finance | Review budget | Next week
- Fatima demoed the new search. Team agreed to ship it after A...
Anil | Fix two layout bugs in the new search feature | 16 October
Fatima | Demo the new search feature | None
4. an agent with one tool
human: How many days are left until 16 October 2026?
ai: calls days_between({'end': '2026-10-16', 'start': '2026-10-01'})
tool: 15
ai: There are 15 days left until October 16, 2026.What each part does
1. A chat model. ChatOllama wraps the local model. invoke sends one message and returns a message object, with token counts in usage_metadata. To use a hosted provider instead, replace this line, for example with init_chat_model and a provider's model name. LangChain's models guide describes invoke, stream for token-by-token output, and batch for many inputs (LangChain: models).
2. A chain. ChatPromptTemplate holds the instructions with placeholders. The pipe operator joins the template, the model and a parser into one object, so summarise.invoke({...}) fills the template, calls the model and returns plain text. Chains keep each step replaceable: you can change the model, edit the template or add a step that cleans the input without touching the rest, and a chain offers the same invoke, batch and stream methods as a single model.
3. Structured output. with_structured_output takes a Pydantic class and returns validated Python objects instead of text. prompt.partial fixes one placeholder, and batch runs three sets of notes. The models guide notes that batch runs calls in parallel on the client, and that max_concurrency limits how many run at once. A local model on a laptop handles one at a time well.
4. An agent. create_agent wraps the model in a loop with tools. Here it has one Python function, and the docstring tells the model what the function does. The model decided to call it, LangChain ran it, and the model wrote the answer from the result (LangChain: overview). Underneath, LangChain's agents run on LangGraph, which you can use directly when a flow needs persistence, branching or a person's approval between steps.
The code worked. Check the answers
Every part ran as designed. Several answers are still wrong, and they are the most useful part of the output.
- The summary changed a fact. The notes say Anil will update the pricing page "by Friday 9 October". The summary says "by Oct 6".
- The schema was followed, but not its meaning. The description asked for "unassigned" and a missing date as null. The model wrote "Unknown", "N/A" and the word "None".
- It invented details. The forecast's due date became "14/10/2023", a year that appears nowhere in the notes. "Budget review moved to next week" became an action for Finance, and Fatima's finished demo became a task.
- The agent ignored a stated fact. The system prompt says today is 3 October 2026. The model called the tool with 1 October as the start date, so the answer was 15 days instead of 13.
A larger model makes fewer of these mistakes, but it still makes them, so the remedies belong in the application:
- Use precise types. A
datefield instead of a string rejects "14/10/2023" and "N/A" at validation time. - Use allowed values. If owners must be meeting attendees, pass the list and check against it.
- Do not ask the model for facts your code knows. The date tool should read today's date itself. The model should not be asked to supply it.
- Check summaries against the source. Dates, numbers and names are easy to compare automatically.
- Keep a small evaluation set of notes with the correct action items, and run it whenever the prompt or model changes. See evaluating LLM outputs.
Where to go next
- Retrieval: answer questions over your own documents. See RAG architecture explained.
- Tools: design functions the model can call safely. See function calling and tool use.
- Agents: how the loop behind
create_agentworks, and how it fails. See AI agents explained. - Choosing a framework: see LlamaIndex vs LangChain.
Common mistakes
- Following an old tutorial. LangChain's API has changed across major versions; check examples against the current documentation.
- Trusting structured output because it parsed. Valid JSON can still hold wrong values.
- String fields for dates and numbers.
- Letting the model supply facts your code already knows.
- Running large batches against a local model with unlimited concurrency.
- No evaluation set, so model or prompt changes are judged by eye.
What is LangChain used for?
Can I use LangChain without an OpenAI API key?
What is a chain in LangChain?
How do I get JSON or structured data from an LLM in LangChain?
LangChain is one of the frameworks covered in the Gen AI Frameworks and Tools module of the Generative AI course.
Sources
- Install LangChain (LangChain documentation) — LangChain
- ChatOllama integration (LangChain documentation) — LangChain
- Models (LangChain documentation) — LangChain
- LangChain overview (LangChain documentation) — LangChain
GloryTecks Team
Training & Placement Faculty
The GloryTecks faculty team mentors learners across Data Science, AI and Data Engineering, with a focus on real-time projects and placement readiness in Hyderabad.
Want to master Generative AI?
Join GloryTecks’ expert-led Generative AI training in Hyderabad with real-time projects and 100% placement support.
LangGraph Tutorial: Building Stateful AI Agents
NextRAG Architecture Explained: Retrieval-Augmented Generation
Related articles
LangGraph Tutorial: Building Stateful AI Agents
Build a small support-ticket agent with LangGraph, using only plain Python and no API key: typed state and reducers, conditional edges, a retry loop, checkpoints with thread IDs, and a human approval step with interrupt. Every output shown was produced by running the code.
Ollama Tutorial: Run LLMs Locally on Your Machine
Ollama runs open language models on your own computer with one install. This tutorial walks through the command line, the REST API, conversation history, the OpenAI-compatible endpoint and a custom model built from a Modelfile, all run on an ordinary laptop, with the settings and limits worth knowing.
What Is Generative AI? A Complete Beginner's Guide
What generative AI is, in plain language: how language models produce text one token at a time (shown with a tiny runnable model), how chat models are trained, how image models differ, what the technology is reliable for, and why it confabulates.