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
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
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
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
async function compareTopics(topic1, topic2) {
return await researchAgent(
`Compare ${topic1} vs ${topic2}: features, pros, cons, pricing, community. End with a recommendation table.`
);
}Saving Reports
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
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
- Comparative research — Compare two topics
- Periodic updates — Re-research weekly
- PDF export — Convert report to PDF
- Web dashboard — Build a research management UI
- Source quality scoring — Rate sources by reliability
Next: We'll build a CLI Automation Tool.