Choose an Agent Framework for a Web Data Application
AI & Machine LearningCompare LangGraph, the OpenAI Agents SDK, Google ADK, CrewAI, Mastra and the Claude Agent SDK on tools, state, deployment and tracing for a web data task.
There are many agent frameworks, and each one says it can build anything. For a web data application, only a few questions really decide the choice.
How does the framework define tools? Where does it keep state, and can a run pick up where it stopped? How do you deploy it, and what can you see when something goes wrong?
This guide starts with what your extraction task needs. Then it compares six current frameworks on those points, using each framework's own documentation. It ends with a shared task you can run yourself.
How we built this comparison: We read each framework's official docs on October 16, 2026. Every claim below comes from those docs. We did not run speed or accuracy tests for this article, so it contains no rankings. Frameworks change quickly, so check the linked docs before you decide.
What does your extraction task require?
Write down your task before you look at any framework. These five questions cover most web data applications.
1. How many steps does the task have?
- One fixed step: "Extract these fields from this URL." You may not need a framework at all. A plain API call and your own code may be enough.
- A few fixed steps: "Find pages, then extract, then save." A workflow tool with typed steps fits well.
- Open-ended steps: "Research this question until you can answer it." An agent loop with tools fits better.
2. How long does a run take?
A run that finishes in seconds can live in memory. A run that takes minutes or hours needs saved state, so it can survive a restart.
3. Does a person need to review anything?
If someone must approve a source list or check a result, the framework needs a way to pause and resume later.
4. Which language does your team use?
Some frameworks are Python first. Some are TypeScript first. A few support several languages.
5. How will you connect to web data?
For MrScraper, there are a few documented paths:
- The MrScraper MCP server. It offers
scraperAPI,webSearchandstatustools to any MCP client. It runs hosted athttps://mcp.mrscraper.com/mcpor locally. - The LangChain integration. The
langchain-mrscraperpackage gives LangChain and LangGraph agents eight ready-made tools. - The REST API, Python SDK or Node.js SDK. You wrap these in your own typed tools. Since every framework below supports MCP, the MCP server works with all of them. Custom tools give you more control over inputs, outputs and errors.
The six frameworks at a glance
| Framework | Languages | What it is built around |
|---|---|---|
| LangGraph | Python, TypeScript | Graphs of steps with saved state |
| OpenAI Agents SDK | Python, TypeScript | Agents with tools, handoffs and a built-in loop |
| Google ADK | Python, TypeScript, Go, Java, Kotlin | Agents with sessions, state and Google Cloud deployment |
| CrewAI | Python | Crews of agents with roles, plus Flows for workflows |
| Mastra | TypeScript | Agents, tools and workflows for TypeScript apps |
| Claude Agent SDK | Python, TypeScript | The Claude Code agent loop as a library |
How do typed tools and state differ across frameworks?
Typed tools tell the model exactly what to send. Saved state lets a long run survive a crash. These two features decide how much code you write around your web data calls.
Tools
| Framework | How you define a tool | How MCP tools connect |
|---|---|---|
| LangGraph | LangChain tools; MrScraper's langchain-mrscraper package ships ready-made ones |
MCPAdapter from langchain.mcp (beta, needs langchain[mcp] 1.4.0 or later) |
| OpenAI Agents SDK | A Python function with a decorator; the SDK builds the schema from type hints with Pydantic | MCPServerStreamableHttp, MCPServerStdio or HostedMCPTool |
| Google ADK | Function tools from your own functions | McpToolset with StreamableHTTPConnectionParams or StdioConnectionParams |
| CrewAI | Tools attached to agents; structured outputs with Pydantic | The mcps field on an agent, or MCPServerAdapter |
| Mastra | createTool() with a Zod inputSchema and optional outputSchema |
MCPClient from @mastra/mcp |
| Claude Agent SDK | @tool in Python or tool() in TypeScript, served by create_sdk_mcp_server |
mcp_servers with "type": "http" or a local command |
A few details matter for web data:
- Error handling. The OpenAI Agents SDK lets you set a
failure_error_function, which controls the message the model sees when a tool fails. The Claude Agent SDK lets a tool returnis_errorwith your own message. Both help the model react to a failed page fetch instead of guessing. - Output types. Mastra tools can declare an
outputSchema, so tool results are checked as well as inputs. - Tool permissions. The Claude Agent SDK requires you to allow MCP tools by name, such as
mcp__mrscraper__scraperAPI. Nothing runs until you list it inallowed_tools.
State and resuming
| Framework | Where state lives | Built-in options named in the docs |
|---|---|---|
| LangGraph | Checkpoints saved after graph steps, grouped by thread_id |
InMemorySaver, SqliteSaver, PostgresSaver |
| OpenAI Agents SDK | Sessions that store conversation history across runs | SQLiteSession, RedisSession, SQLAlchemySession and others |
| Google ADK | Sessions with state for the current conversation | In-memory options for testing, plus database and cloud options |
| CrewAI | Flow state as a Pydantic model; @persist saves it |
SQLiteFlowPersistence is the default backend |
| Mastra | Workflows that can suspend and resume, plus memory and storage | Workflow snapshots and storage providers |
| Claude Agent SDK | Sessions you can resume or fork later | Session resume through the SDK |
Note the difference between conversation history and job state. A session that stores past messages helps a chat continue. A web data job also needs to know which URLs it already read, which fields are still missing and how much budget is left. In some frameworks, that state is built in. In others, you store it yourself.
For long research jobs, look for a framework that can save state after each step and resume from it. LangGraph checkpoints, CrewAI's @persist and Mastra's suspend and resume all point in that direction.
How should you compare deployment and observability?
A framework that works on your laptop still has to run somewhere. And when a web data run fails, you need to see which tool call broke and why.
Deployment
| Framework | Deployment paths named in the docs |
|---|---|
| LangGraph | Your own servers, or LangSmith Deployment for long-running, stateful workflows |
| OpenAI Agents SDK | Your own infrastructure; it is a library you run |
| Google ADK | Containers on your own infrastructure, or Agent Runtime, Cloud Run or GKE on Google Cloud |
| CrewAI | Your own infrastructure, or the CrewAI Enterprise console |
| Mastra | Inside TypeScript apps such as Next.js, Express or Hono, plus Mastra's deploy options |
| Claude Agent SDK | A process you operate; the SDK runs the Claude Code binary |
Observability
| Framework | Tracing named in the docs |
|---|---|
| LangGraph | LangSmith tracing, turned on with LANGSMITH_TRACING=true |
| OpenAI Agents SDK | Built-in tracing for visualizing, debugging and monitoring runs |
| Google ADK | Logging, metrics and traces; Cloud Trace on Google Cloud |
| CrewAI | Built-in tracing with tracing=True, viewed in CrewAI AMP |
| Mastra | Built-in tracing with exporters, including Langfuse and Arize |
| Claude Agent SDK | Hooks that run your code at key points in the agent loop |
What to check for web data
Whatever you pick, make sure you can see these four things for every run:
- Each tool call, with its URL and arguments
- Each tool result, including errors
- Usage per call. MrScraper responses report
token_usageandruntime, so pass them into your traces. - The final answer and its sources, so you can trace a wrong answer back to a page
Also check that your tracing setup does not record secrets. Mastra, for example, includes a
SensitiveDataFilterfor redacting values like tokens and keys. With any framework, keep API keys out of tool arguments, so they never reach a trace.
What does a shared task reveal?
Docs tell you what a framework offers. Building the same small task in each one shows how it feels to use. Run this test on two or three frameworks from your shortlist.
The shared task
Given three documentation URLs, extract each product's name, latest version and release date. Return JSON with a source URL and a supporting quote for each field. Stop after 10 tool calls. If a field is not found, return
nullinstead of guessing.
Use the same parts everywhere
Keep everything except the framework the same:
- The same model and model settings
- The same three URLs
- The same MrScraper connection, such as the hosted MCP server or the same custom tool
- The same tool-call limit
- The same answer key, written by hand before you start
Connect MrScraper the same way in each
Here is the hosted MCP server in the OpenAI Agents SDK. The key comes from an environment variable and is sent as a bearer token, which is the API key option the MrScraper MCP docs describe.
import os
from agents import Agent, Runner
from agents.mcp import MCPServerStreamableHttp
async def run_task(prompt: str):
async with MCPServerStreamableHttp(
name="mrscraper",
params={
"url": "https://mcp.mrscraper.com/mcp",
"headers": {"Authorization": f"Bearer {os.environ['MRSCRAPER_API_KEY']}"},
},
) as server:
agent = Agent(
name="Release checker",
instructions="Use only the given URLs. Quote the page for every field.",
mcp_servers=[server],
)
return await Runner.run(agent, prompt, max_turns=10)
And here is the same server in the Claude Agent SDK:
import os
from claude_agent_sdk import ClaudeAgentOptions
options = ClaudeAgentOptions(
mcp_servers={
"mrscraper": {
"type": "http",
"url": "https://mcp.mrscraper.com/mcp",
"headers": {"Authorization": f"Bearer {os.environ['MRSCRAPER_API_KEY']}"},
}
},
allowed_tools=["mcp__mrscraper__scraperAPI"],
)
For LangGraph, you can skip MCP and use the LangChain package instead. It reads the MRSCRAPER_API_TOKEN environment variable.
from langchain_mrscraper import MrScraperToolkit
tools = MrScraperToolkit().get_tools()
Score what you observe
Use the same scorecard for each framework. Fill it in from your own runs.
| Check | What to record |
|---|---|
| Correct fields | How many of the nine fields match your answer key |
| Made-up fields | Fields with a value that is not on the page |
| Quotes that match | Quotes that appear word for word on the cited page |
| Tool calls | How many calls each run used, and whether the limit held |
| Failure handling | What happened when you gave it a broken URL |
| Resume | Whether you could stop a run halfway and continue it |
| Trace quality | Whether you could find each URL, result and error in the trace |
| Code size | How many lines of your own code the task needed |
Run each framework several times. Model output varies, so one run is not enough to see a pattern.
What to look for in the results
The shared task is built to show differences that a feature table hides:
- Where your code lives. In some frameworks, limits and checks sit in the graph or workflow. In others, they sit in your tools or in code around the agent.
- How errors reach the model. A clear error message helps the model try another URL. A raw exception often leads to a guess.
- How much state you manage yourself. If the framework does not track visited URLs or remaining budget, you will write that code.
- What you can see. A trace that shows each URL and result makes debugging fast. A trace that only shows model messages does not. Pick the framework where these four things fit your team best. The one with the most features is not always the right choice.
FAQs
What does your extraction task require?
Start with five questions. How many steps does the task have? How long does a run take? Does a person need to review anything? Which language does your team use? How will you connect to web data? The answers narrow the list before you compare features.
What does a shared task reveal?
Building the same small task in each framework shows where your code ends up, how tool errors reach the model, how much state you manage yourself and what the traces show. Keep the model, URLs, tools and limits the same, and score each run with the same checklist.
Which parts does MrScraper provide, and which parts must my application implement?
MrScraper is a developer-focused web data API. It provides a REST API, Python and Node.js SDKs, a LangChain integration and an MCP server with hosted and local options. These fetch pages, discover URLs and extract structured data, and each response reports usage.
Your application provides the framework, the model, the agent logic, state, limits, tracing and checks on the final answer. Your team also decides which sources it has permission to collect from.
Summarize this post
Open it in your assistant of choice with the prompt ready to send.
Take a Taste of Easy Scraping!
Find more insights here

Build a Source-Led Deep Research Workflow With MrScraper
Build a deep research workflow that turns a question into a source plan, collects evidence from appr…

Design AI Research Loops That Stop, Recover and Produce Evidence
Learn how to build an AI research loop with clear states, firm stop conditions, safe retries after f…

How to Build a Custom Amazon Price Monitor Without Code
Learn how to build a custom Amazon price tracker in under two minutes without code. Automate price m…