On this page
The Vercel AI SDK gives you a unified interface for calling LLMs from any framework -- Next.js, SvelteKit, Nuxt, or plain Node. CrawlForge gives your LLM access to live web data through 26 specialized scraping tools. Together, they let you build AI applications that can search, fetch, extract, and analyze web content in real time.
This tutorial shows you how to register CrawlForge tools with the Vercel AI SDK's tool() API, so your AI can scrape the web as naturally as it generates text.
Table of Contents
- Prerequisites
- How It Works: Tools in the Vercel AI SDK
- Step 1: Create the CrawlForge Tool Wrapper
- Step 2: Register Tools with generateText
- Step 3: Build a Streaming Chat with Web Access
- Advanced: Multi-Tool Research Agent
- Credit Cost Breakdown
- Best Practices
- Next Steps
Prerequisites
npm install ai @ai-sdk/anthropic zod dotenv# .env.local
ANTHROPIC_API_KEY=sk-ant-xxxxx
CRAWLFORGE_API_KEY=cf_live_xxxxxGet your CrawlForge API key at crawlforge.dev/signup -- 1,000 free credits included.
How It Works: Tools in the Vercel AI SDK
The Vercel AI SDK lets you define tools that the LLM can invoke during a conversation. Each tool has a name, description, parameter schema (using Zod), and an execute function. The LLM reads the tool descriptions, decides when to call them, and incorporates the results into its response.
CrawlForge's REST API maps perfectly to this pattern: each of the 26 tools becomes a callable function with typed parameters.
Step 1: Create the CrawlForge Tool Wrapper
First, build a reusable helper that calls any CrawlForge endpoint:
// lib/crawlforge.ts
const CRAWLFORGE_BASE = 'https://crawlforge.dev/api/v1/tools';
export async function callCrawlForge<T>(
toolName: string,
params: Record<string, unknown>
): Promise<T> {
const response = await fetch(`${CRAWLFORGE_BASE}/${toolName}`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.CRAWLFORGE_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(params),
});
if (!response.ok) {
throw new Error(`CrawlForge ${toolName} failed: ${response.status}`);
}
return response.json() as Promise<T>;
}Step 2: Register Tools with generateText
Now register CrawlForge tools using the Vercel AI SDK's tool() function:
// app/api/chat/route.ts
import { generateText, tool } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { z } from 'zod';
import { callCrawlForge } from '@/lib/crawlforge';
const result = await generateText({
model: anthropic('claude-sonnet-4-20250514'),
tools: {
// Fetch and extract clean content from any URL (2 credits)
extractContent: tool({
description: 'Extract the main content from a web page as clean text. Use this when you need to read an article, documentation page, or any web content.',
parameters: z.object({
url: z.string().url().describe('The URL to extract content from'),
}),
execute: async ({ url }) => {
return callCrawlForge('extract_content', { url });
},
}),
// Search the web (5 credits)
searchWeb: tool({
description: 'Search the web using Google. Returns titles, URLs, and snippets for the top results.',
parameters: z.object({
query: z.string().describe('The search query'),
limit: z.number().optional().default(5).describe('Number of results'),
}),
execute: async ({ query, limit }) => {
return callCrawlForge('search_web', { query, limit });
},
}),
// Extract structured data with CSS selectors (2 credits)
scrapeStructured: tool({
description: 'Extract specific data from a web page using CSS selectors. Use when you need structured data like prices, names, or lists.',
parameters: z.object({
url: z.string().url().describe('The URL to scrape'),
selectors: z.record(z.string()).describe('CSS selectors mapping field names to selectors'),
}),
execute: async ({ url, selectors }) => {
return callCrawlForge('scrape_structured', { url, selectors });
},
}),
},
prompt: 'Find the current pricing for Vercel Pro plan and compare it to Netlify Pro.',
});
console.log(result.text);When the LLM encounters a question that requires web data, it automatically invokes the right CrawlForge tool, receives the results, and weaves them into its response. No manual orchestration needed.
Step 3: Build a Streaming Chat with Web Access
For a real-time chat experience, use streamText instead of generateText:
// app/api/chat/route.ts
import { streamText, tool } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { z } from 'zod';
import { callCrawlForge } from '@/lib/crawlforge';
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: anthropic('claude-sonnet-4-20250514'),
system: `You are a research assistant with access to live web data.
When users ask about current information, use your tools to fetch it.
Always cite the URLs you retrieved data from.`,
messages,
tools: {
extractContent: tool({
description: 'Extract main content from a URL as clean text',
parameters: z.object({
url: z.string().url(),
}),
execute: async ({ url }) =>
callCrawlForge('extract_content', { url }),
}),
searchWeb: tool({
description: 'Search the web and return top results',
parameters: z.object({
query: z.string(),
limit: z.number().optional().default(5),
}),
execute: async ({ query, limit }) =>
callCrawlForge('search_web', { query, limit }),
}),
},
maxSteps: 5, // Allow up to 5 tool calls per response
});
return result.toDataStreamResponse();
}The maxSteps: 5 parameter lets the LLM chain multiple tool calls -- for example, searching the web first, then extracting content from the top result.
Frontend Component
// app/page.tsx
'use client';
import { useChat } from 'ai/react';
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat();
return (
<div className="max-w-2xl mx-auto p-4">
{messages.map((m) => (
<div key={m.id} className="mb-4">
<strong>{m.role === 'user' ? 'You' : 'AI'}:</strong>
<p>{m.content}</p>
</div>
))}
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={handleInputChange}
placeholder="Ask anything about the web..."
className="w-full p-2 border rounded"
disabled={isLoading}
/>
</form>
</div>
);
}Advanced: Multi-Tool Research Agent
Combine multiple CrawlForge tools for deeper research workflows:
import { generateText, tool } from 'ai';
import { anthropic } from '@ai-sdk/anthropic';
import { z } from 'zod';
import { callCrawlForge } from '@/lib/crawlforge';
const research = await generateText({
model: anthropic('claude-sonnet-4-20250514'),
tools: {
searchWeb: tool({
description: 'Search Google for information',
parameters: z.object({ query: z.string(), limit: z.number().default(5) }),
execute: async ({ query, limit }) =>
callCrawlForge('search_web', { query, limit }),
}),
extractContent: tool({
description: 'Read the full content of a web page',
parameters: z.object({ url: z.string().url() }),
execute: async ({ url }) =>
callCrawlForge('extract_content', { url }),
}),
analyzeContent: tool({
description: 'Analyze text for topics, sentiment, and key entities',
parameters: z.object({ text: z.string() }),
execute: async ({ text }) =>
callCrawlForge('analyze_content', { text }),
}),
},
maxSteps: 10,
prompt: `Research the current state of MCP server adoption in 2026.
Search for recent articles, read the top 3, and analyze the key trends.
Provide a summary with citations.`,
});
console.log(research.text);
// Returns a cited research summary using live web dataThis agent will:
- Search Google for relevant articles (5 credits)
- Extract content from the top results (2 credits each)
- Analyze the content for themes (3 credits each)
Total cost for a 3-source research run: ~20 credits.
Credit Cost Breakdown
| Tool | Credits | Best For |
|---|---|---|
| fetch_url | 1 | Raw HTML retrieval |
| extract_text | 1 | Clean text extraction |
| extract_links | 1 | Link discovery |
| extract_metadata | 1 | Page metadata (title, OG tags) |
| extract_content | 2 | Readable content extraction |
| scrape_structured | 2 | CSS selector-based data extraction |
| summarize_content | 2 | Text summarization |
| analyze_content | 3 | Topic and sentiment analysis |
| search_web | 5 | Google search results |
| deep_research | 10 | Multi-source research with citations |
See the full pricing breakdown for all 26 tools.
Best Practices
Minimize credit usage. Use extract_content (2 credits) instead of deep_research (10 credits) when you only need one page. The tool descriptions guide the LLM toward the cheapest option that satisfies the query.
Set maxSteps carefully. A higher maxSteps value allows more tool calls per response but consumes more credits. Start with 3-5 and increase only if the LLM consistently needs more.
Cache frequently accessed pages. If your app repeatedly fetches the same URL, cache the CrawlForge response in Redis or a database rather than re-fetching each time.
Use Zod descriptions. The .describe() strings on your Zod parameters help the LLM understand what values to pass. Be specific: "The full URL including https://" is better than "URL".
Next Steps
You now have a Vercel AI SDK application with live web access. Expand from here:
- Add the remaining 26 CrawlForge tools as needed
- Implement stealth mode for sites with anti-bot protection
- Build a deep research agent for automated market analysis
- Check the CrawlForge Quick Start for MCP client setup
Build AI apps that see the web. Start free with 1,000 credits -- no credit card required.
Try this yourself — no signup needed
Run any of CrawlForge's 27 scraping and extraction tools in the playground, then start free with 1,000 credits.
1,000 free credits • Refills monthly • No credit card required
Tags
About the Author
Stay updated with the latest insights
Get tutorials, product updates, and web scraping tips delivered to your inbox.
No spam. Unsubscribe anytime.