Stop using Perplexity manually — wire it into your stack as an always-on research layer via the API
Turn what you learned into a concrete stack decision.
01AI Agent ToolboxBuild autonomous AI agents that can read, write, and actWant the shortlist in your inbox?
Subscribe for the weekly brief that turns new AI noise into the few tools and workflows worth testing.
Curated bundles that help you move from this guide into a working stack.
Guide
Getting Started with Perplexity Agents
Perplexity isn't just a search engine — here's how to use it as an agent that researches, summarizes, and delivers answers on autopilot
Guide
MCP Servers Explained: What They Are and Why They Matter
The protocol connecting AI assistants to the real world — and how to use it today
Guide
Master Your AI Costs: Reading the Anthropic Console
Stop burning money on API calls — learn to read your dashboard, spot waste, and optimize like a pro
The beginner guide covered Perplexity as a tool you open and use. This guide treats it as infrastructure — a live-data research layer that your other systems query automatically.
The Perplexity API (called Sonar) lets you call Perplexity programmatically. Combined with webhooks, scheduled jobs, and agent frameworks, you get a research pipeline that runs without human input.
Perplexity's API is OpenAI-compatible. If you've used the OpenAI SDK, you can use Perplexity with minimal changes.
Get your API key at perplexity.ai/settings/api (Pro plan required).
export PERPLEXITY_API_KEY=pplx-...
const response = await fetch("https://api.perplexity.ai/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.PERPLEXITY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "sonar",
messages: [
{
role: "system",
content: "You are a precise research assistant. Always include citations."
},
{
role: "user",
content: "What are the top 3 AI agent frameworks released in the last 30 days?"
}
],
max_tokens: 1000,
return_citations: true,
return_images: false,
search_recency_filter: "month", // Options: hour, day, week, month
}),
});
const data = await response.json();
const answer = data.choices[0].message.content;
const citations = data.citations; // Array of source URLs
| Model | Use case | Speed | Depth |
|---|---|---|---|
| sonar | General research, fast | Fast | Standard |
| sonar-pro | Complex research, more sources | Medium | Deep |
| sonar-reasoning | Step-by-step reasoning | Slow | Highest |
| sonar-deep-research | Multi-source synthesis, long reports | Slowest | Maximum |
For most automated pipelines: use sonar for monitoring/quick queries, sonar-pro for structured reports.
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.PERPLEXITY_API_KEY,
baseURL: "https://api.perplexity.ai",
});
const response = await client.chat.completions.create({
model: "sonar-pro",
messages: [{ role: "user", content: "Latest Solana TVL and ecosystem news" }],
});
This lets you swap Perplexity in/out of any OpenAI-based system by changing baseURL and apiKey.
The core pattern: trigger → query → structure → deliver.
Runs on a cron job or scheduled function. Queries Perplexity, formats the output, delivers via Telegram or email.
// research-digest.ts
import { Cron } from "croner";
const TOPICS = [
"DeFi protocol news last 24 hours",
"Solana ecosystem updates last 24 hours",
"AI agent framework releases last 7 days",
];
async function runDigest() {
const results = await Promise.all(
TOPICS.map(topic => queryPerplexity(topic))
);
const digest = results
.map((r, i) => `## ${TOPICS[i]}\n\n${r.answer}\n\n**Sources:** ${r.citations.join(", ")}`)
.join("\n\n---\n\n");
await sendToTelegram(digest);
}
async function queryPerplexity(query: string) {
const res = await fetch("https://api.perplexity.ai/chat/completions", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PERPLEXITY_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
model: "sonar",
messages: [{ role: "user", content: query }],
return_citations: true,
search_recency_filter: "day",
}),
});
const data = await res.json();
return {
answer: data.choices[0].message.content,
citations: data.citations ?? [],
};
}
// Run every morning at 7am
new Cron("0 7 * * *", runDigest);
When something happens in your system, trigger a Perplexity deep-dive automatically.
// Example: when a new token/project is added to a watchlist,
// automatically research it and store the result
async function onProjectAdded(projectName: string) {
const report = await queryPerplexity(
`Comprehensive overview of ${projectName}: what it is, team, traction,
recent news, token performance (if applicable), and community sentiment.
Include risks and contrarian views.`
);
await db.insert(researchReports).values({
project: projectName,
report: report.answer,
citations: report.citations,
generatedAt: new Date(),
model: "sonar-pro",
});
await notifyResearchComplete(projectName);
}
Perplexity handles one query at a time. For deep research, chain queries where each builds on the previous:
async function deepCompetitorAnalysis(companyName: string) {
// Step 1: Overview
const overview = await queryPerplexity(`What does ${companyName} do? Business model, target market, key differentiators.`);
// Step 2: Recent news (informed by overview)
const news = await queryPerplexity(
`Recent news about ${companyName} in the last 30 days. Context: ${overview.answer.slice(0, 300)}`
);
// Step 3: Community sentiment
const sentiment = await queryPerplexity(
`What are users and developers saying about ${companyName}? Reddit, Twitter, HackerNews sentiment.`
);
// Step 4: Synthesize with Claude
const synthesis = await claudeSynthesize({ overview, news, sentiment });
return synthesis;
}
For the synthesis step, pass Perplexity's raw findings to Claude (which has stronger reasoning) and let Claude draw conclusions, identify patterns, and generate recommendations.
Raw prose is hard to process programmatically. Force structured output with system prompts:
const systemPrompt = `
You are a research API. Always respond in valid JSON matching this schema:
{
"summary": "2-3 sentence summary",
"key_points": ["point 1", "point 2", "point 3"],
"sentiment": "bullish | bearish | neutral",
"confidence": 1-10,
"risks": ["risk 1", "risk 2"],
"sources_quality": "high | medium | low"
}
Do not include any text outside the JSON object.
`;
const response = await fetch("https://api.perplexity.ai/chat/completions", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PERPLEXITY_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
model: "sonar-pro",
messages: [
{ role: "system", content: systemPrompt },
{ role: "user", content: "Analyze sentiment around Ethereum L2 scaling solutions" }
],
return_citations: true,
}),
});
const data = await response.json();
const structured = JSON.parse(data.choices[0].message.content);
// structured.sentiment, structured.key_points, etc.
Note: Perplexity doesn't have native JSON mode like OpenAI — you enforce it via the system prompt. Add error handling for cases where the model includes prose outside the JSON.
The most powerful pattern: Perplexity finds and gathers, Claude reasons and decides.
User query
│
▼
Perplexity (sonar-pro)
→ Current information, cited sources, real-time data
│
▼
Claude (claude-sonnet or claude-opus)
→ Reasoning, synthesis, recommendations, action items
│
▼
Output (Telegram, database, dashboard, email)
Implementation:
async function researchAndReason(query: string) {
// Step 1: Perplexity gathers current facts
const research = await queryPerplexity(query);
// Step 2: Claude reasons on the facts
const analysis = await anthropic.messages.create({
model: "claude-sonnet-4-5",
max_tokens: 1500,
messages: [{
role: "user",
content: `
Based on this current research about "${query}", provide:
1. Your assessment (3-5 sentences)
2. Key risks to watch
3. Recommended next actions (numbered list)
4. Confidence level (1-10) and why
Research:
${research.answer}
Sources: ${research.citations.join(", ")}
`
}]
});
return {
facts: research.answer,
analysis: analysis.content[0].text,
sources: research.citations,
};
}
For scheduled jobs, build in delays:
async function batchResearch(queries: string[], delayMs = 2000) {
const results = [];
for (const query of queries) {
results.push(await queryPerplexity(query));
await new Promise(r => setTimeout(r, delayMs)); // Respect rate limits
}
return results;
}
| Strategy | Impact |
|---|---|
| Use sonar for monitoring, sonar-pro only for reports | 2-3x cost reduction |
| Cache results for repeated queries (TTL: 1-24hr depending on topic) | Major savings for monitoring |
| Filter topics before querying — only call API when novelty threshold exceeded | Reduces unnecessary calls |
| Limit max_tokens to what you actually need | Reduces token cost |
import { createClient } from "redis";
const redis = createClient();
async function queryWithCache(query: string, ttlSeconds = 3600) {
const cacheKey = `perplexity:${Buffer.from(query).toString("base64")}`;
const cached = await redis.get(cacheKey);
if (cached) return JSON.parse(cached);
const result = await queryPerplexity(query);
await redis.setEx(cacheKey, ttlSeconds, JSON.stringify(result));
return result;
}
For topics that need near-real-time tracking, combine Perplexity with a polling loop and change detection:
// Track a topic and alert only when something meaningfully new is found
const previousSummaries = new Map<string, string>();
async function monitorTopic(topic: string) {
const result = await queryPerplexity(`${topic} — latest news from the last 2 hours`);
const prev = previousSummaries.get(topic);
// Simple change detection: compare length and first 200 chars
const isDifferent = !prev ||
Math.abs(result.answer.length - prev.length) > 100 ||
result.answer.slice(0, 200) !== prev.slice(0, 200);
if (isDifferent) {
previousSummaries.set(topic, result.answer);
await sendAlert(topic, result.answer, result.citations);
}
}
// Poll every 30 minutes
setInterval(() => monitorTopic("major DeFi exploits or hacks"), 30 * 60 * 1000);
Before deploying a Perplexity pipeline to production:
Want help designing your Perplexity research pipeline or integrating it with your existing stack? Book a 30-minute call and we'll architect it together.