Building a Research Agent with Exa Search + Mithril
Build an autonomous research agent that searches the web, summarizes findings, and pays for every API call — no API keys required.
In this tutorial, we'll build a research agent that autonomously searches the web using Exa, summarizes findings with an LLM, and pays for every API call via x402 — no API keys for individual services required.
What We're Building
A research agent that:
Total cost per report: typically $0.05-0.50 depending on depth.
Architecture
User Input → Research Agent → Exa Search ($0.003/search)
→ Firecrawl ($0.01/page)
→ OpenRouter ($0.02-0.10/summary)
→ Research ReportAll three services are paid via x402 through Mithril. The agent doesn't need API keys for any of them.
Setup
import Mithril from "@mithril/sdk"
const m = new Mithril({
apiKey: process.env.MITHRIL_API_KEY,
})Step 1: Search with Exa
async function searchWeb(query: string) {
const result = await m.pay({
url: "https://api.exa.ai/search",
method: "POST",
body: JSON.stringify({
query,
numResults: 10,
type: "neural",
}),
})
return result.data.results
}Cost: ~$0.003 per search.
Step 2: Scrape Pages with Firecrawl
async function scrapePage(url: string) {
const result = await m.pay({
url: "https://api.firecrawl.dev/v1/scrape",
method: "POST",
body: JSON.stringify({
url,
formats: ["markdown"],
}),
})
return result.data.markdown
}Cost: ~$0.01 per page.
Step 3: Summarize with OpenRouter
async function summarize(content: string, topic: string) {
const result = await m.pay({
url: "https://openrouter.ai/api/v1/chat/completions",
method: "POST",
body: JSON.stringify({
model: "anthropic/claude-sonnet-4-6",
messages: [{
role: "user",
content: `Summarize the following content about "${topic}":\n\n${content}`,
}],
}),
})
return result.data.choices[0].message.content
}Step 4: Orchestrate the Pipeline
async function research(topic: string) {
// Search
const searchResults = await searchWeb(topic)
// Scrape top 5 results
const pages = await Promise.all(
searchResults.slice(0, 5).map(r => scrapePage(r.url))
)
// Summarize each page
const summaries = await Promise.all(
pages.map(page => summarize(page, topic))
)
// Final synthesis
const report = await summarize(
summaries.join("\n\n---\n\n"),
`comprehensive analysis of: ${topic}`
)
return report
}Cost Breakdown
| Step | Service | Cost per unit | Units | Total |
|---|
|------|---------|--------------|-------|-------|
| Search | Exa | $0.003 | 1 | $0.003 |
|---|---|---|---|---|
| Summarize | OpenRouter | ~$0.02 | 6 | $0.12 |
| **Total** | **~$0.17** |
That's a comprehensive research report for 17 cents. With Mithril's credit line, your agent doesn't need upfront funding — it spends now and you settle monthly.