HomeBuilding Real ProjectsProject: Web Research Agent
advanced20 min read· Module 8, Lesson 7

🔍Project: Web Research Agent

Build an agent that searches the web, synthesizes results, and produces cited reports

Project: Web Research Agent

In this project, you'll build a smart agent that takes a question, searches the web, gathers information, and writes a comprehensive report with citations using Claude's built-in web search tool.

Main Code

JavaScript
import Anthropic from "@anthropic-ai/sdk"; const client = new Anthropic(); async function researchAgent(question) { console.log(`Researching: ${question}\n`); const response = await client.messages.create({ model: "claude-sonnet-4-20250514", max_tokens: 4096, tools: [{ type: "web_search_20250305" }], messages: [{ role: "user", content: `You are a research specialist. Research this topic and write a comprehensive report. Topic: ${question} Include: executive summary, key findings, detailed analysis, conclusion, source list with URLs.`, }], }); let report = ""; for (const block of response.content) { if (block.type === "text") report += block.text; } return report; } const report = await researchAgent("Latest developments in AI in 2025"); console.log(report);

Python Version

Python
import anthropic client = anthropic.Anthropic() def research_agent(question): response = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=4096, tools=[{"type": "web_search_20250305"}], messages=[{ "role": "user", "content": f"""Research specialist. Research this topic and write a comprehensive report. Topic: {question} Include: executive summary, key findings, analysis, conclusion, sources with URLs.""", }], ) report = "" for block in response.content: if block.type == "text": report += block.text return report report = research_agent("Latest AI agent frameworks in 2025") print(report)

Deep Research Agent with Loop

JavaScript
async function deepResearchAgent(question, maxSearches = 5) { const messages = [{ role: "user", content: `Research deeply. Search multiple times from different angles.\n\nTopic: ${question}\n\nWrite a detailed report with sources.`, }]; let searches = 0; while (searches < maxSearches) { const response = await client.messages.create({ model: "claude-sonnet-4-20250514", max_tokens: 4096, tools: [{ type: "web_search_20250305" }], messages, }); const searchBlocks = response.content.filter( (b) => b.type === "server_tool_use" && b.name === "web_search_20250305" ); searches += searchBlocks.length; if (response.stop_reason === "end_turn") { let report = ""; for (const block of response.content) { if (block.type === "text") report += block.text; } console.log(`Research complete (${searches} searches)`); return report; } messages.push({ role: "assistant", content: response.content }); messages.push({ role: "user", content: "Continue researching." }); } return "Max search limit reached"; }

Comparative Research

JavaScript
async function compareTopics(topic1, topic2) { return await researchAgent( `Compare ${topic1} vs ${topic2}: features, pros, cons, pricing, community. End with a recommendation table.` ); }

Saving Reports

JavaScript
import fs from "fs"; async function saveReport(question, outputPath) { const report = await researchAgent(question); const fullReport = `# Research Report\n## ${question}\n## ${new Date().toISOString().split("T")[0]}\n\n---\n\n${report}`; fs.writeFileSync(outputPath, fullReport, "utf-8"); console.log(`Report saved to: ${outputPath}`); }

CLI Interface

JavaScript
const question = process.argv.slice(2).join(" "); if (!question) { console.log("Usage: node researcher.js <your research question>"); process.exit(1); } researchAgent(question).then((report) => { console.log("\n" + "=".repeat(60) + "\n" + report); });

Extensions to Try

  1. Comparative research — Compare two topics
  2. Periodic updates — Re-research weekly
  3. PDF export — Convert report to PDF
  4. Web dashboard — Build a research management UI
  5. Source quality scoring — Rate sources by reliability

Next: We'll build a CLI Automation Tool.