I see this pattern everywhere:
- Developer wants to build an AI agent
- Developer installs LangChain (50+ dependencies)
- Developer spends 3 days reading LangChain docs
- Developer's simple agent is now 300 lines with 4 layers of abstraction
- Developer questions life choices
Here's the thing: you can build an AI agent in 50 lines with zero frameworks.
The 50-Line Agent
import anthropic
import requests
from bs4 import BeautifulSoup
client = anthropic.Anthropic()
TOOLS = [
{
"name": "scrape_url",
"description": "Get the text content of any web page",
"input_schema": {
"type": "object",
"properties": {"url": {"type": "string"}},
"required": ["url"]
}
}
]
def execute_tool(name, args):
if name == "scrape_url":
r = requests.get(args["url"], headers={"User-Agent": "Mozilla/5.0"}, timeout=10)
soup = BeautifulSoup(r.text, "html.parser")
return soup.get_text(separator="\n", strip=True)[:3000]
return "Unknown tool"
def agent(task, max_turns=10):
messages = [{"role": "user", "content": task}]
for _ in range(max_turns):
r = client.messages.create(
model="claude-sonnet-4-6-20250514", max_tokens=4096,
tools=TOOLS, messages=messages
)
if r.stop_reason == "end_turn":
return next(b.text for b in r.content if hasattr(b, "text"))
results = []
for b in r.content:
if b.type == "tool_use":
out = execute_tool(b.name, b.input)
results.append({"type": "tool_result", "tool_use_id": b.id, "content": out})
messages += [{"role": "assistant", "content": r.content}, {"role": "user", "content": results}]
return "Max turns"
print(agent("Summarize the top story on Hacker News right now"))
That's it. 50 lines. One dependency (anthropic). The agent can:
- Read any web page
- Decide which pages to read
- Chain multiple reads together
- Summarize and analyze what it finds
But What About LangChain?
LangChain is great if you need:
- Memory management across sessions
- RAG with vector databases
- Complex multi-agent orchestration
- Pre-built integrations with 100+ services
LangChain is overkill if you need:
- A simple agent that calls 1-3 tools
- A prototype or proof of concept
- Something you want to actually understand
Adding More Tools
Want your agent to also search the web and do math? Just add tools:
TOOLS = [
{"name": "scrape_url", ...},
{
"name": "calculate",
"description": "Evaluate a math expression",
"input_schema": {
"type": "object",
"properties": {"expression": {"type": "string"}},
"required": ["expression"]
}
}
]
def execute_tool(name, args):
if name == "scrape_url":
# ... same as before
elif name == "calculate":
return str(eval(args["expression"])) # Use safer eval in production
return "Unknown tool"
The agent now decides on its own whether to browse the web or calculate something.
When to Graduate to a Framework
| Situation | Use Raw API | Use Framework |
|---|---|---|
| 1-3 tools | ✅ | ❌ Overkill |
| Prototype | ✅ | ❌ Too slow |
| Multi-agent | ❌ | ✅ CrewAI/AutoGen |
| RAG pipeline | ❌ | ✅ LangChain |
| Complex state | ❌ | ✅ LangGraph |
| Production at scale | ❌ | ✅ Any framework |
The Philosophy
Frameworks solve problems you don't have yet. Start simple. Add complexity only when the simple version stops working.
"Three similar lines of code is better than a premature abstraction."
What's your agent stack?
I'm curious: are you using a framework? Raw API calls? Something else entirely?
If you built an agent, what tools did you give it? I'm collecting interesting agent architectures for a follow-up post.
Source code: AI Agent Starter Kit — the full version with 5 tools
More agent resources: Awesome AI Agents 2026 — every framework, compared
Top comments (0)