
PLEASE NOTE: This is not an AI-generated blog. I wrote this blog myself, in my own words, based on what I have learned and understood.
Also, if you see emojis throughout the blog like (😄🍕) — It doesn't mean that GPT model written it. I added them by taking it from the google emojis.
Part-1 : Theoretical View
We are in the era of AI. As developers, most of us are already leveraging AI's capabilities inside our applications — sometimes knowingly, sometimes without even realizing which piece of tech is doing the heavy lifting.
We have been using : LangChain, LangGraph (built on top of LangChain), AutoGen, the Agents SDK, etc... --- each of them is a "Framework". But, what actually is a Framework? (No textbook definition)
Framework - what ?
A framework is just a code someone else already wrote, packaged up so you don't have to write it yourself.
It is someone else's pre-built, reusable work that quietly handles the boring, repetitive part of a task. So, we can plug in just the specific details that are important for our problem.
In the next part of this blog, we will see few examples on "How would our life be without frameworks ?", "How better it would be, if we use frameworks ?"
Analogy
Almost everyone reading this has eaten pizza at least once — or at least knows what a pizza looks like 🍕.
If you haven't had one yet, please order one now! 😄
Let's plan to have a pizza tonight. We have two options.
Option 1: Start from absolute zero
We have --- No dough. No sauce. No cheese. Nothing.
So technically, here's your to-do list:
Grow the wheat
Mill it into flour
Make the flour into dough
Grow tomatoes and cook them into sauce
Make the cheese from scratch
Prepare every topping
Finally — bake the pizza
You have full control over every small part of that pizza. But there's a catch: it takes a lot of time.
By the time you've done everything from growing the wheat to baking the pizza, it might have taken you weeks.
Option 2: Walk into a pizza shop
Instead, you walk into a pizza shop that provides you the basics:
Pre-made dough
Sauce, ready to go
Cheese, already grated
All required toppings
Notice what didn't happen here:
Nobody handed you a finished pizza.
Nobody decided what kind of pizza you're making.
You can still choose (the pizza you wanted) :
Margherita 🍕
Paneer 🍕
Chicken 🍕
Loaded veggie 🍕
Whatever you want.
The pizza shop simply removed the part of the job that is common and repetitive — growing wheat, milling flour, preparing the basic ingredients, and so on.
Now you can spend your time on the part that's actually yours --- Deciding what goes on the pizza, and in what combination.
That's the basic idea of a FRAMEWORK.
Implementing it into code
A programming language is like you, standing in an empty kitchen with raw ingredients and no shortcuts. You have enormous freedom and you can cook literally anything — But everything is on you, from scratch.
A framework is the pizza shop handing you the dough and sauce. Similarly, a framework in programming is someone already solved the boring, repeated-every-time problems, and packaged the solution as ready-to-use code.
You didn't get a finished app — the same way you didn't get a finished pizza. You got the common groundwork, which is already done, so you can focus your energy on what makes your application actually yours.
A example: Building a website
Without a Framework :
First, we need to know —
How do I receive a request when someone visits my website? (Receiving HTTP requests)
How do I figure out which page they asked for? (Understanding which URL the user requested--- means, I can have about page, contact page, etc...)
How do I send something back to the user? (Sending HTTP responses)
How do I handle different pages (routes) without writing the same logic again and again? (Handling different routes)
We are actually doing a lot of plumbing work, before we have written a single line of our actual website info.
With a Framework :
The framework already provides the machinery for receiving requests, handling routes, and sending responses. So, instead of worrying about how to handle requests, we can start thinking about what content my website should have and what information my website should provide when someone visits.
The goal is same, there is no change. The difference is, you are just ot starting from scratch anymore.
A framework doesn't provide you a finished application. It just solves the boring and repetitive part that many applications need.
Part-2 : Practical View
How would our life be without a framework?
Let's take a very small example : Imagine that we want to build a program that asks an Generative AI model (LLM) a simple question: "What is the capital of France?"
Let's use Groq OpenAI model.
Without a framework
- We have to talk to Groq Open AI directly -- which means, we need to understand , how the Groq OpenAI wants us to communicate with it.
import os
import requests
from dotenv import load_dotenv
load_dotenv()
api_key = os.environ.get("GROQ_API_KEY")
response = requests.post(
#url to send API request
"https://api.groq.com/openai/v1/chat/completions",
#headers that this API accepts
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
},
json={
"model": "openai/gpt-oss-20b",
#providing the question in specific format
"messages": [{"role": "user", "content": "What is the capital of France?"}],
},
)
data = response.json()
#extracting the specific field where the actual response from the API lies
print(data['choices'][0]['message']['content'])
In the above python code, we have to handle many things by ourselves:
Where to send the request
Which headers Groq-OpenAI expects
How to provide the question
The exact structure of the request (embedding in JSON format)
How to read the response
The exact location of the answer inside that response
Why are we doing all this ? --- because we are talking directly to OpenAI's API. we aren't seeking any additional help.
What if we decide to use another LLM API provider ? --- like Claude instead of OpenAI
We aren't changing our task of asking a question ---- "What is the capital of France?
But now, because we're talking directly to Anthropic (provider of Claude), we have to learn Anthropic's way of communicating with its API**.** Because, URL is different, headers are different , request format and response structure will also differ
import os
import requests
from dotenv import load_dotenv
load_dotenv()
api_key = os.environ.get("ANTHROPIC_API_KEY")
response = requests.post(
#differnet URL
"https://api.anthropic.com/v1/messages",
#different headers
headers={
"x-api-key": api_key,
"anthropic-version": "2023-06-01",
"Content-Type": "application/json"
},
#request format
json={
"model": "claude-sonnet-4-6",
"max_tokens": 1000,
"messages": [
{"role": "user", "content": "What is the capital of France?"}
]
}
)
data = response.json()
#different response structure
answer = data["content"][0]["text"]
print(answer)
Our code has changed when compared to above GroqAPI.
Different URL
Additional field in the header section
Additional parameters in request format
The response structure is different
And if tomorrow, if we switch to another LLM provider again, we may have to learn that provider's way of doing things too.
All this difficulties is because we are configuring according to each provider by ourselves.
Oh wait! If we don't do by ourselves, then who will be doing this plumbing work 😄
How is life with a framework?
It is like someone saying :
"You just tell me which model you want and give me your question. I will take care of configuring the provider (doing all the plumbing work)."
So, with a framework like "Langchain", we can write as :
from langchain_openai import ChatOpenAI
model = ChatOpenAI(model="gpt-oss-20b")
response = model.invoke("What is the capital of France?")
print(response.content)
Now look at what disappeared: (LangChain is handling all the plumbing for us)
Without LangChain, we had to deal with things like:
Where to send the request
Which headers to use
How to structure the request
How to read the response
With LangChain, we don't have to deal with those provider-specific details directly.
The URL, headers, and request shape — all handled internally.
So our application doesn't need to know all the details of how the provider's API works internally.
But what if we don't want OpenAI?
We want to use some other LLM model other than OpenAI, let's move to Claude:
Without a framework, we would have to learn Claude's API and change the code that communicates with the provider.
But with LangChain, we can simply use the corresponding model class:
from langchain_anthropic import ChatAnthropic
model = ChatAnthropic(model="claude-sonnet-4-6")
response = model.invoke("What is the capital of France?")
print(response.content)
Only the part that changed is the provider and model name.
We didn't change the application logic. It still follows the same basic pattern.
Give the model a question -> Invoke the model -> Get the response
We don't have to rewrite our application just because the underlying AI provider changed.
So, it is the real benefit of Framework.
What did LangChain actually did for us?
Think about what happened behind the scenes.
When we use:
ChatOpenAI()--- LangChain knows how to communicate with OpenAI.When we use:
ChatAnthropic()--- LangChain knows how to communicate with Anthropic.- These two providers have different APIs, but LangChain gives us a common way to interact with both.
So, our application can work with a common LangChain interface (instead of needing to learn -- OpenAI's way, Google's way, etc...)
That's a big improvement.
There's a catch
Nothing comes with exceptions ! 😄
LangChain magically doesn't know everything about every possible endpoint.
For example: Groq also provides an OpenAI-compatible API endpoint.
What! Yeah, you heard it right!
- Some providers offer APIs that are compatible with other providers' APIs, which means you can use their models through an API that follows the same interface as another provider's API.
Interesting! Let's see what it is!
Let's use OpenAI model through Groq
The model might be an OpenAI model, but the provider is Groq.
So, we need to tell LangChain that explicitly:
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os
load_dotenv()
api_key = os.environ.get("GROQ_API_KEY")
model = ChatOpenAI(model="openai/gpt-oss-20b", base_url="https://api.groq.com/openai/v1", api_key=api_key)
response = model.invoke(
"What is the capital of France?"
)
print(response.content)
Even though we are using Groq, our application still uses:
model.invoke()andresponse.content()
The difference is that this time we had to provide some configuration ourselves like
base_urlandapi_keybecause LangChain cannot assume that an OpenAI-compatible endpoint is actually hosted by Groq.So, the framework doesn't remove all configuration in such cases.
It removes a lot of the repetitive provider-specific plumbing and gives us a common way to work with the different providers.
The framework takes care of the provider-specific details underneath.
Isn't life better with framework?
Without a framework, every provider can force us to learn a different way of doing the same thing.
With a framework, we can work with a common interface while the framework handles much of the provider-specific work underneath.
Going back to our pizza shop.
Without the pizza shop:
- I will grow the wheat -> make the flour -> prepare the dough -> make the sauce -> make the cheese...
With the pizza shop:
- Give me the basic ingredients. I will decide what pizza I want.
The pizza shop didn't make the pizza for us, it didn't even decide what pizza you wanted.
It didn't take away your freedom. It simply removed a lot of work that we didn't want to repeat, as someone already done that for us.
That's exactly the value of a framework in software.
A framework gives you ready-made building blocks and handles much of the common groundwork, so you can spend more of your time building the business logic, that is unique to your application.
If you don't still appreciate why framework made our life easier, then try thinking about
Tools
Conversation memory
Connecting to multiple databases etc...
Basically, making our AI model as an Agent by providing it more capabilities like above mentioned (tools, memory, etc..).
If you want to do this all, without any framework, it takes a lot of effort and a lot of core-python logic implementation.
If interested in exploring LangGraph framework, explore it here

