Skip to content

Should Beginners Start with CrewAI, LangGraph, or Plain API Calls for AI Agents?

The Framework Rabbit Hole

When I started building AI agents, I made a classic mistake. I jumped straight into CrewAI, thinking it would make everything easier. Instead, I spent two weeks debugging configuration issues, understanding agent roles, and fighting with orchestration patterns I didn’t actually need.

My first “agent” was simple: call an API, process the response, send another call. But I had layered so much abstraction on top that I couldn’t even debug the basic flow.

Here’s what my architecture looked like:

My Request
CrewAI Agent (with role, goal, backstory)
CrewAI Task (with context, tools, callbacks)
CrewAI Crew (orchestration logic I didn't understand)
LangChain LLM (another abstraction)
OpenAI API (what I actually needed)

Six layers to make a simple API call. When something broke, I had no idea where. Was it the crew configuration? The task definition? The agent’s backstory (yes, that’s a real parameter)?

What I Should Have Done First

After struggling with frameworks, I went back to basics. Here’s what a simple agent looks like with just the OpenAI API:

simple_agent.py
import openai
client = openai.OpenAI(api_key="your-key")
def simple_agent(user_input):
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": user_input}
]
)
return response.choices[0].message.content

That’s it. Three lines of actual code. No configuration files, no role definitions, no orchestration patterns to learn.

When I wanted to add function calling (the building block of all agent frameworks), here’s what changed:

agent_with_tools.py
import openai
import json
client = openai.OpenAI(api_key="your-key")
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"}
},
"required": ["location"]
}
}
}
]
def agent_with_tools(user_input):
response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": user_input}
],
tools=tools
)
message = response.choices[0].message
if message.tool_calls:
tool_call = message.tool_calls[0]
if tool_call.function.name == "get_weather":
args = json.loads(tool_call.function.arguments)
result = get_weather(args["location"])
# Continue the conversation with tool result
second_response = client.chat.completions.create(
model="gpt-4",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": user_input},
message,
{"role": "tool", "content": result, "tool_call_id": tool_call.id}
]
)
return second_response.choices[0].message.content
return message.content

Now I understand what’s actually happening:

  1. I send a message
  2. The model decides if it needs a tool
  3. If yes, it returns a tool call
  4. I execute the tool
  5. I send the result back
  6. The model generates a final response

This is the core loop that CrewAI, LangGraph, and every other framework wraps. Once I understood this, the frameworks made sense.

Why Frameworks Exist (And Why They Confuse Beginners)

Framework authors aren’t trying to confuse you. They solve real problems:

Plain API:
- Manual state management
- You build the loop yourself
- Error handling is manual
- Multi-agent coordination is complex
Frameworks provide:
- State management built-in
- Pre-built loops and patterns
- Structured error handling
- Multi-agent orchestration

But these benefits only matter if you understand what they’re abstracting. It’s like learning React before understanding JavaScript. React solves real problems, but you need to know what those problems are.

Here’s what happens when you skip fundamentals:

You see this in CrewAI:
agent = Agent(role="Researcher", goal="Find information")
You think: "Great, simple syntax!"
What you miss: This creates:
- System prompt construction
- Tool binding logic
- Memory management
- Response parsing
- Error recovery

When your agent produces unexpected output, you have no mental model for debugging. Is it the role definition? The goal? The underlying prompt? The model’s interpretation?

The Learning Path That Actually Works

Reddit users who build agents for production agree: start with the API.

From a developer who runs a real estate business:

“I’d skip the frameworks and start with the actual problem you’re solving… I didn’t learn Python first. I ran a real estate business and asked: which part of this breaks when I’m not watching it? Then I built agents for those specific pieces, one at a time.”

From another experienced developer:

“Skip the framework rabbit hole at first. Learn how to talk to an LLM via API, understand tokens and context windows, then build something small end to end. The frameworks change every month but understanding how tool use and function calling actually work under the hood transfers everywhere.”

Here’s the path that works:

Step 1: Plain API Calls
- Learn request/response structure
- Understand tokens and costs
- Handle basic errors
Step 2: Function Calling
- Define tools
- Parse tool calls
- Execute and return results
Step 3: Simple Loops
- Build conversation loops
- Manage state manually
- Handle multi-turn interactions
Step 4: Then (Maybe) Frameworks
- You now understand what they abstract
- You can debug when things break
- You know when frameworks help vs. hinder

What You Learn from Plain API Calls

These fundamentals transfer to any framework:

Token Management

response = client.chat.completions.create(
model="gpt-4",
messages=messages,
max_tokens=500 # Now I understand what this costs
)
print(f"Tokens used: {response.usage.total_tokens}")

When I hit token limits in CrewAI, I knew exactly what was happening. Without this understanding, you’re just tweaking config values hoping something works.

Context Window Economics

Every message you send costs tokens. Long conversation history costs more. Understanding this helps you design agents that don’t waste money.

# Bad: Growing context forever
messages.append({"role": "user", "content": new_input})
# Good: Managed context
messages = messages[-10:] # Keep last 10 messages
messages.append({"role": "user", "content": new_input})

Function Calling Patterns

The tool call loop I showed earlier? That’s how all agents work. LangGraph calls it “nodes” and “edges.” CrewAI calls it “tasks” and “crews.” But underneath, it’s the same pattern:

1. Model decides what to do
2. If tool needed: execute tool, return result
3. Repeat until done

Once I understood this, I could read any framework’s source code and see exactly what it was doing.

When Frameworks Actually Help

After building with plain APIs, I found legitimate use cases for frameworks:

Multi-Agent Systems

When I needed three agents collaborating on a complex workflow:

Research Agent → Analysis Agent → Writing Agent

Managing this manually meant tracking state across agents, handling failures, and coordinating outputs. LangGraph made this cleaner with its graph structure.

Long-Running Workflows

For workflows that needed to pause and resume (like waiting for human approval), LangGraph’s checkpointing helped. But I only appreciated this after trying to build checkpointing myself.

Production Monitoring

CrewAI and LangGraph have built-in observability tools. This matters for production systems, but not for learning.

The “Framework of the Week” Problem

Another Reddit comment stuck with me:

“Don’t get too caught up in the ‘framework of the week,’ because those will change by next month.”

I’ve seen this play out. In the past year alone:

  • AutoGPT was the hot thing, then faded
  • LangChain evolved into LangGraph
  • CrewAI gained traction, now competes with newer options
  • New frameworks appear monthly

But the underlying concepts stayed constant:

  • How LLM APIs work
  • Token economics
  • Function calling patterns
  • Context management

These don’t change. Learn them once, use them forever.

A Practical Starting Point

If you’re a beginner, here’s what I’d build with just APIs:

  1. Simple Chatbot - Request/response loop with conversation history
  2. Tool-Using Agent - One tool (weather API, calculator) with function calling
  3. Multi-Step Agent - Agent that uses multiple tools in sequence
  4. Memory Agent - Simple memory system (store/retrieve past conversations)

Each project teaches one concept deeply. By the end, you’ll understand every abstraction in any framework.

Here’s a minimal multi-step agent:

multi_step_agent.py
import openai
import json
client = openai.OpenAI(api_key="your-key")
TOOLS = {
"search": lambda q: f"Search results for: {q}",
"calculate": lambda expr: str(eval(expr)),
}
def agent(user_input, max_iterations=5):
messages = [
{"role": "system", "content": "You are a helpful assistant with search and calculate tools."},
{"role": "user", "content": user_input}
]
for _ in range(max_iterations):
response = client.chat.completions.create(
model="gpt-4",
messages=messages,
tools=[{
"type": "function",
"function": {
"name": name,
"description": f"Use {name} tool",
"parameters": {"type": "object", "properties": {}}
}
} for name in TOOLS]
)
message = response.choices[0].message
messages.append(message)
if not message.tool_calls:
return message.content
for tool_call in message.tool_calls:
tool_name = tool_call.function.name
result = TOOLS[tool_name]("")
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result
})
return "Max iterations reached"

Forty lines of code. Every line is explicit. When it breaks, you know where to look.

Summary

In this post, I explained why beginners should start with plain API calls before using frameworks like CrewAI or LangGraph. The key point is that understanding tokens, context windows, and function calling fundamentals gives you knowledge that transfers across any framework you’ll eventually use.

The frameworks solve real problems, but only after you understand what those problems are. Start with APIs, build simple agents, then graduate to frameworks when you hit their sweet spot use cases.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments