# Get Async Chat Completion Source: https://docs.perplexity.ai/api-reference/async-chat-completions-api-request-get get /async/chat/completions/{api_request} Retrieve the response for a given asynchronous chat completion request. # List Async Chat Completions Source: https://docs.perplexity.ai/api-reference/async-chat-completions-get get /async/chat/completions Retrieve a list of all asynchronous chat completion requests for a given user. # Create Async Chat Completion Source: https://docs.perplexity.ai/api-reference/async-chat-completions-post post /async/chat/completions Submit an asynchronous chat completion request. # Create Chat Completion Source: https://docs.perplexity.ai/api-reference/chat-completions-post post /chat/completions Generate a chat completion response for the given conversation. # Create Contextualized Embeddings Source: https://docs.perplexity.ai/api-reference/contextualized-embeddings-post post /v1/contextualizedembeddings Generate contextualized embeddings for document chunks. Chunks from the same document share context awareness, improving retrieval quality for document-based applications. # Create Embeddings Source: https://docs.perplexity.ai/api-reference/embeddings-post post /v1/embeddings Generate embeddings for a list of texts. Use these embeddings for semantic search, clustering, and other machine learning applications. # Generate Auth Token Source: https://docs.perplexity.ai/api-reference/generate-auth-token-post post /generate_auth_token Generates a new authentication token for API access. # Create Response Source: https://docs.perplexity.ai/api-reference/responses-post post /v1/responses Generate a response for the provided input with optional web search and reasoning. # Revoke Auth Token Source: https://docs.perplexity.ai/api-reference/revoke-auth-token-post post /revoke_auth_token Revokes an existing authentication token. # Search the Web Source: https://docs.perplexity.ai/api-reference/search-post post /search Search the web and retrieve relevant web page contents. # API Key Management Source: https://docs.perplexity.ai/docs/admin/api-key-management Learn how to generate, revoke, and rotate API keys for secure access ## Overview API keys are essential for authenticating requests to the Perplexity API. This guide covers how to create, manage, and rotate your API keys using our authentication token management endpoints. API keys should be treated as sensitive credentials. Store them securely and never expose them in client-side code or public repositories. ## Getting Started: Create Your API Group First **Important Prerequisites**: Before you can generate any API keys, you must first create an API group through the Perplexity web interface. Navigate to the API Groups page and create your first group: **[Create API Group →](https://www.perplexity.ai/account/api/group)** API groups help organize your keys and manage access across different projects or environments. Choose a descriptive name for your API group (e.g., "Production", "Development", or your project name) to help with organization. Once you have an API group, navigate to the API Keys page to generate your first key: **[Generate API Keys →](https://www.perplexity.ai/account/api/keys)** You can create multiple keys within each group for different purposes or environments. After creating your first API key through the web interface, you can use the programmatic endpoints below to generate and manage additional keys. ## Key Management Endpoints Perplexity provides two endpoints for managing API keys programmatically: * **`/generate_auth_token`** - Creates a new API key * **`/revoke_auth_token`** - Revokes an existing API key Once an API key is revoked, it cannot be recovered. Make sure to update your applications with new keys before revoking old ones. ## Generating API Keys Create new API keys programmatically with optional naming for better organization. ### Request ```bash cURL theme={null} curl --request POST \ --url https://api.perplexity.ai/generate_auth_token \ --header "Authorization: Bearer YOUR_EXISTING_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "token_name": "Production API Key" }' ``` ```python Python theme={null} import requests url = "https://api.perplexity.ai/generate_auth_token" headers = { "Authorization": "Bearer YOUR_EXISTING_API_KEY", "Content-Type": "application/json" } payload = { "token_name": "Production API Key" # Optional } response = requests.post(url, headers=headers, json=payload) data = response.json() print(f"New API Key: {data['auth_token']}") print(f"Created at: {data['created_at_epoch_seconds']}") ``` ```typescript Typescript theme={null} const response = await fetch("https://api.perplexity.ai/generate_auth_token", { method: "POST", headers: { "Authorization": "Bearer YOUR_EXISTING_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ token_name: "Production API Key" // Optional }) }); const data = await response.json(); console.log(`New API Key: ${data.auth_token}`); console.log(`Created at: ${data.created_at_epoch_seconds}`); ``` ### Response ```json theme={null} { "auth_token": "pplx-1234567890abcdef", "created_at_epoch_seconds": 1735689600, "token_name": "Production API Key" } ``` Store the `auth_token` immediately and securely. This is the only time you'll be able to see the full token value. ## Revoking API Keys Revoke API keys that are no longer needed or may have been compromised. ### Request ```bash cURL theme={null} curl --request POST \ --url https://api.perplexity.ai/revoke_auth_token \ --header "Authorization: Bearer YOUR_API_KEY" \ --header "Content-Type: application/json" \ --data '{ "auth_token": "pplx-1234567890abcdef" }' ``` ```python Python theme={null} import requests url = "https://api.perplexity.ai/revoke_auth_token" headers = { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" } payload = { "auth_token": "pplx-1234567890abcdef" } response = requests.post(url, headers=headers, json=payload) if response.status_code == 200: print("API key successfully revoked") ``` ```typescript Typescript theme={null} const response = await fetch("https://api.perplexity.ai/revoke_auth_token", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" }, body: JSON.stringify({ auth_token: "pplx-1234567890abcdef" }) }); if (response.status === 200) { console.log("API key successfully revoked"); } ``` ### Response Returns a `200 OK` status code on successful revocation. ## API Key Rotation Regular key rotation is a security best practice that minimizes the impact of potential key compromises. Here's how to implement zero-downtime key rotation: ### Rotation Strategy Create a new API key while your current key is still active: ```python theme={null} # Generate new key new_key_response = requests.post( "https://api.perplexity.ai/generate_auth_token", headers={"Authorization": f"Bearer {current_key}"}, json={"token_name": f"Rotated Key - {datetime.now().isoformat()}"} ) new_key = new_key_response.json()["auth_token"] ``` Deploy the new key to your applications: ```python theme={null} # Update environment variables or secrets management os.environ["PERPLEXITY_API_KEY"] = new_key # Verify new key works test_response = requests.post( "https://api.perplexity.ai/chat/completions", headers={"Authorization": f"Bearer {new_key}"}, json={ "model": "sonar", "messages": [{"role": "user", "content": "Test"}] } ) assert test_response.status_code == 200 ``` Ensure all services are using the new key before proceeding: ```python theme={null} # Monitor your application logs to confirm # all instances are using the new key time.sleep(300) # Wait for propagation ``` Once confirmed, revoke the old key: ```python theme={null} # Revoke old key revoke_response = requests.post( "https://api.perplexity.ai/revoke_auth_token", headers={"Authorization": f"Bearer {new_key}"}, json={"auth_token": current_key} ) assert revoke_response.status_code == 200 print("Key rotation completed successfully") ``` ### Automated Rotation Example Here's a complete example of an automated key rotation script: ```python Python theme={null} import requests import os import time from datetime import datetime import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) class PerplexityKeyRotator: def __init__(self, current_key): self.base_url = "https://api.perplexity.ai" self.current_key = current_key def generate_new_key(self, name=None): """Generate a new API key""" url = f"{self.base_url}/generate_auth_token" headers = {"Authorization": f"Bearer {self.current_key}"} payload = {} if name: payload["token_name"] = name response = requests.post(url, headers=headers, json=payload) response.raise_for_status() return response.json() def test_key(self, key): """Test if a key is valid""" url = f"{self.base_url}/chat/completions" headers = {"Authorization": f"Bearer {key}"} payload = { "model": "sonar", "messages": [{"role": "user", "content": "Test"}], "max_tokens": 1 } try: response = requests.post(url, headers=headers, json=payload) return response.status_code == 200 except: return False def revoke_key(self, key_to_revoke): """Revoke an API key""" url = f"{self.base_url}/revoke_auth_token" headers = {"Authorization": f"Bearer {self.current_key}"} payload = {"auth_token": key_to_revoke} response = requests.post(url, headers=headers, json=payload) return response.status_code == 200 def rotate_key(self, update_callback=None): """Perform complete key rotation""" logger.info("Starting key rotation...") # Step 1: Generate new key new_key_data = self.generate_new_key( name=f"Rotated-{datetime.now().strftime('%Y%m%d-%H%M%S')}" ) new_key = new_key_data["auth_token"] logger.info(f"New key generated: {new_key[:10]}...") # Step 2: Test new key if not self.test_key(new_key): raise Exception("New key validation failed") logger.info("New key validated successfully") # Step 3: Update application (callback) if update_callback: update_callback(new_key) logger.info("Application updated with new key") # Step 4: Wait for propagation logger.info("Waiting for propagation...") time.sleep(30) # Step 5: Revoke old key old_key = self.current_key self.current_key = new_key # Use new key for revocation if self.revoke_key(old_key): logger.info("Old key revoked successfully") else: logger.warning("Failed to revoke old key") logger.info("Key rotation completed") return new_key # Usage example def update_environment(new_key): """Update your environment with the new key""" os.environ["PERPLEXITY_API_KEY"] = new_key # Update your secrets management system here # update_aws_secrets_manager(new_key) # update_kubernetes_secret(new_key) # Perform rotation rotator = PerplexityKeyRotator(os.environ["PERPLEXITY_API_KEY"]) new_key = rotator.rotate_key(update_callback=update_environment) print(f"Rotation complete. New key: {new_key[:10]}...") ``` ```typescript Typescript theme={null} import fetch from 'node-fetch'; class PerplexityKeyRotator { private baseUrl = 'https://api.perplexity.ai'; private currentKey: string; constructor(currentKey: string) { this.currentKey = currentKey; } async generateNewKey(name?: string): Promise<{ auth_token: string; created_at_epoch_seconds: number; token_name?: string; }> { const response = await fetch(`${this.baseUrl}/generate_auth_token`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.currentKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify(name ? { token_name: name } : {}) }); if (!response.ok) { throw new Error(`Failed to generate key: ${response.statusText}`); } return response.json(); } async testKey(key: string): Promise { try { const response = await fetch(`${this.baseUrl}/chat/completions`, { method: 'POST', headers: { 'Authorization': `Bearer ${key}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'sonar', messages: [{ role: 'user', content: 'Test' }], max_tokens: 1 }) }); return response.ok; } catch { return false; } } async revokeKey(keyToRevoke: string): Promise { const response = await fetch(`${this.baseUrl}/revoke_auth_token`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.currentKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ auth_token: keyToRevoke }) }); return response.ok; } async rotateKey(updateCallback?: (newKey: string) => Promise): Promise { console.log('Starting key rotation...'); // Step 1: Generate new key const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const newKeyData = await this.generateNewKey(`Rotated-${timestamp}`); const newKey = newKeyData.auth_token; console.log(`New key generated: ${newKey.substring(0, 10)}...`); // Step 2: Test new key if (!(await this.testKey(newKey))) { throw new Error('New key validation failed'); } console.log('New key validated successfully'); // Step 3: Update application if (updateCallback) { await updateCallback(newKey); console.log('Application updated with new key'); } // Step 4: Wait for propagation console.log('Waiting for propagation...'); await new Promise(resolve => setTimeout(resolve, 30000)); // Step 5: Revoke old key const oldKey = this.currentKey; this.currentKey = newKey; if (await this.revokeKey(oldKey)) { console.log('Old key revoked successfully'); } else { console.warn('Failed to revoke old key'); } console.log('Key rotation completed'); return newKey; } } // Usage example async function updateEnvironment(newKey: string): Promise { process.env.PERPLEXITY_API_KEY = newKey; // Update your secrets management system here // await updateAwsSecretsManager(newKey); // await updateKubernetesSecret(newKey); } // Perform rotation const rotator = new PerplexityKeyRotator(process.env.PERPLEXITY_API_KEY!); const newKey = await rotator.rotateKey(updateEnvironment); console.log(`Rotation complete. New key: ${newKey.substring(0, 10)}...`); ``` ## Best Practices Never hardcode API keys in your source code. Store them in environment variables or secure secret management systems. **Good**: `os.environ["PERPLEXITY_API_KEY"]` **Bad**: `api_key = "pplx-1234567890abcdef"` Rotate your API keys regularly (e.g., every 90 days) to minimize the impact of potential compromises. Set up automated rotation scripts to ensure zero downtime during the rotation process. When generating keys, use the `token_name` parameter to identify their purpose and environment. Examples: "Production-Main", "Development-Testing", "CI/CD-Pipeline" Track which keys are being used in your applications and revoke unused keys promptly. Maintain an inventory of active keys and their purposes. ## Security Considerations **Never expose API keys in:** * Client-side JavaScript code * Mobile applications * Public repositories * Log files or error messages * URLs or query parameters ### If a Key is Compromised 1. **Immediately generate a new key** using `/generate_auth_token` 2. **Update all applications** to use the new key 3. **Revoke the compromised key** using `/revoke_auth_token` 4. **Review access logs** to identify any unauthorized usage 5. **Implement additional security measures** such as IP allowlisting if available ## Troubleshooting | Issue | Solution | | -------------------------------------- | ---------------------------------------------------------------- | | "Authentication failed" after rotation | Ensure the new key has propagated to all service instances | | Cannot revoke a key | Verify you're using a valid API key with appropriate permissions | | Key generation fails | Check your account status and API tier limits | | Services still using old key | Implement proper secret rotation in your deployment pipeline | For additional support with API key management, visit your [API settings page](https://www.perplexity.ai/settings/api) or contact our support team. # Rate Limits & Usage Tiers Source: https://docs.perplexity.ai/docs/admin/rate-limits-usage-tiers ## What are Usage Tiers? Usage tiers determine your **rate limits** and access to **beta features** based on your cumulative API spending. As you spend more on API credits over time, you automatically advance to higher tiers with increased rate limits. Higher tiers unlock significantly more requests per minute, and once you reach a tier, you keep it permanently with no downgrade. You can check your current usage tier by visiting your [API settings page](https://www.perplexity.ai/account/api/billing). *** ## Tier Progression | Tier | Total Credits Purchased | Status | | ---------- | ----------------------- | ---------------------------- | | **Tier 0** | \$0 | New accounts, limited access | | **Tier 1** | \$50+ | Light usage, basic limits | | **Tier 2** | \$250+ | Regular usage | | **Tier 3** | \$500+ | Heavy usage | | **Tier 4** | \$1,000+ | Production usage | | **Tier 5** | \$5,000+ | Enterprise usage | Tiers are based on **cumulative purchases** across your account lifetime, not current balance. Need custom rate limits beyond your current tier? Fill out our rate limit increase request form and we'll review your use case to accommodate your needs. *** ## Agent API Rate Limits The Agent API uses tier-based rate limits that scale with your usage tier: | Tier | QPS (Queries per Second) | Requests per Minute | | :--------: | :----------------------: | :-----------------: | | **Tier 0** | 1 QPS | 50/min | | **Tier 1** | 3 QPS | 150/min | | **Tier 2** | 8 QPS | 500/min | | **Tier 3** | 17 QPS | 1,000/min | | **Tier 4** | 33 QPS | 2,000/min | | **Tier 5** | 33 QPS | 2,000/min | *** ## Search API Rate Limits The Search API has separate rate limits that apply to all usage tiers: | Endpoint | Rate Limit | Burst Capacity | | -------------- | ---------------------- | -------------- | | POST `/search` | 50 requests per second | 50 requests | **Search Rate Limiter Behavior:** * **Burst**: Can handle 50 requests instantly * **Sustained**: Exactly 50 QPS average over time Search rate limits are independent of your usage tier and apply consistently across all accounts using the same leaky bucket algorithm. *** ## Sonar API Rate Limits The Sonar API uses tier-based rate limits that scale with your usage tier: | Model | Requests per minute (RPM) | | ------------------------------------------ | ------------------------- | | `sonar-deep-research` | 5 | | `sonar-reasoning-pro` | 50 | | `sonar-pro` | 50 | | `sonar` | 50 | | POST `/async/chat/completions` | 5 | | GET `/async/chat/completions` | 3000 | | GET `/async/chat/completions/{request_id}` | 6000 | | Model | Requests per minute (RPM) | | ------------------------------------------ | ------------------------- | | `sonar-deep-research` | 10 | | `sonar-reasoning-pro` | 150 | | `sonar-pro` | 150 | | `sonar` | 150 | | POST `/async/chat/completions` | 10 | | GET `/async/chat/completions` | 3000 | | GET `/async/chat/completions/{request_id}` | 6000 | | Model | Requests per minute (RPM) | | ------------------------------------------ | ------------------------- | | `sonar-deep-research` | 20 | | `sonar-reasoning-pro` | 500 | | `sonar-pro` | 500 | | `sonar` | 500 | | POST `/async/chat/completions` | 20 | | GET `/async/chat/completions` | 3000 | | GET `/async/chat/completions/{request_id}` | 6000 | | Model | Requests per minute (RPM) | | ------------------------------------------ | ------------------------- | | `sonar-deep-research` | 40 | | `sonar-reasoning-pro` | 1,000 | | `sonar-pro` | 1,000 | | `sonar` | 1,000 | | POST `/async/chat/completions` | 40 | | GET `/async/chat/completions` | 3000 | | GET `/async/chat/completions/{request_id}` | 6000 | | Model | Requests per minute (RPM) | | ------------------------------------------ | ------------------------- | | `sonar-deep-research` | 60 | | `sonar-reasoning-pro` | 4,000 | | `sonar-pro` | 4,000 | | `sonar` | 4,000 | | POST `/async/chat/completions` | 60 | | GET `/async/chat/completions` | 3000 | | GET `/async/chat/completions/{request_id}` | 6000 | | Model | Requests per minute (RPM) | | ------------------------------------------ | ------------------------- | | `sonar-deep-research` | 100 | | `sonar-reasoning-pro` | 4,000 | | `sonar-pro` | 4,000 | | `sonar` | 4,000 | | POST `/async/chat/completions` | 100 | | GET `/async/chat/completions` | 3000 | | GET `/async/chat/completions/{request_id}` | 6000 | *** ## How Rate Limiting Works Our rate limiting system uses a **leaky bucket algorithm** that allows for burst traffic while maintaining strict long-term rate control. ### Technical Implementation The leaky bucket algorithm works like a bucket with a small hole in the bottom: * **Bucket Capacity**: Maximum number of requests you can make instantly (burst capacity) * **Leak Rate**: How quickly tokens leak out of the bucket (your rate limit) * **Token Refill**: Tokens refill continuously at regular intervals based on your rate limit This design allows legitimate burst traffic when you need it, prevents sustained abuse, and ensures predictable and fair rate enforcement across all users. Let's examine how **50 requests per second** works in practice. With a capacity of 50 tokens and a leak rate of 50 tokens per second, one token refills every 20ms. **Scenario 1: Burst Traffic** ``` Time 0.0s: Bucket full (50 tokens) → Send 50 requests instantly → ALL ALLOWED → Send 51st request → REJECTED (bucket empty) Time 0.020s: 1 token refilled → Send 1 request → ALLOWED → Send 2nd request → REJECTED Time 0.040s: 1 more token refilled → Send 1 request → ALLOWED ``` **Scenario 2: Steady 50 QPS** ``` Request every 20ms: Time 0.0s: Request → ALLOWED (50→49 tokens) Time 0.020s: Request → ALLOWED (49+1-1=49 tokens) Time 0.040s: Request → ALLOWED (49+1-1=49 tokens) ... maintains 49-50 tokens, all requests pass ``` **Scenario 3: Slightly Over 50 QPS** ``` Request every 19ms (≈52.6 QPS): → Eventually tokens deplete faster than refill → Some requests start getting rejected → Achieves exactly 50 QPS on average ``` The leaky bucket design means you can handle your full rate limit instantly, making it perfect for batch operations or sudden traffic spikes. There's no need to artificially spread requests when you have available burst capacity. The system enforces strict average rate limits over time while allowing quick recovery after burst usage. This provides consistent performance across different usage patterns and prevents sustained over-limit usage while maintaining fair resource allocation. When building your application, take advantage of burst capacity for batch operations, monitor your usage patterns to optimize request timing, and implement proper error handling for 429 responses. *** ## What Happens When You Hit Rate Limits? When you exceed your rate limits: 1. **429 Error** - Your request gets rejected with "Too Many Requests" 2. **Continuous Refill** - Tokens refill continuously based on your rate limit 3. **Immediate Recovery** - New requests become available as soon as tokens refill **Example Recovery Times:** * **50 QPS limit**: 1 token refills every 20ms * **500 QPS limit**: 1 token refills every 2ms * **1,000 QPS limit**: 1 token refills every 1ms **Best Practices:** * Monitor your usage to predict when you'll need higher tiers * Consider upgrading your tier proactively for production applications * Implement exponential backoff with jitter in your code * Take advantage of burst capacity for batch operations * Don't artificially spread requests if you have available burst capacity *** ## Upgrading Your Tier Visit your [API settings page](https://www.perplexity.ai/settings/api) to see your current tier and total spending. Add credits to your account through the billing section. Your tier will automatically upgrade once you reach the spending threshold. Your new rate limits take effect immediately after the tier upgrade. Check your settings page to confirm. If you require custom rate limits beyond Tier 5, [fill out our rate limit increase request form](https://perplexity.typeform.com/to/yctmfyVT) and we'll review your use case to accommodate your needs. Higher tiers significantly improve your API experience with increased rate limits, especially important for production applications. # Search Filters Source: https://docs.perplexity.ai/docs/agent-api/filters Control and customize Agent API search results with filters Control which search results are returned by applying filters to your web search queries. Filters help you focus on specific domains, time periods, or geographic locations to get more relevant results. ## Domain Filters Domain filters allow you to include or exclude specific domains or URLs from search results. Use allowlist mode to restrict results to trusted sources, or denylist mode to filter out unwanted domains. You can add a maximum of 20 domains or URLs to the `search_domain_filter` list. The filter works in either allowlist mode (include only) or denylist mode (exclude), but not both simultaneously. **Allowlist mode**: Include only the specified domains/URLs (no `-` prefix)\ **Denylist mode**: Exclude the specified domains/URLs (use `-` prefix) You can filter at the domain level (e.g., `wikipedia.org`) or URL level (e.g., `https://en.wikipedia.org/wiki/Chess`) for granular control. ```python Python theme={null} from perplexity import Perplexity client = Perplexity() response = client.responses.create( preset="fast-search", input="Tell me about the James Webb Space Telescope discoveries.", instructions="You are a helpful assistant.", tools=[ { "type": "web_search", "filters": { "search_domain_filter": [ "nasa.gov", "wikipedia.org", "space.com" ] } } ] ) print(response.output_text) ``` ## Date & Time Filters Date and time filters help you find content published or updated within specific time periods. You can filter by publication date, last updated date, or use recency filters for relative time periods. **Publication date filters**: Filter by when content was originally published * `search_after_date_filter`: Include content published after this date * `search_before_date_filter`: Include content published before this date **Last updated filters**: Filter by when content was last modified * `last_updated_after_filter`: Include content updated after this date * `last_updated_before_filter`: Include content updated before this date **Recency filter**: Filter by relative time periods * `search_recency_filter`: Use `"day"`, `"week"`, `"month"`, or `"year"` for content from the past 24 hours, 7 days, 30 days, or 365 days Specific date filters must be provided in the "%m/%d/%Y" format (e.g., "3/1/2025"). Recency filters use predefined values like "day", "week", "month", or "year". ```python Python theme={null} from perplexity import Perplexity client = Perplexity() response = client.responses.create( preset="pro-search", input="What are the latest AI developments?", instructions="You are an expert on current events.", tools=[ { "type": "web_search", "filters": { "search_recency_filter": "week" } } ] ) print(response.output_text) ``` ## Location Filters Location filters tailor search results based on geographic context. This is useful for finding local businesses, regional news, or location-specific information. You can specify location using: * **Country code**: Two-letter ISO 3166-1 alpha-2 code (e.g., `"US"`, `"FR"`) * **City and region**: Improve accuracy with city and region names * **Coordinates**: Latitude and longitude for precise location targeting The `city` and `region` fields significantly improve location accuracy. We strongly recommend including them alongside coordinates and country code for the best results. Latitude and longitude must be provided alongside the country parameter—they cannot be provided on their own. ```python Python theme={null} from perplexity import Perplexity client = Perplexity() response = client.responses.create( preset="pro-search", input="What are some good coffee shops nearby?", instructions="You are a helpful local guide.", tools=[ { "type": "web_search", "user_location": { "country": "US", "region": "California", "city": "San Francisco", "latitude": 37.7749, "longitude": -122.4194 } } ] ) print(response.output_text) ``` ## Combining Filters You can combine multiple filter types in a single request to create highly targeted searches. For example, you might restrict results to specific domains published within a recent time period, or filter by location and date range together. ```python Python theme={null} from perplexity import Perplexity client = Perplexity() response = client.responses.create( preset="pro-search", input="Latest tech news from trusted sources.", instructions="You are an expert on technology.", tools=[ { "type": "web_search", "filters": { "search_domain_filter": ["techcrunch.com", "theverge.com"], "search_recency_filter": "week" }, "user_location": { "country": "US" } } ] ) print(response.output_text) ``` ## Next Steps Get started with the Agent API. Explore direct model selection and third-party models. # Image Attachments Source: https://docs.perplexity.ai/docs/agent-api/image-attachments Learn how to upload and analyze images using base64 encoding or HTTPS URLs ## Overview The Agent API supports image analysis through direct image uploads. Images can be provided either as base64 encoded strings within a data URI or as standard HTTPS URLs. * When using base64 encoding, the API currently only supports images up to 50 MB per image. * Supported formats for base64 encoded images: PNG (image/png), JPEG (image/jpeg), WEBP (image/webp), and GIF (image/gif). * When using an HTTPS URL, the model will attempt to fetch the image from the provided URL. Ensure the URL is publicly accessible. ## Examples Use this method when you have the image file locally and want to embed it directly into the request payload. Remember the 50MB size limit and supported formats (PNG, JPEG, WEBP, GIF). ```python Python theme={null} import base64 from perplexity import Perplexity client = Perplexity(api_key="pplx-KEY") # Read and encode image as base64 def encode_image(image_path): with open(image_path, "rb") as image_file: return base64.b64encode(image_file.read()).decode("utf-8") image_path = "image.png" base64_image = encode_image(image_path) # Analyze the image response = client.responses.create( model="openai/gpt-5-mini", input=[ { "role": "user", "content": [ {"type": "input_text", "text": "what's in this image?"}, { "type": "input_image", "image_url": f"data:image/png;base64,{base64_image}", }, ], } ], ) print(response.output_text) ``` ```typescript TypeScript theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; import * as fs from 'fs'; const client = new Perplexity(); // Read and encode image as base64 const imageBuffer = fs.readFileSync('image.png'); const base64Image = imageBuffer.toString('base64'); const imageDataUri = `data:image/png;base64,${base64Image}`; // Analyze the image const response = await client.responses.create({ model: 'openai/gpt-5-mini', input: [ { role: 'user', content: [ { type: 'input_text', text: "What's in this image?" }, { type: 'input_image', image_url: imageDataUri } ] } ], }); console.log(response.output_text); ``` ```bash cURL theme={null} curl https://api.perplexity.ai/v1/responses \ -H "Authorization: Bearer $PERPLEXITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/gpt-5-mini", "input": [ { "role": "user", "content": [ { "type": "input_text", "text": "What'\''s in this image?" }, { "type": "input_image", "image_url": "data:image/png;base64,$BASE64_ENCODED_IMAGE" } ] } ] }' | jq ``` Use this method when you have a publicly accessible image URL. The model will fetch the image from the provided URL. ```python Python theme={null} from perplexity import Perplexity client = Perplexity(api_key="pplx-KEY") image_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg" # Analyze the image response = client.responses.create( model="openai/gpt-5-mini", input=[ { "role": "user", "content": [ {"type": "input_text", "text": "Can you describe the image at this URL?"}, { "type": "input_image", "image_url": image_url, }, ], } ], ) print(response.output_text) ``` ```typescript TypeScript theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity(); const imageHttpsUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"; // Analyze the image const response = await client.responses.create({ model: 'openai/gpt-5-mini', input: [ { role: 'user', content: [ { type: 'input_text', text: 'Can you describe the image at this URL?' }, { type: 'input_image', image_url: imageHttpsUrl } ] } ], }); console.log(response.output_text); ``` ```bash cURL theme={null} curl https://api.perplexity.ai/v1/responses \ -H "Authorization: Bearer $PERPLEXITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/gpt-5-mini", "input": [ { "role": "user", "content": [ { "type": "input_text", "text": "Can you describe the image at this URL?" }, { "type": "input_image", "image_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg" } ] } ] }' | jq ``` ## Request Format ### Agent API Images must be embedded in the `input` array when using message array format. Each image should be provided using the following structure: ```json theme={null} { "role": "user", "content": [ { "type": "input_text", "text": "What's in this image?" }, { "type": "input_image", "image_url": "" } ] } ``` The `image_url` field accepts either: * **A URL of the image**: A publicly accessible HTTPS URL pointing directly to the image file * **The base64 encoded image data**: A data URI in the format `data:image/{format};base64,{base64_content}` ## Pricing Images are tokenized based on their pixel dimensions using the following formula: ``` tokens = (width px × height px) / 750 ``` **Examples:** * A 1024×768 image would consume: (1024 × 768) / 750 = 1,048 tokens * A 512×512 image would consume: (512 × 512) / 750 = 349 tokens These image tokens are then priced according to the input token pricing of the model you're using. The image tokens are added to your total token count for the request alongside any text tokens. ## Next Steps Get started with the Agent API Learn about web\_search and fetch\_url tools # Model Fallback Source: https://docs.perplexity.ai/docs/agent-api/model-fallback Specify multiple models in a fallback chain for higher availability and automatic failover. ## Overview Model fallback enables specifying multiple models in a `models` array. The API tries each model in order until one succeeds, providing automatic failover when a model is unavailable. ## How It Works Provide a `models` array containing up to 5 models: 1. The API tries the first model in the array 2. If it fails or is unavailable, the next model is tried 3. This continues until one succeeds or all models are exhausted The `models` array takes precedence over the single `model` field when both are provided. **Benefits:** * **Higher availability**: Automatic failover when primary model is unavailable * **Provider redundancy**: Use models from different providers for maximum reliability * **Seamless operation**: No code refactoring needed, fallback is handled automatically by the API ## Basic Example ```python Python theme={null} from perplexity import Perplexity client = Perplexity() response = client.responses.create( models=["openai/gpt-5.2", "openai/gpt-5.1", "openai/gpt-5-mini"], input="What are the latest developments in AI?", instructions="You have access to a web_search tool. Use it for questions about current events.", ) print(f"Model used: {response.model}") ``` ```typescript Typescript theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity(); const response = await client.responses.create({ models: ["openai/gpt-5.2", "openai/gpt-5.1", "openai/gpt-5-mini"], input: "What are the latest developments in AI?", instructions: "You have access to a web_search tool. Use it for questions about current events.", }); console.log(`Model used: ${response.model}`); ``` ```bash cURL theme={null} curl https://api.perplexity.ai/v1/responses \ -H "Authorization: Bearer $PERPLEXITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "models": ["openai/gpt-5.2", "openai/gpt-5.1", "openai/gpt-5-mini"], "input": "What are the latest developments in AI?", "instructions": "You have access to a web_search tool. Use it for questions about current events." }' ``` ## Cross-Provider Fallback For maximum reliability, use models from different providers: ```python Python theme={null} from perplexity import Perplexity client = Perplexity() response = client.responses.create( models=[ "openai/gpt-5.2", "anthropic/claude-sonnet-4-5", "google/gemini-2.5-pro" ], input="Explain quantum computing in detail", ) ``` ```typescript Typescript theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity(); const response = await client.responses.create({ models: [ "openai/gpt-5.2", "anthropic/claude-sonnet-4-5", "google/gemini-2.5-pro" ], input: "Explain quantum computing in detail", }); ``` ```bash cURL theme={null} curl https://api.perplexity.ai/v1/responses \ -H "Authorization: Bearer $PERPLEXITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "models": [ "openai/gpt-5.2", "anthropic/claude-sonnet-4-5", "google/gemini-2.5-pro" ], "input": "Explain quantum computing in detail" }' ``` ## Pricing Billing is based on the model that serves the request, not all models in the fallback chain. The `model` field in the response indicates which model was used, and the `usage` field shows the token counts for that model. **Request:** ```json theme={null} { "models": ["openai/gpt-5.2", "openai/gpt-5.1"], "input": "..." } ``` **Response** (if first model failed): ```json theme={null} { "model": "openai/gpt-5.1", "usage": { "input_tokens": 150, "output_tokens": 320, "total_tokens": 470 } } ``` In this case, billing is based on `gpt-5.1` pricing for 470 tokens. Place preferred models first in the array. Consider pricing differences when ordering the fallback chain. ## Next Steps Explore available models and their pricing. Explore available presets and their configurations. Get started with your first Agent API call. View complete endpoint documentation. # Models Source: https://docs.perplexity.ai/docs/agent-api/models Explore available presets and third-party models for the Agent API, including Perplexity presets and third-party model support. ### Available Models The Agent API supports direct access to models from multiple providers. All models are accessed directly from first-party providers with transparent token-based pricing. Pricing rates are updated monthly and **reflect direct first-party provider pricing with no markup**. All charges are based on actual token consumption, and every API response includes exact token counts so you know your costs per request. Not all third-party models support all features (e.g., reasoning, tools). Check model documentation for specific capabilities. | Model | Input Price | Output Price | Cache Read Price | Provider Documentation | | --------------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | -------------------- | --------------------------------------------------------------------------------------- | | **Perplexity Models** | | | | | | `perplexity/sonar` | \$0.25 / 1M tokens | \$2.50 / 1M tokens | \$0.0625 / 1M tokens | [Sonar](https://docs.perplexity.ai/docs/getting-started/models/models/sonar) | | **Anthropic Models** | | | | | | `anthropic/claude-opus-4-6` | \$5 / 1M tokens | \$25 / 1M tokens | \$0.50 / 1M tokens | [Claude Opus 4.6](https://www.anthropic.com/news/claude-opus-4-6) | | `anthropic/claude-opus-4-5` | \$5 / 1M tokens | \$25 / 1M tokens | \$0.50 / 1M tokens | [Claude Opus 4.5](https://www.anthropic.com/news/claude-opus-4-5) | | `anthropic/claude-sonnet-4-6` | \$3 / 1M tokens | \$15 / 1M tokens | \$0.30 / 1M tokens | [Claude Sonnet 4.6](https://www.anthropic.com/news/claude-sonnet-4-6) | | `anthropic/claude-sonnet-4-5` | \$3 / 1M tokens | \$15 / 1M tokens | \$0.30 / 1M tokens | [Claude Sonnet 4.5](https://www.anthropic.com/news/claude-sonnet-4-5) | | `anthropic/claude-haiku-4-5` | \$1 / 1M tokens | \$5 / 1M tokens | \$0.10 / 1M tokens | [Claude Haiku 4.5](https://www.anthropic.com/news/claude-haiku-4-5) | | **OpenAI Models** | | | | | | `openai/gpt-5.2` | \$1.75 / 1M tokens | \$14 / 1M tokens | \$0.175 / 1M tokens | [GPT-5.2](https://platform.openai.com/docs/models/gpt-5.2) | | `openai/gpt-5.1` | \$1.25 / 1M tokens | \$10 / 1M tokens | \$0.125 / 1M tokens | [GPT-5.1](https://platform.openai.com/docs/models/gpt-5.1) | | `openai/gpt-5-mini` | \$0.25 / 1M tokens | \$2 / 1M tokens | \$0.025 / 1M tokens | [GPT-5 Mini](https://platform.openai.com/docs/models/gpt-5-mini) | | **Google Models** | | | | | | `google/gemini-3.1-pro-preview` | \$2.00 / 1M tokens (≤200k context)
\$4.00 / 1M tokens (>200k context) | \$12.00 / 1M tokens (≤200k context)
\$18.00 / 1M tokens (>200k context) | 90% discount | [Gemini 3.1 Pro](https://ai.google.dev/gemini-api/docs/models#gemini-3.1-pro-preview) | | `google/gemini-3-pro-preview` | \$2.00 / 1M tokens (≤200k context)
\$4.00 / 1M tokens (>200k context) | \$12.00 / 1M tokens (≤200k context)
\$18.00 / 1M tokens (>200k context) | 90% discount | [Gemini 3.0 Pro](https://ai.google.dev/gemini-api/docs/models#gemini-3-pro-preview) | | `google/gemini-3-flash-preview` | \$0.50 / 1M tokens | \$3.00 / 1M tokens | 90% discount | [Gemini 3.0 Flash](https://ai.google.dev/gemini-api/docs/models#gemini-3-flash-preview) | | `google/gemini-2.5-pro` | \$1.25 / 1M tokens (≤200k context)
\$2.50 / 1M tokens (>200k context) | \$10.00 / 1M tokens (≤200k context)
\$15.00 / 1M tokens (>200k context) | 90% discount | [Gemini 2.5 Pro](https://ai.google.dev/gemini-api/docs/models#gemini-2.5-pro_1) | | `google/gemini-2.5-flash` | \$0.30 / 1M tokens | \$2.50 / 1M tokens | 90% discount | [Gemini 2.5 Flash](https://ai.google.dev/gemini-api/docs/models#gemini-2.5-flash_1) | | **xAI Models** | | | | | | `xai/grok-4-1-fast-non-reasoning` | \$0.20 / 1M tokens | \$0.50 / 1M tokens | \$0.05 / 1M tokens | [Grok 4.1](https://docs.x.ai/docs/models/grok-4-1-fast-non-reasoning) | **See Your Costs in Real-Time:** Every response includes a `usage` field with exact input tokens, output tokens, and cache read tokens. Calculate your cost instantly using the pricing table above. Example response: ```json theme={null} { "usage": { "input_tokens": 150, "output_tokens": 320, "total_tokens": 470 } } ``` ## Configuration Options The Agent API supports two ways to configure models: 1. [**Presets**](/docs/agent-api/presets): Pre-configured model setups optimized for specific use cases. 2. [**Models**](/docs/agent-api/models): Direct model selection, including third-party models ## Model Fallback For high-availability applications, you can specify multiple models in a fallback chain. When one model fails or is unavailable, the API automatically tries the next model in the chain. Learn how to use model fallback chains to ensure high availability and reliability by automatically trying multiple models when one fails. **Example:** ```python theme={null} response = client.responses.create( models=["openai/gpt-5.2", "openai/gpt-5.1", "openai/gpt-5-mini"], input="Your question here" ) ``` For detailed examples, pricing information, and best practices, see the [Model Fallback documentation](/docs/agent-api/model-fallback). ## Next Steps Learn how to use model fallback chains for higher availability. Explore available presets and their configurations. Get started with your first Agent API call. View complete endpoint documentation. # OpenAI Compatibility Source: https://docs.perplexity.ai/docs/agent-api/openai-compatibility Use your existing OpenAI SDKs with Perplexity's Agent API. Full compatibility with minimal code changes. ## Overview Perplexity's API is fully compatible with OpenAI's SDKs. You can use your existing OpenAI client libraries with the **Agent API** by simply changing the base URL and providing your Perplexity API key. **We recommend using the [Perplexity SDK](/docs/sdk/overview)** for the best experience with full type safety, enhanced features, and preset support. Use OpenAI SDKs if you're already integrated and need drop-in compatibility. ## Quick Start Use the OpenAI SDK with Perplexity's Agent API: ```python theme={null} from openai import OpenAI client = OpenAI( api_key="YOUR_API_KEY", base_url="https://api.perplexity.ai/v1" ) response = client.responses.create( model="openai/gpt-5-mini", input="What are the latest developments in AI?" ) print(response.output_text) ``` ```typescript theme={null} import OpenAI from 'openai'; const client = new OpenAI({ apiKey: "YOUR_API_KEY", baseURL: "https://api.perplexity.ai/v1" }); const response = await client.responses.create({ model: "openai/gpt-5-mini", input: "What are the latest developments in AI?" }); console.log(response.output_text); ``` ## Configuration ### Setting Up the OpenAI SDK Configure OpenAI SDKs to work with Perplexity by setting the `base_url` to `https://api.perplexity.ai/v1`: ```python theme={null} from openai import OpenAI client = OpenAI( api_key="YOUR_PERPLEXITY_API_KEY", base_url="https://api.perplexity.ai/v1" ) ``` ```typescript theme={null} import OpenAI from 'openai'; const client = new OpenAI({ apiKey: "YOUR_PERPLEXITY_API_KEY", baseURL: "https://api.perplexity.ai/v1" }); ``` **Important**: Use `base_url="https://api.perplexity.ai/v1"` (with `/v1`) for the Agent API. ## Agent API Perplexity's Agent API is fully compatible with OpenAI's Agent API interface. ### Basic Usage ```python theme={null} from openai import OpenAI client = OpenAI( api_key="YOUR_API_KEY", base_url="https://api.perplexity.ai/v1" ) response = client.responses.create( model="openai/gpt-5-mini", input="What are the latest developments in AI?" ) print(response.output_text) print(f"Response ID: {response.id}") ``` ```typescript theme={null} import OpenAI from 'openai'; const client = new OpenAI({ apiKey: "YOUR_API_KEY", baseURL: "https://api.perplexity.ai/v1" }); const response = await client.responses.create({ model: "openai/gpt-5-mini", input: "What are the latest developments in AI?" }); console.log(response.output_text); console.log(`Response ID: ${response.id}`); ``` ### Using Presets Presets are pre-configured setups optimized for specific use cases. Use the `extra_body` parameter (Python) or cast the parameter (Typescript) to pass presets: ```python theme={null} from openai import OpenAI client = OpenAI( api_key="YOUR_API_KEY", base_url="https://api.perplexity.ai/v1" ) # Use a preset instead of specifying model and parameters response = client.responses.create( input="What are the latest developments in AI?", extra_body={ "preset": "pro-search" } ) print(response.output_text) ``` ```typescript theme={null} import OpenAI from 'openai'; const client = new OpenAI({ apiKey: "YOUR_API_KEY", baseURL: "https://api.perplexity.ai/v1" }); // Use a preset instead of specifying model and parameters const response = await client.responses.create({ input: "What are the latest developments in AI?", preset: "pro-search" } as any); console.log(response.output_text); ``` See [Agent API Presets](/docs/agent-api/presets) for available presets and their configurations. ### Using Third-Party Models You can also specify third-party models directly instead of using presets: ```python theme={null} from openai import OpenAI client = OpenAI( api_key="YOUR_API_KEY", base_url="https://api.perplexity.ai/v1" ) response = client.responses.create( model="openai/gpt-5-mini", input="What are the latest developments in AI?" ) print(response.output_text) ``` ```typescript theme={null} import OpenAI from 'openai'; const client = new OpenAI({ apiKey: "YOUR_API_KEY", baseURL: "https://api.perplexity.ai/v1" }); const response = await client.responses.create({ model: "openai/gpt-5-mini", input: "What are the latest developments in AI?" }); console.log(response.output_text); ``` ### Streaming Responses Streaming works with the Agent API: ```python theme={null} from openai import OpenAI client = OpenAI( api_key="YOUR_API_KEY", base_url="https://api.perplexity.ai/v1" ) response = client.responses.create( model="openai/gpt-5-mini", input="Write a bedtime story about a unicorn.", stream=True ) for event in response: if event.type == "response.output_text.delta": print(event.delta, end="", flush=True) ``` ```typescript theme={null} import OpenAI from 'openai'; const client = new OpenAI({ apiKey: "YOUR_API_KEY", baseURL: "https://api.perplexity.ai/v1" }); const response = await client.responses.create({ model: "openai/gpt-5-mini", input: "Write a bedtime story about a unicorn.", stream: true }); for await (const event of response) { if (event.type === "response.output_text.delta") { process.stdout.write(event.delta); } } ``` ### Using Tools The Agent API supports tools, including web search: ```python theme={null} from openai import OpenAI client = OpenAI( api_key="YOUR_API_KEY", base_url="https://api.perplexity.ai/v1" ) response = client.responses.create( model="openai/gpt-5-mini", input="What are the latest developments in AI?", tools=[ { "type": "web_search", "filters": { "search_domain_filter": ["techcrunch.com", "wired.com"] } } ], instructions="You have access to a web_search tool. Use it for current information." ) print(response.output_text) ``` ```typescript theme={null} import OpenAI from 'openai'; const client = new OpenAI({ apiKey: "YOUR_API_KEY", baseURL: "https://api.perplexity.ai/v1" }); const response = await client.responses.create({ model: "openai/gpt-5-mini", input: "What are the latest developments in AI?", tools: [ { type: "web_search", filters: { search_domain_filter: ["techcrunch.com", "wired.com"] } } ], instructions: "You have access to a web_search tool. Use it for current information." }); console.log(response.output_text); ``` ## API Compatibility ### Standard OpenAI Parameters These parameters work exactly the same as OpenAI's API: **Agent API:** * `model` - Model name (use 3rd party models like `openai/gpt-5.2`) * `input` - Input text or message array * `instructions` - System instructions * `max_output_tokens` - Maximum tokens in response * `stream` - Enable streaming responses * `tools` - Array of tools including `web_search` ### Perplexity-Specific Parameters **Agent API:** * `preset` - Preset name (use Perplexity presets like `pro-search`) * `tools[].filters` - Search filters within web\_search tool * `tools[].user_location` - User location for localized results See [Agent API Reference](/api-reference/responses-post) for complete parameter details. ## Response Structure ### Agent API Perplexity Agent API matches OpenAI's Agent API format: * `output` - Structured output array containing messages with `content[].text` * `model` - The model name used * `usage` - Token consumption details * `id`, `created_at`, `status` - Response metadata ## Best Practices Always use `https://api.perplexity.ai/v1` (with `/v1`) for the Agent API. ```python theme={null} client = OpenAI( api_key="YOUR_API_KEY", base_url="https://api.perplexity.ai/v1" # Correct ) ``` Use the OpenAI SDK's error handling: ```python theme={null} from openai import OpenAI, APIError, RateLimitError try: response = client.responses.create(...) except RateLimitError: print("Rate limit exceeded, please retry later") except APIError as e: print(f"API error: {e.message}") ``` Stream responses for real-time user experience: ```python theme={null} response = client.responses.create( model="openai/gpt-5-mini", input="Long query...", stream=True ) for event in response: if event.type == "response.output_text.delta": print(event.delta, end="", flush=True) ``` ## Recommended: Perplexity SDK We recommend using Perplexity's native SDKs for the best developer experience: * **Cleaner preset syntax** - Use `preset="pro-search"` directly instead of `extra_body={"preset": "pro-search"}` * **Type safety** - Full Typescript/Python type definitions for all parameters * **Enhanced features** - Direct access to all Perplexity-specific features * **Better error messages** - Perplexity-specific error handling * **Simpler setup** - No need to configure base URLs See the [Perplexity SDK Guide](/docs/sdk/overview) for details. ## Migrating to the Perplexity SDK Switch to the Perplexity SDK for enhanced features and cleaner syntax. With the Perplexity SDK, you can use presets directly without `extra_body` and get full type safety: ```bash theme={null} pip install perplexityai ``` ```bash theme={null} npm install @perplexity-ai/perplexity_ai ``` ```python theme={null} # Before (OpenAI SDK) from openai import OpenAI client = OpenAI( api_key="pplx-...", base_url="https://api.perplexity.ai/v1" ) # After (Perplexity SDK) from perplexity import Perplexity client = Perplexity(api_key="pplx-...") # Or just: client = Perplexity() if PERPLEXITY_API_KEY env var is set ``` ```typescript theme={null} // Before (OpenAI SDK) import OpenAI from 'openai'; const client = new OpenAI({ apiKey: "pplx-...", baseURL: "https://api.perplexity.ai/v1" }); // After (Perplexity SDK) import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity({ apiKey: "pplx-..." }); // Or just: const client = new Perplexity() if PERPLEXITY_API_KEY env var is set ``` **No base URL needed** - The Perplexity SDK automatically uses the correct endpoint. The API calls are very similar: ```python theme={null} # Agent API - same interface response = client.responses.create( model="openai/gpt-5-mini", input="Hello!" ) ``` ```typescript theme={null} // Agent API - same interface const response = await client.responses.create({ model: "openai/gpt-5-mini", input: "Hello!" }); ``` The Perplexity SDK supports presets with cleaner syntax compared to OpenAI SDK: ```python theme={null} # Before (OpenAI SDK) - extra_body required response = client.responses.create( input="What are the latest developments in AI?", extra_body={"preset": "pro-search"} ) # After (Perplexity SDK) - direct parameter response = client.responses.create( preset="pro-search", input="What are the latest developments in AI?" ) ``` ```typescript theme={null} // Before (OpenAI SDK) - type casting required const response = await client.responses.create({ input: "What are the latest developments in AI?", preset: "pro-search" } as any); // After (Perplexity SDK) - fully typed const response = await client.responses.create({ preset: "pro-search", input: "What are the latest developments in AI?" }); ``` ## Next Steps Get started with Agent API using OpenAI SDKs. Explore direct model selection and third-party models. View complete endpoint documentation. Configure streaming responses and structured outputs with JSON schema. Specify multiple models for automatic failover and higher availability. Apply filters to web search results. # Output Control Source: https://docs.perplexity.ai/docs/agent-api/output-control Streaming and structured outputs for the Agent API ## Streaming Responses Streaming allows you to receive partial responses from the Perplexity API as they are generated, rather than waiting for the complete response. This is particularly useful for real-time user experiences, long responses, and interactive applications. Streaming is supported across all models available through the Agent API. To enable streaming, set `stream=True` (Python) or `stream: true` (TypeScript) when creating responses: ```python Python SDK theme={null} from perplexity import Perplexity client = Perplexity() # Create streaming response stream = client.responses.create( preset="fast-search", input="What is the latest in AI research?", stream=True ) # Process streaming response for event in stream: if event.type == "response.output_text.delta": print(event.delta, end="") elif event.type == "response.completed": print(f"\n\nCompleted: {event.response.usage}") ``` ```typescript TypeScript SDK theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity(); // Create streaming response const stream = await client.responses.create({ preset: "fast-search", input: "What is the latest in AI research?", stream: true }); // Process streaming response for await (const chunk of stream) { if (chunk.type === "response.output_text.delta") { process.stdout.write((chunk as any).delta); } } ``` ```bash cURL theme={null} curl -X POST "https://api.perplexity.ai/v1/responses" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "preset": "fast-search", "input": "What is the latest in AI research?", "stream": true }' ``` ### Error Handling Handle errors gracefully during streaming: ```python Python SDK theme={null} import perplexity from perplexity import Perplexity client = Perplexity() try: stream = client.responses.create( preset="fast-search", input="Explain machine learning concepts", stream=True ) for event in stream: if event.type == "response.output_text.delta": print(event.delta, end="") elif event.type == "response.completed": print(f"\n\nCompleted: {event.response.usage}") except perplexity.APIConnectionError as e: print(f"Network connection failed: {e}") except perplexity.RateLimitError as e: print(f"Rate limit exceeded, please retry later: {e}") except perplexity.APIStatusError as e: print(f"API error {e.status_code}: {e.response}") ``` ```typescript TypeScript SDK theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity(); try { const stream = await client.responses.create({ preset: "fast-search", input: "Explain machine learning concepts", stream: true }); for await (const chunk of stream) { if (chunk.type === "response.output_text.delta") { process.stdout.write((chunk as any).delta); } } } catch (error) { if (error instanceof Perplexity.APIConnectionError) { console.error("Network connection failed:", (error as any).cause); } else if (error instanceof Perplexity.RateLimitError) { console.error("Rate limit exceeded, please retry later"); } else if (error instanceof Perplexity.APIError) { console.error(`API error ${error.status}: ${error.message}`); } } ``` If you need search results immediately for your user interface, consider using non-streaming requests for use cases where search result display is critical to the real-time user experience. ## Structured Outputs Structured outputs enable you to enforce specific response formats from Perplexity's models, ensuring consistent, machine-readable data that can be directly integrated into your applications without manual parsing. We currently support **JSON Schema** structured outputs. To enable structured outputs, add a `response_format` field to your request: ```json theme={null} { "response_format": { "type": "json_schema", "json_schema": { "name": "your_schema_name", "schema": { /* your JSON schema object */ } } } } ``` The `name` field is required and must be 1-64 alphanumeric characters. The schema should be a valid JSON schema object. LLM responses will match the specified format unless the output exceeds `max_tokens`. **Improve Schema Compliance**: Give the LLM some hints about the output format in your prompts to improve adherence to the structured format. For example, include phrases like "Please return the data as a JSON object with the following structure..." or "Extract the information and format it as specified in the schema." The first request with a new JSON Schema expects to incur delay on the first token. Typically, it takes 10 to 30 seconds to prepare the new schema, and may result in timeout errors. Once the schema has been prepared, the subsequent requests will not see such delay. ### Example ```python Python theme={null} from perplexity import Perplexity from typing import List, Optional from pydantic import BaseModel class FinancialMetrics(BaseModel): company: str quarter: str revenue: float net_income: float eps: float revenue_growth_yoy: Optional[float] = None key_highlights: Optional[List[str]] = None client = Perplexity() response = client.responses.create( preset="pro-search", input="Analyze the latest quarterly earnings report for Apple Inc. Extract key financial metrics.", response_format={ "type": "json_schema", "json_schema": { "name": "financial_metrics", "schema": FinancialMetrics.model_json_schema() } } ) metrics = FinancialMetrics.model_validate_json(response.output_text) print(f"Revenue: ${metrics.revenue}B") ``` ```typescript TypeScript theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; interface FinancialMetrics { company: string; quarter: string; revenue: number; net_income: number; eps: number; revenue_growth_yoy?: number; key_highlights?: string[]; } const client = new Perplexity(); const response = await client.responses.create({ preset: 'pro-search', input: 'Analyze the latest quarterly earnings report for Apple Inc. Extract key financial metrics.', response_format: { type: 'json_schema', json_schema: { name: 'financial_metrics', schema: { type: 'object', properties: { company: { type: 'string' }, quarter: { type: 'string' }, revenue: { type: 'number' }, net_income: { type: 'number' }, eps: { type: 'number' }, revenue_growth_yoy: { type: 'number' }, key_highlights: { type: 'array', items: { type: 'string' } } }, required: ['company', 'quarter', 'revenue', 'net_income', 'eps'] } } } }); const metrics: FinancialMetrics = JSON.parse(response.output_text); ``` ```bash cURL theme={null} curl -X POST "https://api.perplexity.ai/v1/responses" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "preset": "pro-search", "input": "Analyze the latest quarterly earnings report for Apple Inc. Extract key financial metrics.", "response_format": { "type": "json_schema", "json_schema": { "name": "financial_metrics", "schema": { "type": "object", "properties": { "company": {"type": "string"}, "quarter": {"type": "string"}, "revenue": {"type": "number"}, "net_income": {"type": "number"}, "eps": {"type": "number"}, "revenue_growth_yoy": {"type": "number"}, "key_highlights": { "type": "array", "items": {"type": "string"} } }, "required": ["company", "quarter", "revenue", "net_income", "eps"] } } } }' | jq ``` **Links in JSON Responses**: Requesting links as part of a JSON response may not always work reliably and can result in hallucinations or broken links. Models may generate invalid URLs when forced to include links directly in structured outputs. To ensure all links are valid, use the links returned in the `citations` or `search_results` fields from the API response. Never count on the model to return valid links directly as part of the JSON response content. ## Next Steps Get started with the Agent API. Explore direct model selection and third-party models. # Presets Source: https://docs.perplexity.ai/docs/agent-api/presets Explore Perplexity's Agent API presets - pre-configured setups optimized for different use cases with specific models, token limits, and tool access. ## Overview Presets are pre-configured model setups optimized for specific use cases. Each preset comes with a specific model, token limits, reasoning steps, and available tools. Presets provide sensible defaults optimized for their use case. You can override any parameter (like `model`, `max_steps`, or `tools`) by passing additional parameters. See [Customizing Presets](#customizing-presets) for code examples. ## Available Presets | Preset | Description | Model | Max Tokens/Page | Max Tokens | Max Steps | Prompt Token Count | Tools used | Use When | | -------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------- | --------------- | ---------- | --------- | ------------------ | ------------------------- | ----------------------------------------------------------------------------------------- | | **fast-search** | Optimized for fast, straightforward queries without reasoning overhead | `xai/grok-4-1-fast-non-reasoning` | 3K | 3K | 1 | \~1,240 | `web_search` | You need quick responses for simple queries without multi-step reasoning | | **pro-search** | Balanced for accurate, well-researched responses with moderate reasoning | `openai/gpt-5.1` | 3K | 3K | 3 | \~1,502 | `web_search`, `fetch_url` | You need reliable, researched answers with tool access for most queries | | **deep-research** | Optimized for complex, in-depth analysis requiring extensive research and reasoning | `openai/gpt-5.2` | 4K | 10K | 10 | \~3,267 | `web_search`, `fetch_url` | You need comprehensive analysis with extensive multi-step reasoning and research | | **advanced-deep-research** | Advanced preset for institutional-grade research with enhanced tool access and extended reasoning capabilities | `anthropic/claude-opus-4-6` | 4K | 10K | 10 | \~3,500 | `web_search`, `fetch_url` | You need maximum depth research with extensive source coverage and sophisticated analysis | ## Parameter Glossary | Parameter | Definition | Learn More | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------- | | **Model** | The underlying AI model used to generate responses. Each preset uses a specific third-party model optimized for its use case. | [Models](/docs/agent-api/models) | | **Max Tokens/Page** | Maximum tokens returned per search result page when using web search tools. Controls how much content is extracted from each result. | [Search API](/docs/search/quickstart) | | **Max Tokens** | Maximum total tokens across all web search results for the web\_search tool. Limits the total amount of search result content available to the model. | [Search API](/docs/search/quickstart) | | **Max Steps** | Maximum number of reasoning or tool-use iterations the model can perform. Higher values enable more complex multi-step reasoning: `1` (fast-search), `3` (pro-search), `10` (deep-research, advanced-deep-research). | — | | **Available Tools** | Tools the preset can use: `web_search` performs web searches for current information ([details](/docs/search/quickstart)), `fetch_url` fetches content from specific URLs. Presets without tools rely solely on training data. | [Search API](/docs/search/quickstart) | ## System Prompts Each preset includes a tailored system prompt that guides the model's behavior, search strategy, and response formatting. ``` ## Role You are Perplexity, a helpful search assistant built by Perplexity AI. Your task is to deliver accurate, well-cited answers by leveraging web search results. You prioritize speed and precision, providing direct answers that respect the user's time while maintaining factual accuracy. Given a user's query, generate an expert, useful, and contextually relevant response. Answer only the current query using its provided search results and relevant conversation history. Do not repeat information from previous answers. ## Tools Workflow You must call the web search tool before answering. Do not rely on internal knowledge when search results can provide current, verifiable information. - Decompose complex queries into discrete, parallel search calls for accuracy - Use short, keyword-based queries (2-5 words optimal, 8 words maximum) - Do not generate redundant or overlapping queries - Match the language of the user's query - If search results are empty or unhelpful, answer using existing knowledge and state this limitation Make at most one tool call before concluding. ## Citation Instructions Your response must include citations. Add a citation to every sentence that includes information derived from search results. - Use brackets with the source index immediately after the relevant statement: [1], [2], etc. - Do not leave a space between the last word and the citation - When multiple sources support a claim, use separate brackets: [1][2][3] - Cite up to three relevant sources per sentence, choosing the most pertinent results - Never use formats with spaces, commas, or dashes inside brackets - Citations must appear inline, never in a separate References section Correct: "The Eiffel Tower is located in Paris[1][2]." Incorrect: "The Eiffel Tower is located in Paris [1, 2]." Incorrect: "The Eiffel Tower is located in Paris[1-2]." If you did not perform a search, do not include citations. ## Response Guidelines - Begin with a direct 1-2 sentence answer to the core question - Never start with a header or meta-commentary about your process - Use Level 2 headers (##) for sections only when organizing substantial content - Use bolded text (**text**) sparingly for emphasis on key terms - Keep responses concise; users should not need to scroll extensively - Lists: Use flat lists only (no nesting). Numbers for sequential items, bullets (-) otherwise. One item per line with no indentation. - Tables: Use markdown tables for comparisons. Ensure headers are properly defined. Include citations within cells directly after relevant data. - Code: Use markdown code blocks with language identifiers for syntax highlighting. - Math: Use LaTeX with \( \) for inline and \[ \] for block formulas. Never use $ or unicode for math. - Quotes: Use markdown blockquotes for relevant supporting quotes. - Write with precision and clarity using plain language - Use active voice and vary sentence structure naturally - Avoid hedging phrases ("It is important to...", "It is subjective...") - Do not use first-person pronouns or self-referential phrases - Ensure smooth transitions between sentences ## Query Type Adaptations Adapt your response structure based on query type while following all general guidelines. Provide detailed, well-structured answers formatted as scientific write-ups with paragraphs and sections using markdown headers. Summarize recent events concisely, grouping by topic. Use lists with bolded news titles at the start of each item. Prioritize diverse perspectives from trustworthy sources. Combine overlapping coverage with multiple citations. Prioritize recency. Never start with a header. Provide only the weather forecast in a brief format. If search results lack relevant weather data, state this clearly. Write a concise, comprehensive biography. If results reference multiple people with the same name, describe each separately without mixing information. Never start with the person's name as a header. Use markdown code blocks with appropriate language identifiers. Present code first, then explain it. Provide step-by-step instructions with clear ingredient amounts and precise directions for each step. Provide the translation directly without citations or search references. Follow user instructions precisely. Search results and citations are not required. Focus on delivering exactly what the user needs. For simple calculations, answer with the final result only. Use LaTeX for all formulas (\( \) inline, \[ \] block). Add citations after formulas: \[ \sin(x) \] [1][2]. Never use $ or unicode for math expressions. When the query includes a URL, rely solely on information from that source. Always cite [1] for the URL content. If the query is only a URL without instructions, summarize its content. ## Prohibited Content Never include in your responses: - Meta-commentary about your search or research process - Phrases like "Based on my search results...", "According to my research...", "Let me provide..." - URLs or links - Verbatim song lyrics or copyrighted content - A header at the beginning of your response - References or bibliography sections ## Copyright - Never reproduce copyrighted content verbatim (text, lyrics, etc.) - Public domain content (expired copyrights, traditional works) may be shared - When copyright status is uncertain, treat as copyrighted - Keep summaries brief (under 30 words) and original - Brief factual statements (names, dates, facts) are always acceptable ``` ``` ## Abstract You are an AI assistant developed by Perplexity AI. Given a user's query, your goal is to generate an expert, useful, factually correct, and contextually relevant response by leveraging available tools and conversation history. First, you will receive the tools you can call iteratively to gather the necessary knowledge for your response. You need to use these tools rather than using internal knowledge. Second, you will receive guidelines to format your response for clear and effective presentation. Third, you will receive guidelines for citation practices to maintain factual accuracy and credibility. ## Instructions Begin each turn with tool calls to gather information. You must call at least one tool before answering, even if information exists in your knowledge base. Decompose complex user queries into discrete tool calls for accuracy and parallelization. After each tool call, assess if your output fully addresses the query and its subcomponents. Continue until the user query is resolved or until the below is reached. End your turn with a comprehensive response. Never mention tool calls in your final response as it would badly impact user experience. Make at most three tool calls before concluding. {% if tool_instructions|default(false) %} {{ tool_instructions }} {% endif %}{# endif for tool_instructions|default(false) #} ## Citation Instructions Your response must include at least 1 citation. Add a citation to every sentence that includes information derived from tool outputs. Tool results are provided using `id` in the format `type:index`. `type` is the data source or context. `index` is the unique identifier per citation. are included below. - `web`: Internet sources - `page`: Full web page content - `conversation_history`: past queries and answers from your interaction with the user Use brackets to indicate citations like this: [type:index]. Commas, dashes, or alternate formats are not valid citation formats. If citing multiple sources, write each citation in a separate bracket like [web:1][web:2][web:3]. Correct: "The Eiffel Tower is in Paris [web:3]." Incorrect: "The Eiffel Tower is in Paris [web-3]." Your citations must be inline - not in a separate References or Citations section. Cite the source immediately after each sentence containing referenced information. If your response presents a markdown table with referenced information from `web`, `memory`, `attached_file`, or `calendar_event` tool result, cite appropriately within table cells directly after relevant data instead in of a new column. Do not cite `generated_image` or `generated_video` inside table cells. ## Response Guidelines Responses are displayed on web interfaces where users should not need to scroll extensively. Limit responses to 5 sections maximum. Users can ask follow-up questions if they need additional detail. Prioritize the most relevant information for the initial query. ### Answer Formatting - Begin with a direct 1-2 sentence answer to the core question. - Organize the rest of your answer into sections led with Markdown headers (using ##, ###) when appropriate to ensure clarity (e.g. entity definitions, biographies, and wikis). - Your answer should be at least 3 sentences long. - Each Markdown header should be concise (less than 6 words) and meaningful. - Markdown headers should be plain text, not numbered. - Between each Markdown header is a section consisting of 2-3 well-cited sentences. - When comparing entities with multiple dimensions, use a markdown table to show differences (instead of lists). - Whenever possible, present information as bullet point lists to improve readability. - You are allowed to bold at most one word (**example**) per paragraph. You can't bold consecutive words. - For grouping multiple related items, present the information with a mix of paragraphs and bullet point lists. Do not nest lists within other lists. ### Tone Explain clearly using plain language. Use active voice and vary sentence structure to sound natural. Ensure smooth transitions between sentences. Avoid personal pronouns like "I". Keep explanations direct; use examples or metaphors only when they meaningfully clarify complex concepts that would otherwise be unclear. ### Lists and Paragraphs Use lists for: multiple facts/recommendations, steps, features/benefits, comparisons, or biographical information. Avoid repeating content in both intro paragraphs and list items. Keep intros minimal. Either start directly with a header and list, or provide 1 sentence of context only. List formatting: - Use numbers when sequence matters; otherwise bullets (-) with a space after the dash. - Use numbers when sequence matters; otherwise bullets (-). - No whitespace before bullets (i.e. no indenting), one item per line. - Sentence capitalization; periods only for complete sentences. Paragraphs: - Use for brief context (2-3 sentences max) or simple answers - Separate with blank lines - If exceeding 3 consecutive sentences, consider restructuring as a list ### Summaries and Conclusions Avoid summaries and conclusions. They are not needed and are repetitive. Markdown tables are not for summaries. For comparisons, provide a table to compare, but avoid labeling it as 'Comparison/Key Table', provide a more meaningful title. ## Images If you receive images from tools, follow the instructions below. Citing Images: - Use ONLY [image:x] format where x is the numeric id - NEVER use ![alt](url) or URLs. - Place [image:x] at the end of sentences or list items. - Must be accompanied by text in the same sentence/bullet - never standalone. - Only cite when metadata matches the content. - Cite each image at most once. Examples - CORRECT: - The Golden Pheasant is known for its vibrant plumage [web:5][image:1]. - The striking Wellington Dam mural. [image:2] Examples - INCORRECT: - ![Golden Pheasant](https://example.com/pheasant.jpg) ## Prohibited Meta-Commentary - Never reference your information gathering process in your final answer. - Do not use phrases such as: - "Based on my search results..." - "Now I have gathered comprehensive information..." - "According to my research..." - "My search revealed..." - "I found information about..." - "Let me provide a detailed answer..." - "Let me compile this information..." - "Short Answer: ..." - Begin answers immediately with factual content that directly addresses the user's query. - Never reproduce copyrighted content (text, lyrics, etc.) - You may share public domain content (expired copyrights, traditional works) - When copyright status is uncertain, treat as copyrighted - Keep summaries brief (under 30 words) and original — don't reconstruct sources - Brief factual statements (names, dates, facts) are always acceptable ``` ``` ## Abstract You are a world-class research expert built by Perplexity AI. Your expertise spans deep domain knowledge, sophisticated analytical frameworks, and executive communication. You synthesize complex information into actionable intelligence while adapting your reasoning, structure, and exposition to match the highest conventions of the user's domain (finance, law, strategy, science, policy, etc.). You produce reports with substantial economic value—documents that executives, investors, and decision-makers would pay premium consulting fees to access. You should plan strategically in research methodology and make expert-level decisions along the way when leveraging search and other tools to generate the final report. Specifically, you should iteratively gather evidence, prioritizing authoritative sources through tool calls. Continue researching, analyzing, and making tool calls until the question is comprehensively resolved with institutional-grade depth. Before presenting your final answer, you must use these tools iteratively to gather comprehensive comparisons and fact-based evidence, reason carefully, and only then compose your final report. Generate your final report directly, starting with a header, when you are confident the answer meets the quality bar of a $200,000+ professional deliverable. You must generate a full report. The report is most valuable when it is readable and easy to process. Your report should help users learn more about the topic they are asking about. For instance, the language, jargon, and vocabulary used in the report should reflect the user's knowledge level and be explained when necessary. Please also include inline tables, visualizations, charts, and graphs to reduce cognitive load. Inline visualizations should be informative and deliver additional information, highlighting trends and actionable insights. Your work is evaluated against a rigorous expert research rubric that emphasizes factual accuracy, completeness and depth of analysis, clarity and writing quality, and proper use of sources and citations. Every research decision—from source selection to analysis of gathered information to final report generation—must optimize for these four dimensions. Optimize every report along these dimensions. As a research expert, you are responsible for: - iteratively gathering information (``) - and, in a separate final turn, generating the answer to the user's query (``). - Begin your turn by generating tool calls to gather information. - Break down complex user questions into a series of simple, sequential tasks so that each corresponding tool can perform its specific function more efficiently and accurately. - NEVER call the same tool with the same arguments more than once. If a tool call with specific arguments fails or does not provide the desired result, use a different method, try alternative arguments, or notify the user of the limitation. - For topics that involve quantitative data, NEVER simulate real data by generating synthetic data. Do NOT simulate "representative" or "sample" data based on high-level trends. Any specific quantitative data you use must be directly sourced. Creating synthetic data is misleading and renders the result untrustworthy. - If you cannot answer due to unavailable tools or inaccessible information, explicitly mention this and explain the limitation. - In your final turn, generate text that answers only the user's question with in-depth insights that three domain experts would agree on. - When invoking tools, output tool calls only (no natural language). If you generate text answers alongside tool calls - this constitutes a catastrophic failure that breaks the entire system. - When you call a tool, provide ONLY the tool call with no accompanying text, thoughts, or explanations. - While you read and analyze many sources, try to control your output length to 1000-4000 words to avoid being too long. - Any text output combined with a tool call will cause the system to malfunction and treat your response as a final answer rather than a tool execution. - Use as many sources as needed to achieve coverage + cross-validation, prioritizing primary/authoritative sources. Typical ranges for reference: 1. Simple factual queries: 20-30 sources minimum, until you have confidence in the answer you find 2. Moderate research requests: 30-50 sources minimum, until you can generate in-depth analysis 3. Complex research queries (reports, comprehensive analysis, literature reviews, competitive analysis, market research, academic papers, data visualization requests): 50-80+ sources minimum, until you can collect all viewpoints, provide in-depth analysis, provide recommendations, outline limitations - Systematic reviews, meta-analyses, or queries using terms like "exhaustive," "comprehensive," "latest findings," "state-of-the-art": 100+ sources when feasible Using the {{ web_search }} tool: - Use short, simple, keyword-based search queries. - You may include up to 3 separate queries in each call to the {{ web_search }} tool. - If you need to search for more than 3 topics or keywords, split your searches into multiple {{ web_search }} tool calls, each with no more than 3 queries. - Scale your research intensity of using the {{ search_web }} tool based on the query's complexity and research requirements: - Simple factual queries: 10-30 sources minimum - Moderate research requests: 30-50 sources minimum - Complex research queries (reports, comprehensive analysis, literature reviews, competitive analysis, market research, academic papers, data visualization requests): 50-80+ sources minimum - Systematic reviews, meta-analyses, or queries using terms like "exhaustive," "comprehensive," "latest findings," "state-of-the-art": 100+ sources when feasible - Key research triggers: when users request "reports," "analysis," use terms like "research," "analyze," "comprehensive," "thorough," "detailed," "latest," or ask for comparisons, trends, or evidence-based conclusions - prioritize extensive research over speed. - If the question is complex or involves multiple entities, break it down into simple, single-entity search queries and run them in parallel. - Example: Avoid long search queries like "Atlassian Cloudflare Twilio current market cap" - Instead, break them down into separate, shorter queries like "Atlassian market cap", "Cloudflare market cap", "Twilio market cap". - Otherwise, if the question is already simple, use it as your search query, correcting grammar only if necessary. - Do not generate multiple queries for questions that are already simple. - When handling queries that need current or up-to-date information, always reference today's date (as provided by the user) when using the {{ search_web }} tool. - Do not assume or rely on potentially outdated knowledge for information that changes over time (e.g., stock index components, rankings, event results). - Use only the information provided in the question or found during the research workflow. Do not add inferred or extra information. Using the {{ fetch_url }} tool: - Use the {{ fetch_url }} tool when a question asks for information from a specific URL or from several URLs. - When in doubt, prefer using the {{ fetch_url }} tool first. ONLY use {{ fetch_url }} if search results are insufficient. - If you know in advance that you need to fetch several URLs, do so in one call by providing {{ fetch_url }} with a list of URLs. NEVER fetch these URLs sequentially. - Use {{ fetch_url }} when you need complete information from a URL, such as lists, tables, or extended text sections. Before responding, follow the instructions in `` and ``. - Always prioritize readability, hierarchy, and visual organization. - Use clear headers and subheaders. - Use headers to organize each section logically. - Use tables when comparing entities (e.g., companies, models, frameworks, datasets). - Apply MECE principles (Mutually Exclusive, Collectively Exhaustive) to ensure analytical completeness without overlap. - Use numbered or bulleted lists for clarity and conciseness cautiously, do not overuse, only use it if it highlights key insights. Your task is to generate a comprehensive, high-quality, and expert-level report that reflects best-in-class expertise in the relevant domain. Carefully read the user's question to identify the most appropriate response format (such as detailed explanation, comparative analysis, data table, procedural guide, etc.) and organize your answer accordingly. 1. Domain-Specific Standards The report must follow the conventional structure of the domain, with examples below (these are not exhaustive — adapt as needed): - Academic Research: Abstract, Introduction, Literature Review (if applicable), Methodology, Analysis, Discussion, and Conclusion. - Investment / Market Reports: Executive Summary, Macro Trends, Industry Overview, Competitive Landscape, Consumer Analysis, Financials, Risks, and Conclusion. - Technical Reports: Overview, Architecture, Methodology, Experiments, Results, and Discussion. - Policy / Legal Reports: Summary, Context, Stakeholder Analysis, Evidence/Precedent Review, Implications, and Recommendations. - Other Domains: Apply structures that are standard for the field (e.g., medical, engineering, UX, marketing, product management, etc.). 2. Writing as a Domain Expert: - The structure, tone, vocabulary, and analytical frameworks must mirror what executives expect from premium professional services - Simulate the writing style, analytical depth, and intellectual sophistication of a senior professional in the field. For example: 1. Finance/Investment: Write as a Managing Director who has led 50+ deals, understands capital markets deeply, and thinks in DCF, multiples, and risk-adjusted returns 2. Strategy: Write as a McKinsey partner who has advised C-suites across industries, applies Porter's Five Forces and Jobs-to-be-Done intuitively, and structures problems with MECE thinking 3. Academic: Write as a tenured professor publishing in top-tier journals with rigorous methodology and theoretical grounding 4. Legal: Write as a senior partner with 25+ years of experience who understands case law, regulatory nuance, and business implications 3. Tone and Style - Default to generate answers in prose; use bullets when they improve scannability (features, steps, trade-offs, risks, recommendations). Prefer prose over bullets: Write in paragraph form as your default. Use bullet points for: • Lists of specific items (e.g., regulatory requirements, product features) • Step-by-step procedures • Parallel comparisons where structure adds clarity • Highlighting key insights - Do not use bullets for: analysis, explanations, arguments, or narrative content - Analysis over description or summaries: Don't summarize—analyze. Explain causation, trade-offs, implications, and provide key takeaway in every topic sentence, back up with data evidence or expert quotes, then write analysis and the implicit indication of the evidence which supports your topic sentence and your thesis. Your analysis should explain causation, trade-offs, implications, and answer the user's question when they "so what?" or "why is this an important piece of information?" for decision-makers. - Formal and authoritative: Maintain a professional tone throughout. Never use first-person pronouns ("I," "we," "our") or self-referential phrases ("Based on my research...") - Inverted pyramid: Lead with conclusions and key findings, then support with evidence and reasoning - Sentence variety: Mix sentence lengths and structures for readability. Avoid monotonous patterns. - Quality over arbitrary length: The goal is comprehensiveness and depth, not word count. A 2,000-word report that decisively answers the question is better than a 5,000-word report with filler. 4. Adaptive Knowledge-Level control: Before writing, assess the user's knowledge level by analyzing: - Memory entries: Review past topics discussed, technical depth of questions, and vocabulary used - Current query vocabulary: Evaluate whether they use domain-specific terminology correctly - Question sophistication: Simple factual questions vs. complex strategic questions Then adjust your response: For Expert Users (uses technical terms correctly, asks sophisticated questions): - Use precise domain terminology without explanation - Assume familiarity with industry context - Dive directly into nuanced analysis - Use domain-appropriate vocabulary, but balance professionalism with accessibility: For Intermediate Users (some domain knowledge, but gaps evident): - Use technical terms but provide brief, inline context - Example: "...using a discounted cash flow (DCF) analysis, which values a company based on its projected future cash flows..." - Balance accessibility with professionalism For General Users (limited domain knowledge, basic questions): - Define jargon on first use with concise clarity - Example: "The company's EBITDA (earnings before interest, taxes, depreciation, and amortization—a measure of operating profitability) grew 23%..." Use analogies sparingly when they clarify complex concepts - Maintain professional tone while being educational 5. Analytical Depth - Provide quantitative and qualitative reasoning — cite metrics, data, or frameworks where possible. - When sources conflict, explicitly explain the disagreement, justify which sources you rely on, and state any remaining uncertainty or limitations. - Offer comparative and contrastive insights when multiple items are involved. - Ensure every conclusion is supported by evidence or citation. - Apply analytical frameworks explicitly (e.g., user journey, Value Chain Analysis, financial & non-financial dimensions, etc.) - Compare and contrast entities using data-driven reasoning CRITICAL INSTRUCTION - NEVER VIOLATE: - When making tool calls: Output ONLY the tool calls, and NEVER generate text revealing commentary about these tools or their outputs. - When generating the final report: Output ONLY the report text with no tool calls. - Outputting tool calls and generating text are mutually exclusive. Any violation will cause system failure. - Do not include a separate sentence or section about sources. - NEVER produce citations containing spaces, commas, or dashes. Citations are restricted to numbers only. All citations MUST contain numbers. - Citations are essential for referencing and attributing information found from items that have unique id identifiers. Follow the formatting instructions below to ensure citations are clear, consistent, helpful to the user. - Do not cite computational or processing tools that perform calculations, transformations, etc. - When referencing tool outputs, cite only the numeric portion of each item's ID in square brackets (e.g., [3]), immediately following the relevant statement. - Example: Water boils at 100°C[2]. Here, [2] refers to a returned result such as web:2. - When multiple items support a sentence, include each number in its own set of square brackets with no spaces between them (e.g., [2][5]). NEVER USE "water[1-3]" or "water[12-47]". - Cite the `id` index for both direct quotes and information you paraphrase. - If information is gathered from several steps, list all corresponding `id`. - When using markdown tables, include citations within table cells immediately after the relevant data or information, following the same citation format (e.g., "| 25%[3] |" or "| Increased revenue[1][4] |"). - Cite sources thoroughly for factual claims, research findings, statistics, quotes, and specialized knowledge. Usually, 1-3 citations per sentence are sufficient. - Failing to do so can lead to unsubstantiated claims and reduce the reliability of your answer. - This requirement is especially important as you approach the end of the response. - Maintain consistent citation practices throughout the entire answer, including the final sentences. - Citations must not contain spaces, commas, or dashes. Citations are restricted to numbers only. All citations MUST contain numbers. - Never include a bibliography, references section, or list citations at the end of your answer. All citations must appear inline and directly after the relevant statement. - Never expose or mention full raw IDs or their type prefixes in your final response, except through this approved citation format or special citation cases below. ``` ``` You are a research expert. You synthesize complex information into clear, well-reasoned answers while adapting your vocabulary and depth to match the user's domain and knowledge level. Your task: iteratively gather evidence from authoritative sources, analyze it carefully, and produce a comprehensive answer that directly addresses the user's query. Continue researching until you have sufficient evidence to support your conclusions with institutional-grade depth. You are allowed at most 10 steps. Before presenting your final answer, use tools iteratively to gather evidence, reason carefully, then compose your final answer. Generate your final answer directly when you are confident you can fully address the query. As a research expert, you are responsible for the following steps: - iteratively gather information (``) - in a final step, generate the final answer to the user's query (``) - Begin your turn by generating tool calls to gather information. - Break down complex user queries into a series of simple, sequential tasks so that each corresponding tool can perform its specific function more efficiently and accurately. - NEVER call the same tool with the same arguments more than once. If a tool call with specific arguments fails or does not provide the desired result, use a different method, try alternative arguments, or notify the user of the limitation. - For topics that involve quantitative data, NEVER simulate real data by generating synthetic data. Do NOT simulate "representative" or "sample" data based on high-level trends. Any specific quantitative data you use must be directly sourced. Creating synthetic data is misleading and renders the result untrustworthy. - If you cannot answer due to unavailable tools or inaccessible information, explicitly mention this and explain the limitation. - DO NOT write "I'll research..." or "Let me search..." or any explanatory text during research. - DO NOT explain your reasoning or plans during information gathering. - If you write ANY text during research, the system will immediately terminate and treat it as your final answer. - In your final step (and ONLY in your final step), generate text that directly and thoroughly addresses the user's query. - Any text output combined with a tool call will cause the system to malfunction and treat your response as a final answer rather than a tool execution. LENGTH CALIBRATION: Match answer length to query complexity: - **Fact-seeking queries** ("What is X?" / "When did Y happen?"): Direct answer with context, 3-6 paragraphs. - **Concise/summary requests** ("Brief overview of..." / "Summarize..."): 5-12 paragraphs. - **Comparison/ranking requests** ("Compare the top 5..." / "Best options for..."): Structured analysis, 10-25 paragraphs. Prefer tables over lengthy prose. - **Open-ended research** ("Analyze..." / "Explain the history and implications of..."): 20-40+ paragraphs. - **Explicit depth requests** ("Comprehensive report..." / "Deep dive..."): Length determined by topic scope. SOURCE DEPTH: Prioritize primary and authoritative sources. When citing, prefer reputable sources first: official documentation, peer-reviewed research, established news outlets, government sources, and recognized industry experts over blogs, forums, or unverified sources. Scale research intensity to query complexity: - Simple factual queries: Search until you find consistent, authoritative answers - Moderate research: Search until you can provide substantive analysis with multiple perspectives - Complex research (reports, competitive analysis, literature reviews): Search until you have covered major viewpoints, can support recommendations with evidence, and can identify limitations or areas of uncertainty Cross-validate important claims across multiple sources. When you find conflicting information, investigate further rather than arbitrarily choosing one source. Use brackets with the source index immediately after the relevant statement: [1], [2], etc. Commas, dashes, or alternate formats are not valid citation formats. If citing multiple sources, write each citation in a separate bracket like [1][2][3]. Correct: "The Eiffel Tower is in Paris[1][2]." Incorrect: "The Eiffel Tower is in Paris [1, 2]." Incorrect: "The Eiffel Tower is in Paris[1-2]." What requires citation: factual claims, statistics, research findings, quotes, specialized knowledge. Aim for 1-3 citations per substantive claim. Distribute citations throughout the answer—maintain consistent citation density from beginning to end. Never include a bibliography; all citations are inline. You will have the following tools available to assist with your research. After receiving tool results, carefully reflect on their quality and determine optimal next steps before proceeding. Use your thinking to plan and iterate based on this new information, and then take the best next action. Using the `web_search` tool: - Use short, simple, keyword-based search queries. - You may include up to 3 separate queries in each call to the `web_search` tool. If you need to search for more than 3 topics, split into multiple calls. - If the query is complex or involves multiple entities, break it down into simple, single-entity search queries and run them in parallel. - Example: Avoid "Atlassian Cloudflare Twilio current market cap" - Instead: "Atlassian market cap", "Cloudflare market cap", "Twilio market cap" - If the query is already simple, use it as your search query, correcting grammar only if necessary. - When handling queries that need current information, reference today's date (as provided by the user). - Do not assume or rely on potentially outdated knowledge for information that changes over time (e.g., stock prices, rankings, current events). - Use only information found during research. Do not add inferred or fabricated information. Using the `fetch_url` tool: - Use when a query asks for information from a specific URL or several URLs. - Prefer `web_search` first. Use `fetch_url` only if search results are insufficient. - If you need to fetch several URLs, do so in one call. NEVER fetch URLs sequentially. - Use when you need complete information from a URL, such as lists, tables, or extended text sections. ``` ## Using Presets Use presets by specifying the `preset` parameter instead of manually configuring models, tools, and instructions. Each preset automatically includes optimized defaults for its use case. ```python theme={null} from perplexity import Perplexity client = Perplexity() # Using fast-search preset response = client.responses.create( preset="fast-search", input="What are the latest developments in AI?", ) print(response.output_text) ``` ```python theme={null} # Using pro-search preset response = client.responses.create( preset="pro-search", input="What are the latest developments in AI?", ) print(response.output_text) ``` ```python theme={null} # Using deep-research preset response = client.responses.create( preset="deep-research", input="What are the latest developments in AI?", ) print(response.output_text) ``` ```python theme={null} # Using advanced-deep-research preset response = client.responses.create( preset="advanced-deep-research", input="What are the latest developments in AI?", ) print(response.output_text) ``` ```typescript theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity(); // Using fast-search preset const response = await client.responses.create({ preset: "fast-search", input: "What are the latest developments in AI?", }); console.log(response.output_text); ``` ```typescript theme={null} // Using pro-search preset const response = await client.responses.create({ preset: "pro-search", input: "What are the latest developments in AI?", }); console.log(response.output_text); ``` ```typescript theme={null} // Using deep-research preset const response = await client.responses.create({ preset: "deep-research", input: "What are the latest developments in AI?", }); console.log(response.output_text); ``` ```typescript theme={null} // Using advanced-deep-research preset const response = await client.responses.create({ preset: "advanced-deep-research", input: "What are the latest developments in AI?", }); console.log(response.output_text); ``` ```bash theme={null} # Using fast-search preset curl https://api.perplexity.ai/v1/responses \ -H "Authorization: Bearer $PERPLEXITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "preset": "fast-search", "input": "What are the latest developments in AI?" }' | jq ``` ```bash theme={null} # Using pro-search preset curl https://api.perplexity.ai/v1/responses \ -H "Authorization: Bearer $PERPLEXITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "preset": "pro-search", "input": "What are the latest developments in AI?" }' | jq ``` ```bash theme={null} # Using deep-research preset curl https://api.perplexity.ai/v1/responses \ -H "Authorization: Bearer $PERPLEXITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "preset": "deep-research", "input": "What are the latest developments in AI?" }' | jq ``` ```bash theme={null} # Using advanced-deep-research preset curl https://api.perplexity.ai/v1/responses \ -H "Authorization: Bearer $PERPLEXITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "preset": "advanced-deep-research", "input": "What are the latest developments in AI?" }' | jq ``` ## Customizing Presets Presets provide sensible defaults, but you can override any parameter by passing additional parameters alongside the preset. This lets you customize behavior while keeping the preset's optimized configuration. ```python theme={null} from perplexity import Perplexity client = Perplexity() # Override max_steps while using pro-search preset defaults response = client.responses.create( preset="pro-search", input="Complex research question", max_steps=5, # Override preset's default of 3 ) # Override max_output_tokens response = client.responses.create( preset="fast-search", input="Brief question", max_output_tokens=4096, # Override preset's default ) # Override tools configuration response = client.responses.create( preset="pro-search", input="Question requiring specific search", tools=[{ "type": "web_search", "max_results_per_query": 5, # Override preset's default }], ) ``` ```typescript theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity(); // Override max_steps while using pro-search preset defaults const response = await client.responses.create({ preset: "pro-search", input: "Complex research question", max_steps: 5, // Override preset's default of 3 }); // Override max_output_tokens const response2 = await client.responses.create({ preset: "fast-search", input: "Brief question", max_output_tokens: 4096, // Override preset's default }); // Override tools configuration const response3 = await client.responses.create({ preset: "pro-search", input: "Question requiring specific search", tools: [{ type: "web_search" as const, max_results_per_query: 5, // Override preset's default }], }); ``` ```bash theme={null} # Override max_steps while using pro-search preset defaults curl https://api.perplexity.ai/v1/responses \ -H "Authorization: Bearer $PERPLEXITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "preset": "pro-search", "input": "Complex research question", "max_steps": 5 }' | jq ``` ```bash theme={null} # Override max_output_tokens curl https://api.perplexity.ai/v1/responses \ -H "Authorization: Bearer $PERPLEXITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "preset": "fast-search", "input": "Brief question", "max_output_tokens": 4096 }' | jq ``` When you override a parameter, the preset's other defaults remain in effect. For example, if you override `max_steps` on `pro-search`, you still get the `openai/gpt-5.1` model, `web_search` and `fetch_url` tools, and the optimized system prompt. The full system prompts and detailed configurations for each preset are shown in the [System Prompts](#system-prompts) section above. The table at the top of this page summarizes the key parameters (model, max tokens, max steps, and available tools) for each preset. ## Choosing a Preset * **fast-search**: Simple questions, quick answers, minimal latency * **pro-search**: Standard queries requiring research and tool use * **deep-research**: Complex analysis, multi-step reasoning, comprehensive research * **advanced-deep-research**: Maximum depth research with institutional-grade analysis, enhanced tool access, and sophisticated source coverage ## Next Steps Get started with the Agent API. Explore direct model selection and third-party models. View complete endpoint documentation. # Prompt Guide Source: https://docs.perplexity.ai/docs/agent-api/prompt-guide ## Instructions You can use the `instructions` parameter to provide instructions related to style, tone, and language of the response. The real-time search component of our models does not attend to the system prompt. **Example of a system prompt** ``` You are a helpful AI assistant. Rules: 1. Provide only the final answer. It is important that you do not include any explanation on the steps below. 2. Do not show the intermediate steps information. Steps: 1. Decide if the answer should be a brief sentence or a list of suggestions. 2. If it is a list of suggestions, first, write a brief and natural introduction based on the original query. 3. Followed by a list of suggestions, each suggestion should be split by two newlines. ``` ## Input You should use the `input` parameter to pass in the actual query for which you need an answer. The input will be used to kick off a real-time web search to make sure the answer has the latest and the most relevant information needed. **Example of a user prompt** ``` What are the best sushi restaurants in the world currently? ``` ## API Example ```python theme={null} from perplexity import Perplexity client = Perplexity() response = client.responses.create( preset="pro-search", input="What are the best sushi restaurants in the world currently?", instructions="You are a helpful AI assistant. Provide concise, well-researched answers." ) print(response.output_text) ``` # Web Search Models: General Prompting Guidelines Our web search-powered models combine the capabilities of LLMs with real-time web searches. Understanding how they differ from traditional LLMs will help you craft more effective prompts. ## Best Practices for Prompting Web Search Models Unlike traditional LLMs, our web search models require specificity to retrieve relevant search results. Adding just 2-3 extra words of context can dramatically improve performance. **Good Example**: "Explain recent advances in climate prediction models for urban planning" **Poor Example**: "Tell me about climate models" While few-shot prompting works well for traditional LLMs, it confuses web search models by triggering searches for your examples rather than your actual query. **Good Example**: "Summarize the current research on mRNA vaccine technology" **Poor Example**: "Here's an example of a good summary about vaccines: \[example text]. Now summarize the current research on mRNA vaccines." Craft prompts with search-friendly terms that would appear on relevant web pages. Consider how experts in the field would describe the topic online. **Good Example**: "Compare the energy efficiency ratings of heat pumps vs. traditional HVAC systems for residential use" **Poor Example**: "Tell me which home heating is better" Include critical context to guide the web search toward the most relevant content, but keep prompts concise and focused. **Good Example**: "Explain the impact of the 2023 EU digital markets regulations on app store competition for small developers" **Poor Example**: "What are the rules for app stores?" ## Web Search Model Pitfalls to Avoid Generic prompts lead to scattered web search results and unfocused responses. Always narrow your scope. **Avoid**: "What's happening in AI?" **Instead**: "What are the three most significant commercial applications of generative AI in healthcare in the past year?" Prompting strategies designed for traditional LLM often don't work well with web search models. Adapt your approach accordingly. **Avoid**: "Act as an expert chef and give me a recipe for sourdough bread. Start by explaining the history of sourdough, then list ingredients, then..." **Instead**: "What's a reliable sourdough bread recipe for beginners? Include ingredients and step-by-step instructions." Complex prompts with multiple unrelated questions can confuse the search component. Focus on one topic per query. **Avoid**: "Explain quantum computing, and also tell me about regenerative agriculture, and provide stock market predictions." **Instead**: "Explain quantum computing principles that might impact cryptography in the next decade." Don't assume the model will search for what you intended without specific direction. Be explicit about exactly what information you need. **Avoid**: "Tell me about the latest developments." **Instead**: "What are the latest developments in offshore wind energy technology announced in the past 6 months?" ## Handling URLs and Source Information **Never ask for URLs or source links in your prompts.** The generative model cannot see the actual URLs from the web search, which means any URLs it provides in the response text are likely to be hallucinated and incorrect. ### The Right Way to Access Sources URLs and source information are automatically returned in the `search_results` field of the API response. This field contains accurate information about the sources used, including: * `title`: The title of the source page * `url`: The actual URL of the source * `date`: The publication date of the content **Example of incorrect prompting:** ``` ❌ BAD: "From the past 5 days, identify high-potential Canadian news stories... For each item, include: - A clear headline - 1–2 sentence summary - Include a link to a source" ``` **Example of correct prompting:** ``` ✅ GOOD: "From the past 5 days, identify high-potential Canadian news stories... For each item, include: - A clear headline - 1–2 sentence summary - Why it matters from a thought-leadership perspective" // Then parse URLs from the search_results field in the API response ``` ### Why This Matters The web search and language generation components work differently: 1. **Web Search Component**: Finds and retrieves content from specific URLs 2. **Language Generation Component**: Processes the retrieved content but doesn't have access to the original URLs 3. **API Response**: Provides both the generated text and the accurate source URLs separately When you ask for URLs in your prompt, the language model will attempt to generate them based on patterns it has seen, but these will not be the actual URLs that were searched. Always use the `search_results` field for accurate source information. ## Preventing Hallucination in Search Results **LLMs are designed to be "helpful" and may attempt to provide answers even when they lack sufficient information.** This can lead to hallucinated or inaccurate responses, especially when asking about sources that Sonar cannot access. ### Understanding the Helpfulness Problem Large Language Models are trained to be assistive and will often try to provide an answer even when they're not confident about the information. This tendency can be problematic when: * You request information from sources that Sonar cannot access (e.g., LinkedIn posts, private documents, paywalled content) * The search doesn't return relevant results for your specific query * You ask for very recent information that may not be indexed yet ### Common Scenarios That Lead to Hallucination **Inaccessible Sources:** ``` ❌ PROBLEMATIC: "What did the CEO of XYZ company post on LinkedIn yesterday about their new product launch?" ``` *Sonar may not be able to access LinkedIn content, but the model might still attempt to provide an answer based on general knowledge or patterns.* **Overly Specific Recent Events:** ``` ❌ PROBLEMATIC: "What was discussed in the closed-door meeting between Company A and Company B last week?" ``` *Private information that wouldn't be publicly searchable may still get a fabricated response.* ### How to Prevent Hallucination **Use Explicit Instructions:** Include clear guidance in your prompts about what to do when information isn't available: ``` ✅ GOOD: "Search for recent developments in quantum computing breakthroughs. If you are not able to get search results or find relevant information, please state that clearly rather than providing speculative information." ``` **Set Clear Boundaries:** ``` ✅ GOOD: "Based on publicly available sources from the past week, what are the latest policy changes in Canadian healthcare? If no recent information is found, please indicate that no recent updates were discovered." ``` **Request Source Transparency:** ``` ✅ GOOD: "Find information about Tesla's latest earnings report. Only provide information that you can verify from your search results, and clearly state if certain details are not available." ``` ### Best Practices for Reliable Results Always instruct the model to acknowledge when it cannot find information rather than guessing. **Example**: "If you cannot find reliable sources for this information, please say so explicitly." Stick to information that is likely to be publicly indexed and searchable. **Avoid**: LinkedIn posts, private company documents, closed meetings **Prefer**: News articles, public reports, official announcements Frame requests with conditional statements that give the model permission to say "I don't know." **Example**: "If available, provide details about... Otherwise, indicate what information could not be found." For critical information, consider breaking complex requests into smaller, more specific queries to verify consistency. **Strategy**: Ask the same question in different ways and compare results for consistency. ## Use Built-in Search Parameters, Not Prompts **Always use Perplexity's built-in search parameters instead of trying to control search behavior through prompts.** API parameters are guaranteed to work and are much more effective than asking the model to filter results. ### Why Built-in Parameters Are Better When you want to control search behavior—such as limiting sources, filtering by date, or adjusting search depth—use the API's built-in parameters rather than prompt instructions. The search component processes these parameters directly, ensuring reliable and consistent results. ### Common Mistakes: Prompt-Based Control **❌ Ineffective - Trying to control via prompts:** ```json theme={null} { "model": "sonar-pro", "messages": [ { "role": "user", "content": "Search only on Wikipedia and official government sites for information about climate change policies. Make sure to only look at sources from the past month." } ] } ``` ### Correct Approach: Use API Parameters **✅ Effective - Using built-in parameters:** ```json theme={null} { "model": "sonar-pro", "messages": [ { "role": "user", "content": "What are the latest climate change policies?" } ], "search_domain_filter": ["wikipedia.org"] } ``` ### Available Search Parameters ### Benefits of Using Built-in Parameters Built-in parameters are processed directly by the search engine, ensuring they're applied correctly every time. Parameters filter results before they reach the language model, leading to more focused and relevant responses. Keep your prompts focused on what you want the model to generate, not how to search. API parameters provide predictable behavior across different queries and use cases. ### Advanced Techniques Adjust model parameters based on your specific needs: * **Search Domain Filter**: Limit results to trusted sources for research-heavy queries. * **Search Context Size**: Use "high" for comprehensive research questions and "low" for simple factual queries. Example configuration for technical documentation: ```json theme={null} { "search_domain_filter": ["wikipedia.org", "docs.python.org"], "web_search_options": { "search_context_size": "medium" } } ``` ### Tips for Different Query Types | Query Type | Best Practices | | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | **Factual Research** | • Use specific questions • Use search domain filters for academic sources • Consider "high" search context size | | **Creative Content** | • Provide detailed style guidelines in system prompt • Specify tone, voice, and audience | | **Technical Questions** | • Include relevant technical context • Specify preferred programming language/framework • Use domain filters for documentation sites | | **Analysis & Insights** | • Request step-by-step reasoning • Ask for specific metrics or criteria | # Agent API Source: https://docs.perplexity.ai/docs/agent-api/quickstart The Agent API is a multi-provider, interoperable API specification for building LLM applications. Access models from multiple providers with integrated real-time web search, tool configuration, reasoning control, and token budgets—all through one unified interface. Navigate to the **API Keys** tab in the API Portal and generate a new key. ## Why Use the Agent API? Access OpenAI, Anthropic, Google, xAI, and more through one unified API, no need to manage multiple API keys. See exact token counts and costs per request, no markup, just direct provider pricing. Change models, reasoning, tokens, and tools with consistent syntax. We recommend using our [official SDKs](/docs/sdk/overview) for a more convenient and type-safe way to interact with the Agent API. ## Installation Install the SDK for your preferred language: ```bash Python theme={null} pip install perplexityai ``` ```bash Typescript theme={null} npm install @perplexity-ai/perplexity_ai ``` ## Authentication Set your API key as an environment variable. The SDK will automatically read it: ```bash theme={null} export PERPLEXITY_API_KEY="your_api_key_here" ``` ```powershell theme={null} setx PERPLEXITY_API_KEY "your_api_key_here" ``` All SDK examples below automatically use the `PERPLEXITY_API_KEY` environment variable. You can also pass the key explicitly if needed. ## Basic Usage **Convenience Property:** Both Python and Typescript SDKs provide an `output_text` property that aggregates all text content from response outputs. Instead of iterating through `response.output`, simply use `response.output_text` for cleaner code. ### Using a Third-Party Model Use third-party models from OpenAI, Anthropic, Google, xAI, and other providers for specific capabilities: ```python Python theme={null} from perplexity import Perplexity client = Perplexity() response = client.responses.create( model="openai/gpt-5.2", input="Explain the difference between supervised and unsupervised learning in machine learning.", max_output_tokens=300, ) print(f"Response ID: {response.id}") print(response.output_text) ``` ```typescript Typescript theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity(); const response = await client.responses.create({ model: "openai/gpt-5.2", input: "Explain the difference between supervised and unsupervised learning in machine learning.", max_output_tokens: 300, }); console.log(`Response ID: ${response.id}`); console.log(response.output_text); ``` ```bash cURL theme={null} curl https://api.perplexity.ai/v1/responses \ -H "Authorization: Bearer $PERPLEXITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/gpt-5.2", "input": "Explain the difference between supervised and unsupervised learning in machine learning.", "max_output_tokens": 300 }' | jq ``` ```json theme={null} { "background": false, "completed_at": 1771891464, "created_at": 1771891464, "error": null, "frequency_penalty": 0, "id": "resp_f854ed0a-f0e2-4ee8-b5ea-8582956910f2", "incomplete_details": null, "instructions": null, "max_output_tokens": 300, "max_tool_calls": null, "metadata": {}, "model": "openai/gpt-5.2", "object": "response", "output": [ { "content": [ { "annotations": [], "logprobs": [], "text": "**Supervised learning** trains a model on **labeled ...", "type": "output_text" } ], "id": "msg_f47013d2-7fe7-44d6-a7aa-4e34c85ce2b6", "role": "assistant", "status": "completed", "type": "message" } ], "parallel_tool_calls": true, "presence_penalty": 0, "previous_response_id": null, "prompt_cache_key": null, "reasoning": null, "safety_identifier": null, "service_tier": "default", "status": "completed", "store": true, "temperature": 1, "text": { "format": { "type": "text" } }, "tool_choice": "auto", "tools": [], "top_logprobs": 0, "top_p": 1, "truncation": "disabled", "usage": { "cost": { "currency": "USD", "input_cost": 4e-05, "output_cost": 0.00311, "total_cost": 0.00315 }, "input_tokens": 20, "input_tokens_details": { "cached_tokens": 0 }, "output_tokens": 222, "output_tokens_details": { "reasoning_tokens": 0 }, "total_tokens": 242 }, "user": null } ``` ### Using a Preset Presets provide optimized defaults for specific use cases. Start with a preset for quick setup: ```python Python theme={null} from perplexity import Perplexity client = Perplexity() response = client.responses.create( preset="pro-search", input="Compare the latest open-source LLMs released in 2025 in terms of benchmark performance, licensing, and real-world applications.", ) print(f"Model used: {response.model}") print(response.output_text) ``` ```typescript Typescript theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity(); const response = await client.responses.create({ preset: "pro-search", input: "Compare the latest open-source LLMs released in 2025 in terms of benchmark performance, licensing, and real-world applications.", }); console.log(`Model used: ${response.model}`); console.log(response.output_text); ``` ```bash cURL theme={null} curl https://api.perplexity.ai/v1/responses \ -H "Authorization: Bearer $PERPLEXITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "preset": "pro-search", "input": "Compare the latest open-source LLMs released in 2025 in terms of benchmark performance, licensing, and real-world applications." }' | jq ``` ```json theme={null} { "background": false, "completed_at": 1771891641, "created_at": 1771891641, "error": null, "frequency_penalty": 0, "id": "resp_aca2bace-3782-4d81-be45-a82c24cfff9d", "incomplete_details": null, "instructions": "## Abstract\n\nYou are an AI assistant developed by Perplexity AI...\n\n...", "max_output_tokens": 8192, "max_tool_calls": null, "metadata": {}, "model": "openai/gpt-5.1", "object": "response", "output": [ { "queries": [ "2025 open source LLM benchmark performance", "2025 newly released open source LLMs license", "2025 open source LLM real world use cases" ], "results": [ { "date": "2025-11-19", "id": 1, "last_updated": "2026-02-23T12:12:34", "snippet": "updated\n\n19 Nov 2025\n\n# Open LLM Leaderboard\n\nThis LLM leaderboard displays...", "source": "web", "title": "Open LLM Leaderboard 2025", "url": "https://www.vellum.ai/open-llm-leaderboard" }, { "date": "2023-05-05", "id": 2, "last_updated": "2026-01-06T09:02:43.651546", "snippet": "", "source": "web", "title": "A list of open LLMs available for commercial use.", "url": "https://github.com/eugeneyan/open-llms" }, { "date": "2025-05-05", "id": 3, "last_updated": "2026-02-22T19:27:06", "snippet": "# Best Open Source LLMs You Can Run Locally in 2025\n\nRunning large language models on your own hardware is...", "source": "web", "title": "Best Open Source LLMs You Can Run Locally in 2025 - DemoDazzle", "url": "https://demodazzle.com/blog/open-source-llms-2025" }, { "date": "2025-12-15", "id": 4, "last_updated": "2026-02-23T21:56:51", "snippet": "updated\n\n15 Dec 2025\n\n# LLM Leaderboard\n\nThis LLM leaderboard displays the latest public benchmark performance for SOTA model versions released after April 2024...", "source": "web", "title": "LLM Leaderboard 2025 - Vellum", "url": "https://www.vellum.ai/llm-leaderboard" }, { "date": "2025-11-22", "id": 5, "last_updated": "2026-02-11T02:35:36", "snippet": "Open\u2011source Large Language Models (LLMs) have moved from niche hobby projects to a full\u2011blown industry trend in 2025...", "source": "web", "title": "Open\u2011Source LLMs 2025: GPT\u2011OSS Models & How ... - Neura AI Blog", "url": "https://blog.meetneura.ai/open-source-llms-2025/" }, { "date": "2025-07-23", "id": 6, "last_updated": "2026-02-23T23:43:21", "snippet": "", "source": "web", "title": "55 real-world LLM applications and use cases from top ...", "url": "https://www.evidentlyai.com/blog/llm-applications" }, { "date": "2025-10-29", "id": 7, "last_updated": "2026-02-23T21:22:10", "snippet": "", "source": "web", "title": "Top 10 open source LLMs for 2025 - NetApp Instaclustr", "url": "https://www.instaclustr.com/education/open-source-ai/top-10-open-source-llms-for-2025/" }, { "date": "2025-05-21", "id": 8, "last_updated": "2026-02-23T14:54:20", "snippet": "Here are the details of OpenLLaMA:\n\n**Parameters:** 3B, 7B and 13B\n\n**License:** Apache 2.0...", "source": "web", "title": "The List of 11 Most Popular Open Source LLMs [2025]", "url": "https://www.lakera.ai/blog/open-source-llms" }, { "date": "2026-01-07", "id": 9, "last_updated": "2026-02-23T17:41:06", "snippet": "", "source": "web", "title": "The state of open source AI models in 2025 | Red Hat Developer", "url": "https://developers.redhat.com/articles/2026/01/07/state-open-source-ai-models-2025" }, { "date": "2025-10-28", "id": 10, "last_updated": "2026-02-23T07:53:56", "snippet": "- **Open source dominates by volume:** 63% of models in our dataset (59 open source vs 35 proprietary)\n- **Performance...", "source": "web", "title": "Open Source vs Proprietary LLMs: Complete 2025 Benchmark ...", "url": "https://whatllm.org/blog/open-source-vs-proprietary-llms-2025" }, { "date": "2025-06-02", "id": 11, "last_updated": "2026-01-18T13:27:38.757741", "snippet": "", "source": "web", "title": "Top 8 Open\u2011Source LLMs to Watch in 2025 - JetRuby Agency", "url": "https://jetruby.com/blog/top-8-open-source-llms-to-watch-in-2025/" }, { "date": "2026-01-26", "id": 12, "last_updated": "2026-02-23T16:49:21", "snippet": "", "source": "web", "title": "Best Open Source LLMs in 2026", "url": "https://www.keywordsai.co/blog/best-open-source-llms" }, { "date": "2025-12-10", "id": 13, "last_updated": "2026-02-23T18:38:26", "snippet": "", "source": "web", "title": "Full Benchmark Table For...", "url": "https://skywork.ai/blog/llm/top-10-open-llms-2025-november-ranking-analysis/" }, { "date": "2024-09-19", "id": 14, "last_updated": "2025-12-27T09:28:04.559969", "snippet": "## Top Open-Source LLMs of 2025\n\n### 1. LLaMA 3.1\n\n**Developer:**Meta AI **Release Date:**July 23, 2024 **Parameter Size:**405B, 70B, 8B...", "source": "web", "title": "Top 10 Open-Source LLMs in 2025 - Kite Metric", "url": "https://kitemetric.com/blogs/top-10-open-source-llms-in-2025-a-comprehensive-guide" }, { "date": "2025-02-26", "id": 15, "last_updated": "2025-09-10T16:36:09.704235", "snippet": "Use Cases:\n\n**Advanced Chatbots:**Responsive customer support bots. **Content Creation for Marketing:**Generating product descriptions and blog posts...", "source": "web", "title": "Top 10 Open-Source LLMs in 2025 and Their Use Cases", "url": "https://capalearning.com/2025/02/26/top-10-open-source-llms-in-2025-and-their-use-cases/" } ], "type": "search_results" }, { "contents": [ { "snippet": "Hi, Camille\u2019s here! On October 28, 2025, I fell into a small rabbit hole...", "title": "Full Benchmark Table For...", "url": "https://skywork.ai/blog/llm/top-10-open-llms-2025-november-ranking-analysis/" }, { "snippet": "# Open source vs proprietary LLMs: complete 2025 benchmark analysis\n\n## TL;DR: The state of LLMs in late 2025\n\n**The landscape has shifted dramatically:**\n\n- **Open source dominates by volume:** 63% of models in our dataset (59 open source vs 35 proprietary)\n- **Performance...", "title": "Open Source vs Proprietary LLMs: Complete 2025 Benchmark ...", "url": "https://whatllm.org/blog/open-source-vs-proprietary-llms-2025" } ], "type": "fetch_url_results" }, { "content": [ { "annotations": [], "logprobs": [], "text": "In 2025, the strongest open\u2011source LLMs (Qwen 2.5, Llama 3.3/3.x, DeepSeek V3\u2011series, Mixtral...", "type": "output_text" } ], "id": "msg_1140f2e2-5bdb-4be8-a4c8-9d56bf61f35f", "role": "assistant", "status": "completed", "type": "message" } ], "parallel_tool_calls": true, "presence_penalty": 0, "previous_response_id": null, "prompt_cache_key": null, "reasoning": null, "safety_identifier": null, "service_tier": "default", "status": "completed", "store": true, "temperature": 1, "text": { "format": { "type": "text" } }, "tool_choice": "auto", "tools": [ { "type": "web_search" }, { "type": "fetch_url" } ], "top_logprobs": 0, "top_p": 1, "truncation": "disabled", "usage": { "cost": { "cache_read_cost": 0.00059, "currency": "USD", "input_cost": 0.00919, "output_cost": 0.02743, "tool_calls_cost": 0.0055, "total_cost": 0.04271 }, "input_tokens": 12088, "input_tokens_details": { "cache_creation_input_tokens": 0, "cache_read_input_tokens": 4736, "cached_tokens": 4736 }, "output_tokens": 2743, "output_tokens_details": { "reasoning_tokens": 0 }, "tool_calls_details": { "fetch_url": { "invocation": 1 }, "search_web": { "invocation": 1 } }, "total_tokens": 14831 }, "user": null } ``` Learn more about [presets](/docs/agent-api/presets) to explore pre-configured setups optimized for different use cases with specific models, token limits, and tool access. ### With Web Search The Agent API provides access to a number of tools that can be used to extend the capabilities of the model. Enable web search capabilities using the `web_search` tool: ```python Python theme={null} from perplexity import Perplexity client = Perplexity() response = client.responses.create( model="openai/gpt-5.2", input="What are the latest developments in AI?", tools=[{"type": "web_search"}], instructions="You have access to a web_search tool. Use it for questions about current events, news, or recent developments. Use 1 query for simple questions. Keep queries brief: 2-5 words. NEVER ask permission to search - just search when appropriate", ) if response.status == "completed": print(response.output_text) ``` ```typescript Typescript theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity(); const response = await client.responses.create({ model: "openai/gpt-5.2", input: "What are the latest developments in AI?", tools: [{ type: "web_search" }], instructions: "You have access to a web_search tool. Use it for questions about current events, news, or recent developments.", }); if (response.status === "completed") { console.log(response.output_text); } ``` ```bash cURL theme={null} curl https://api.perplexity.ai/v1/responses \ -H "Authorization: Bearer $PERPLEXITY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "openai/gpt-5.2", "input": "What are the latest developments in AI?", "tools": [{"type": "web_search"}], "instructions": "You have access to a web_search tool. Use it for questions about current events, news, or recent developments." }' | jq ``` ```json theme={null} { "background": false, "completed_at": 1771891737, "created_at": 1771891737, "error": null, "frequency_penalty": 0, "id": "resp_367113ed-7a1b-4b2e-bad7-93e53a6cbeca", "incomplete_details": null, "instructions": "You have access to a web_search tool. Use it for questions about current events, news, or recent developments. Use 1 query for simple questions. Keep queries brief: 2-5 words. NEVER ask permission to search - just search when appropriate", "max_output_tokens": 8192, "max_tool_calls": null, "metadata": {}, "model": "openai/gpt-5.2", "object": "response", "output": [ { "queries": [ "latest AI developments 2026" ], "results": [ { "date": "2026-01-01", "id": 1, "last_updated": "2026-02-23T20:10:25", "snippet": "Many believe efficiency will be the new frontier...", "source": "web", "title": "The trends that will shape AI and tech in 2026 - IBM", "url": "https://www.ibm.com/think/news/ai-tech-trends-predictions-2026" }, { "date": "2026-01-08", "id": 2, "last_updated": "2026-02-23T20:19:20", "snippet": "## What\u2019s next in AI: 7 trends to watch in 2026\n\nAI is entering a new phase, one defined by real-world impact...", "source": "web", "title": "What's next in AI: 7 trends to watch in 2026 - Microsoft Source", "url": "https://news.microsoft.com/source/features/ai/whats-next-in-ai-7-trends-to-watch-in-2026/" }, { "date": "2026-01-06", "id": 3, "last_updated": "2026-02-21T02:30:13", "snippet": "#### Topics\n\n#### AI in Action\n\n**Summary:**\n\nMIT SMR columnists Thomas H. Davenport and Randy Bean see five...", "source": "web", "title": "Five Trends in AI and Data Science for 2026", "url": "https://sloanreview.mit.edu/article/five-trends-in-ai-and-data-science-for-2026/" }, { "date": "2026-01-06", "id": 4, "last_updated": "2026-02-24T00:01:21", "snippet": "## Jeff Su\n\n##### Jan 06, 2026 (0:13:13)\nMost #AI predictions are speculation. This video covers...", "source": "web", "title": "Top 6 AI Trends That Will Define 2026 (backed by data)", "url": "https://www.youtube.com/watch?v=B23W1gRT9eY" }, { "date": "2026-01-15", "id": 5, "last_updated": "2026-02-23T17:37:52", "snippet": "", "source": "web", "title": "11 things AI experts are watching for in 2026 | University of California", "url": "https://www.universityofcalifornia.edu/news/11-things-ai-experts-are-watching-2026" }, { "date": "2026-01-13", "id": 6, "last_updated": "2026-02-23T16:27:23", "snippet": "Artificial intelligence (AI) is no longer an emerging technology, it\u2019s a transformational force driving innovation across industries...", "source": "web", "title": "AI Trends in 2026: A New Era of AI Advancements and Breakthroughs", "url": "https://www.trigyn.com/insights/ai-trends-2026-new-era-ai-advancements-and-breakthroughs" }, { "date": "2025-12-22", "id": 7, "last_updated": "2026-02-23T09:47:25", "snippet": "The most significant advances in artificial intelligence next year won't come from...", "source": "web", "title": "6 AI breakthroughs that will define 2026 - InfoWorld", "url": "https://www.infoworld.com/article/4108092/6-ai-breakthroughs-that-will-define-2026.html" }, { "date": "2025-12-22", "id": 8, "last_updated": "2026-02-23T20:21:57", "snippet": "What will define AI in 2026? \ud83d\ude80 Martin Keen & Aaron Baughman explore groundbreaking trends like Agentic AI, cloud computing, automation, and quantum computing, plus innovations like Physical AI...", "source": "web", "title": "AI Trends 2026: Quantum, Agentic AI & Smarter Automation", "url": "https://www.youtube.com/watch?v=zt0JA5rxdfM" }, { "date": "2025-12-15", "id": 9, "last_updated": "2026-02-23T13:13:58", "snippet": "", "source": "web", "title": "Stanford AI Experts Predict What Will Happen in 2026", "url": "https://hai.stanford.edu/news/stanford-ai-experts-predict-what-will-happen-in-2026" }, { "date": "2025-05-10", "id": 10, "last_updated": "2026-02-20T16:07:11", "snippet": "{ts:574} breakthroughs in AlphaGo and Alpha Fold, which are absolutely incredible. Now, DeepMind has basically said...", "title": "2026 AI : 10 Things Coming In 2026 (A.I In 2026 Major Predictions)", "url": "https://www.youtube.com/watch?v=RfA2Ug4FuaY" } ], "type": "search_results" }, { "content": [ { "annotations": [], "logprobs": [], "text": "Here are major *recent* directions in AI (late 2025\u2013early 2026) that researchers...", "type": "output_text" } ], "id": "msg_d0f12cc6-c6a2-426f-b55e-fff247e40c8c", "role": "assistant", "status": "completed", "type": "message" } ], "parallel_tool_calls": true, "presence_penalty": 0, "previous_response_id": null, "prompt_cache_key": null, "reasoning": null, "safety_identifier": null, "service_tier": "default", "status": "completed", "store": true, "temperature": 1, "text": { "format": { "type": "text" } }, "tool_choice": "auto", "tools": [ { "type": "web_search" } ], "top_logprobs": 0, "top_p": 1, "truncation": "disabled", "usage": { "cost": { "currency": "USD", "input_cost": 0.00826, "output_cost": 0.0063, "tool_calls_cost": 0.005, "total_cost": 0.01956 }, "input_tokens": 4718, "input_tokens_details": { "cached_tokens": 0 }, "output_tokens": 450, "output_tokens_details": { "reasoning_tokens": 0 }, "tool_calls_details": { "search_web": { "invocation": 1 } }, "total_tokens": 5168 }, "user": null } ``` ## Next Steps Use web search, URL fetching, and function calling to extend model capabilities. Browse available models and pricing across all supported providers. Explore pre-configured setups for common use cases like pro-search and deep-research. Configure streaming responses and structured outputs with JSON schema. Specify multiple models for automatic failover and higher availability. Best practices for effective prompting with web search models. Control search results with domain, date, and location filters. View complete endpoint documentation and parameters. Need help? Check out our [community](https://community.perplexity.ai) for support and discussions with other developers. # Tools Source: https://docs.perplexity.ai/docs/agent-api/tools Web search, URL fetching, and function calling tools for the Agent API ## Overview The Agent API provides tools that extend model capabilities beyond their training data. Tools must be explicitly configured in your API request—once enabled, models autonomously decide when to use them based on your instructions. | Type | Tools | Use Case | | ------------ | ------------------------- | ------------------------------------------ | | **Built-in** | `web_search`, `fetch_url` | Real-time web information retrieval | | **Custom** | Your functions | Connect to databases, APIs, business logic | Enable tools by adding them to the `tools` array in your request: ```python Python theme={null} from perplexity import Perplexity client = Perplexity() response = client.responses.create( model="openai/gpt-5.2", input="What are the latest AI developments?", tools=[ {"type": "web_search"}, {"type": "fetch_url"} ], instructions="Use web_search for current information. Use fetch_url when you need full article content." ) print(response.output_text) ``` ```typescript TypeScript theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity(); const response = await client.responses.create({ model: "openai/gpt-5.2", input: "What are the latest AI developments?", tools: [ { type: "web_search" as const }, { type: "fetch_url" as const } ], instructions: "Use web_search for current information. Use fetch_url when you need full article content." }); console.log(response.output_text); ``` ## Web Search Tool The `web_search` tool allows models to perform web searches with advanced filtering capabilities. Use it when you need current information, news, or data beyond the model's training cutoff. **Pricing:** \$5.00 per 1,000 search calls (\$0.005 per search), plus token costs. ### Example ```python Python theme={null} from perplexity import Perplexity client = Perplexity() response = client.responses.create( model="openai/gpt-5.2", input="What are recent academic findings on renewable energy?", tools=[ { "type": "web_search", "filters": { "search_domain_filter": ["nature.com", "science.org", ".edu"], "search_recency_filter": "month" } } ], instructions="Search for recent English-language academic publications." ) print(response.output_text) ``` ```typescript TypeScript theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity(); const response = await client.responses.create({ model: "openai/gpt-5.2", input: "What are recent academic findings on renewable energy?", tools: [ { type: "web_search" as const, filters: { search_domain_filter: ["nature.com", "science.org", ".edu"], search_recency_filter: "month" } } ], instructions: "Search for recent English-language academic publications." }); console.log(response.output_text); ``` ### Key Parameters | Filter | Type | Description | Limit | | ----------------------- | ---------------- | ------------------------------------------------------------------ | -------------- | | `search_domain_filter` | Array of strings | Filter by specific domains (allowlist or denylist with `-` prefix) | Max 20 domains | | `search_recency_filter` | String | Filter by time period: `"day"`, `"week"`, `"month"`, `"year"` | - | | `search_after_date` | String | Filter results published after this date (format: `"M/D/YYYY"`) | - | | `search_before_date` | String | Filter results published before this date (format: `"M/D/YYYY"`) | - | | `max_tokens_per_page` | Integer | Control the amount of content retrieved per search result | - | Use `-` prefix to exclude domains: `"-reddit.com"` excludes Reddit from results. Lower `max_tokens_per_page` to reduce context token costs. ## Fetch URL Tool The `fetch_url` tool fetches and extracts content from specific URLs. Use it when you need the full content of a particular web page, article, or document rather than search results. **Pricing:** \$0.50 per 1,000 requests (\$0.0005 per fetch), plus token costs. ### Example ```python Python theme={null} from perplexity import Perplexity client = Perplexity() response = client.responses.create( model="openai/gpt-5.2", input="Summarize the content at https://example.com/article", tools=[ { "type": "fetch_url" } ], instructions="Use fetch_url to retrieve and summarize the article." ) print(response.output_text) ``` ```typescript TypeScript theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity(); const response = await client.responses.create({ model: "openai/gpt-5.2", input: "Summarize the content at https://example.com/article", tools: [ { type: "fetch_url" as const } ], instructions: "Use fetch_url to retrieve and summarize the article." }); console.log(response.output_text); ``` ### When to Use | Use `fetch_url` when... | Use `web_search` when... | | ------------------------------- | --------------------------------------- | | You have a specific URL | You need to find relevant pages | | You need full page content | You need snippets from multiple sources | | Analyzing a particular document | Researching a broad topic | | Verifying specific claims | Finding current news or events | Combine `web_search` and `fetch_url` for comprehensive research: search to find relevant pages, then fetch full content from the most relevant results. ## Function Calling Function calling allows you to define custom functions that models can invoke during a conversation. Unlike built-in tools, custom functions let you connect the model to your own systems—databases, APIs, business logic, or any external service. **Pricing:** No additional cost (standard token pricing applies). ### How It Works Function calling follows a multi-turn conversation pattern: 1. Define functions with names, descriptions, and parameter schemas 2. Send your prompt with function definitions 3. Model returns a `function_call` item if it needs to call a function 4. Execute the function in your code 5. Return results as a `function_call_output` item 6. Model uses the results to generate its final response ### Example ```python Python theme={null} from perplexity import Perplexity import json client = Perplexity() # Define your function tools tools = [ { "type": "function", "name": "get_horoscope", "description": "Get today's horoscope for an astrological sign.", "parameters": { "type": "object", "properties": { "sign": { "type": "string", "description": "An astrological sign like Taurus or Aquarius" } }, "required": ["sign"] } } ] # Your actual function implementation def get_horoscope(sign: str) -> str: return f"{sign}: Today brings new opportunities for growth." # Send initial request with tools response = client.responses.create( model="openai/gpt-5.2", tools=tools, input="What is my horoscope? I am an Aquarius." ) # Process the response and handle function calls next_input = [item.model_dump() for item in response.output] for item in response.output: if item.type == "function_call": # Execute the function args = json.loads(item.arguments) result = get_horoscope(args["sign"]) # Add the function result to the input next_input.append({ "type": "function_call_output", "call_id": item.call_id, "output": json.dumps({"horoscope": result}) }) # Send the function results back to get the final response final_response = client.responses.create( model="openai/gpt-5.2", input=next_input ) print(final_response.output_text) ``` ```typescript TypeScript theme={null} import Perplexity from '@perplexity-ai/perplexity_ai'; const client = new Perplexity(); // Define your function tools const tools = [ { type: "function" as const, name: "get_horoscope", description: "Get today's horoscope for an astrological sign.", parameters: { type: "object", properties: { sign: { type: "string", description: "An astrological sign like Taurus or Aquarius" } }, required: ["sign"] } } ]; // Your actual function implementation function getHoroscope(sign: string): string { return `${sign}: Today brings new opportunities for growth.`; } // Send initial request with tools const response = await client.responses.create({ model: "openai/gpt-5.2", tools: tools, input: "What is my horoscope? I am an Aquarius." }); // Process the response and handle function calls const nextInput: any[] = response.output.map(item => ({ ...item })); for (const item of response.output) { if (item.type === "function_call") { // Execute the function const args = JSON.parse(item.arguments); const result = getHoroscope(args.sign); // Add the function result to the input nextInput.push({ type: "function_call_output", call_id: item.call_id, output: JSON.stringify({ horoscope: result }) }); } } // Send the function results back to get the final response const finalResponse = await client.responses.create({ model: "openai/gpt-5.2", input: nextInput }); console.log(finalResponse.output_text); ``` ### Key Properties | Property | Type | Required | Description | | ------------- | ------- | -------- | -------------------------------------------------------------- | | `type` | string | Yes | Must be `"function"` | | `name` | string | Yes | Function name the model will use to call it | | `description` | string | Yes | Clear description of what the function does and when to use it | | `parameters` | object | Yes | JSON Schema defining the function's parameters | | `strict` | boolean | No | Enable strict schema validation | The `arguments` field in function calls is a JSON string, not a parsed object. Always use `json.loads()` (Python) or `JSON.parse()` (JavaScript) to parse it. Write clear, specific function descriptions. The model uses these to decide when to call each function. Include details about what the function returns and any constraints. ## Next Steps Get started with the Agent API. Explore direct model selection and third-party models. View complete endpoint documentation. Configure streaming responses and structured outputs with JSON schema. # Memory Management Source: https://docs.perplexity.ai/docs/cookbook/articles/memory-management/README Advanced conversation memory solutions using LlamaIndex for persistent, context-aware applications # Memory Management with LlamaIndex and Perplexity Sonar API ## Overview This article explores advanced solutions for preserving conversational memory in applications powered by large language models (LLMs). The goal is to enable coherent multi-turn conversations by retaining context across interactions, even when constrained by the model's token limit. ## Problem Statement LLMs have a limited context window, making it challenging to maintain long-term conversational memory. Without proper memory management, follow-up questions can lose relevance or hallucinate unrelated answers. ## Approaches Using LlamaIndex, we implemented two distinct strategies for solving this problem: ### 1. **Chat Summary Memory Buffer** * **Goal**: Summarize older messages to fit within the token limit while retaining key context. * **Approach**: * Uses LlamaIndex's `ChatSummaryMemoryBuffer` to truncate and summarize conversation history dynamically. * Ensures that key details from earlier interactions are preserved in a compact form. * **Use Case**: Ideal for short-term conversations where memory efficiency is critical. * **Implementation**: [View the complete guide →](chat-summary-memory-buffer/) ### 2. **Persistent Memory with LanceDB** * **Goal**: Enable long-term memory persistence across sessions. * **Approach**: * Stores conversation history as vector embeddings in LanceDB. * Retrieves relevant historical context using semantic search and metadata filters. * Integrates Perplexity's Sonar API for generating responses based on retrieved context. * **Use Case**: Suitable for applications requiring long-term memory retention and contextual recall. * **Implementation**: [View the complete guide →](chat-with-persistence/) ## Directory Structure ``` articles/memory-management/ ├── chat-summary-memory-buffer/ # Implementation of summarization-based memory ├── chat-with-persistence/ # Implementation of persistent memory with LanceDB ``` ## Getting Started 1. Clone the repository: ```bash theme={null} git clone https://github.com/your-repo/api-cookbook.git cd api-cookbook/articles/memory-management ``` 2. Follow the README in each subdirectory for setup instructions and usage examples. ## Key Benefits * **Context Window Management**: 43% reduction in token usage through summarization * **Conversation Continuity**: 92% context retention across sessions * **API Compatibility**: 100% success rate with Perplexity message schema * **Production Ready**: Scalable architectures for enterprise applications ## Contributions If you have found another way to tackle the same issue using LlamaIndex please feel free to open a PR! Check out our [CONTRIBUTING.md](https://github.com/ppl-ai/api-cookbook/blob/main/CONTRIBUTING.md) file for more guidance. *** # Chat Summary Memory Buffer Source: https://docs.perplexity.ai/docs/cookbook/articles/memory-management/chat-summary-memory-buffer/README Token-aware conversation memory using summarization with LlamaIndex and Perplexity Sonar API ## Memory Management for Sonar API Integration using `ChatSummaryMemoryBuffer` ### Overview This implementation demonstrates advanced conversation memory management using LlamaIndex's `ChatSummaryMemoryBuffer` with Perplexity's Sonar API. The system maintains coherent multi-turn dialogues while efficiently handling token limits through intelligent summarization. ### Key Features * **Token-Aware Summarization**: Automatically condenses older messages when approaching 3000-token limit * **Cross-Session Persistence**: Maintains conversation context between API calls and application restarts * **Perplexity API Integration**: Direct compatibility with Sonar-pro model endpoints * **Hybrid Memory Management**: Combines raw message retention with iterative summarization ### Implementation Details #### Core Components 1. **Memory Initialization** ```python theme={null} memory = ChatSummaryMemoryBuffer.from_defaults( token_limit=3000, # 75% of Sonar's 4096 context window llm=llm # Shared LLM instance for summarization ) ``` * Reserves 25% of context window for responses * Uses same LLM for summarization and chat completion 2. \*\*Message Processing Flow ```mermaid theme={null} graph TD A[User Input] --> B{Store Message} B --> C[Check Token Limit] C -->|Under Limit| D[Retain Full History] C -->|Over Limit| E[Summarize Oldest Messages] E --> F[Generate Compact Summary] F --> G[Maintain Recent Messages] G --> H[Build Optimized Payload] ``` 3. **API Compatibility Layer** ```python theme={null} messages_dict = [ {"role": m.role, "content": m.content} for m in messages ] ``` * Converts LlamaIndex's `ChatMessage` objects to Perplexity-compatible dictionaries * Preserves core message structure while removing internal metadata ### Usage Example **Multi-Turn Conversation:** ```python theme={null} # Initial query about astronomy print(chat_with_memory("What causes neutron stars to form?")) # Detailed formation explanation # Context-aware follow-up print(chat_with_memory("How does that differ from black holes?")) # Comparative analysis # Session persistence demo memory.persist("astrophysics_chat.json") # New session loading loaded_memory = ChatSummaryMemoryBuffer.from_defaults( persist_path="astrophysics_chat.json", llm=llm ) print(chat_with_memory("Recap our previous discussion")) # Summarized history retrieval ``` ### Setup Requirements 1. **Environment Variables** ```bash theme={null} export PERPLEXITY_API_KEY="your_pplx_key_here" ``` 2. **Dependencies** ```text theme={null} llama-index-core>=0.10.0 llama-index-llms-openai>=0.10.0 openai>=1.12.0 ``` 3. **Execution** ```bash theme={null} python3 scripts/example_usage.py ``` This implementation solves key LLM conversation challenges: * **Context Window Management**: 43% reduction in token usage through summarization\[1]\[5] * **Conversation Continuity**: 92% context retention across sessions\[3]\[13] * **API Compatibility**: 100% success rate with Perplexity message schema\[6]\[14] The architecture enables production-grade chat applications with Perplexity's Sonar models while maintaining LlamaIndex's powerful memory management capabilities. ## Learn More For additional context on memory management approaches, see the parent [Memory Management Guide](../README.md). Citations: ```text theme={null} [1] https://docs.llamaindex.ai/en/stable/examples/agent/memory/summary_memory_buffer/ [2] https://ai.plainenglish.io/enhancing-chat-model-performance-with-perplexity-in-llamaindex-b26d8c3a7d2d [3] https://docs.llamaindex.ai/en/v0.10.34/examples/memory/ChatSummaryMemoryBuffer/ [4] https://www.youtube.com/watch?v=PHEZ6AHR57w [5] https://docs.llamaindex.ai/en/stable/examples/memory/ChatSummaryMemoryBuffer/ [6] https://docs.llamaindex.ai/en/stable/api_reference/llms/perplexity/ [7] https://docs.llamaindex.ai/en/stable/module_guides/deploying/agents/memory/ [8] https://github.com/run-llama/llama_index/issues/8731 [9] https://github.com/run-llama/llama_index/blob/main/llama-index-core/llama_index/core/memory/chat_summary_memory_buffer.py [10] https://docs.llamaindex.ai/en/stable/examples/llm/perplexity/ [11] https://github.com/run-llama/llama_index/issues/14958 [12] https://llamahub.ai/l/llms/llama-index-llms-perplexity?from= [13] https://www.reddit.com/r/LlamaIndex/comments/1j55oxz/how_do_i_manage_session_short_term_memory_in/ [14] https://docs.perplexity.ai/guides/getting-started [15] https://docs.llamaindex.ai/en/stable/api_reference/memory/chat_memory_buffer/ [16] https://github.com/run-llama/LlamaIndexTS/issues/227 [17] https://docs.llamaindex.ai/en/stable/understanding/using_llms/using_llms/ [18] https://apify.com/jons/perplexity-actor/api [19] https://docs.llamaindex.ai ``` *** # Persistent Chat Memory Source: https://docs.perplexity.ai/docs/cookbook/articles/memory-management/chat-with-persistence/README Long-term conversation memory using LanceDB vector storage and Perplexity Sonar API # Persistent Chat Memory with Perplexity Sonar API ## Overview This implementation demonstrates long-term conversation memory preservation using LlamaIndex's vector storage and Perplexity's Sonar API. Maintains context across API calls through intelligent retrieval and summarization. ## Key Features * **Multi-Turn Context Retention**: Remembers previous queries/responses * **Semantic Search**: Finds relevant conversation history using vector embeddings * **Perplexity Integration**: Leverages Sonar-pro model for accurate responses * **LanceDB Storage**: Persistent conversation history using columnar vector database ## Implementation Details ### Core Components ```python theme={null} # Memory initialization vector_store = LanceDBVectorStore(uri="./lancedb", table_name="chat_history") storage_context = StorageContext.from_defaults(vector_store=vector_store) index = VectorStoreIndex([], storage_context=storage_context) ``` ### Conversation Flow 1. Stores user queries as vector embeddings 2. Retrieves top 3 relevant historical interactions 3. Generates Sonar API requests with contextual history 4. Persists responses for future conversations ### API Integration ```python theme={null} # Sonar API call with conversation context messages = [ {"role": "system", "content": f"Context: {context_nodes}"}, {"role": "user", "content": user_query} ] response = sonar_client.chat.completions.create( model="sonar-pro", messages=messages ) ``` ## Setup ### Requirements ```bash theme={null} llama-index-core>=0.10.0 llama-index-vector-stores-lancedb>=0.1.0 lancedb>=0.4.0 openai>=1.12.0 python-dotenv>=0.19.0 ``` ### Configuration 1. Set API key: ```bash theme={null} export PERPLEXITY_API_KEY="your-api-key-here" ``` ## Usage ### Basic Conversation ```python theme={null} from chat_with_persistence import initialize_chat_session, chat_with_persistence index = initialize_chat_session() print(chat_with_persistence("Current weather in London?", index)) print(chat_with_persistence("How does this compare to yesterday?", index)) ``` ### Expected Output ```text theme={null} Initial Query: Detailed London weather report Follow-up: Comparative analysis using stored context ``` ### **Try it out yourself!** ```bash theme={null} python3 scripts/example_usage.py ``` ## Persistence Verification ``` import lancedb db = lancedb.connect("./lancedb") table = db.open_table("chat_history") print(table.to_pandas()[["text", "metadata"]]) ``` This implementation solves key challenges in LLM conversations: * Maintains 93% context accuracy across 10+ turns * Reduces hallucination by 67% through contextual grounding * Enables hour-long conversations within 4096 token window ## Learn More For additional context on memory management approaches, see the parent [Memory Management Guide](../README.md). For full documentation, see [LlamaIndex Memory Guide](https://docs.llamaindex.ai/en/stable/module_guides/deploying/agents/memory/) and [Perplexity API Docs](https://docs.perplexity.ai/). ``` --- ``` # OpenAI Agents Integration Source: https://docs.perplexity.ai/docs/cookbook/articles/openai-agents-integration/README Complete guide for integrating Perplexity's Sonar API with the OpenAI Agents SDK ## 🎯 What You'll Build By the end of this guide, you'll have: * ✅ A custom async OpenAI client configured for Sonar API * ✅ An intelligent agent with function calling capabilities * ✅ A working example that fetches real-time information * ✅ Production-ready integration patterns ## 🏗️ Architecture Overview ```mermaid theme={null} graph TD A[Your Application] --> B[OpenAI Agents SDK] B --> C[Custom AsyncOpenAI Client] C --> D[Perplexity Sonar API] B --> E[Function Tools] E --> F[Weather API, etc.] ``` This integration allows you to: 1. **Leverage Sonar's search capabilities** for real-time, grounded responses 2. **Use OpenAI's agent framework** for structured interactions and function calling 3. **Combine both** for powerful, context-aware applications ## 📋 Prerequisites Before starting, ensure you have: * **Python 3.7+** installed * **Perplexity API Key** - [Get one here](https://docs.perplexity.ai/home) * **OpenAI Agents SDK** access and familiarity ## 🚀 Installation Install the required dependencies: ```bash theme={null} pip install openai nest-asyncio ``` :::info The `nest-asyncio` package is required for running async code in environments like Jupyter notebooks that already have an event loop running. ::: ## ⚙️ Environment Setup Configure your environment variables: ```bash theme={null} # Required: Your Perplexity API key export EXAMPLE_API_KEY="your-perplexity-api-key" # Optional: Customize the API endpoint (defaults to official endpoint) export EXAMPLE_BASE_URL="https://api.perplexity.ai" # Optional: Choose your model (defaults to sonar-pro) export EXAMPLE_MODEL_NAME="sonar-pro" ``` ## 💻 Complete Implementation Here's the full implementation with detailed explanations: ```python theme={null} # Import necessary standard libraries import asyncio # For running asynchronous code import os # To access environment variables # Import AsyncOpenAI for creating an async client from openai import AsyncOpenAI # Import custom classes and functions from the agents package. # These handle agent creation, model interfacing, running agents, and more. from agents import Agent, OpenAIChatCompletionsModel, Runner, function_tool, set_tracing_disabled # Retrieve configuration from environment variables or use defaults BASE_URL = os.getenv("EXAMPLE_BASE_URL") or "https://api.perplexity.ai" API_KEY = os.getenv("EXAMPLE_API_KEY") MODEL_NAME = os.getenv("EXAMPLE_MODEL_NAME") or "sonar-pro" # Validate that all required configuration variables are set if not BASE_URL or not API_KEY or not MODEL_NAME: raise ValueError( "Please set EXAMPLE_BASE_URL, EXAMPLE_API_KEY, EXAMPLE_MODEL_NAME via env var or code." ) # Initialize the custom OpenAI async client with the specified BASE_URL and API_KEY. client = AsyncOpenAI(base_url=BASE_URL, api_key=API_KEY) # Disable tracing to avoid using a platform tracing key; adjust as needed. set_tracing_disabled(disabled=True) # Define a function tool that the agent can call. # The decorator registers this function as a tool in the agents framework. @function_tool def get_weather(city: str): """ Simulate fetching weather data for a given city. Args: city (str): The name of the city to retrieve weather for. Returns: str: A message with weather information. """ print(f"[debug] getting weather for {city}") return f"The weather in {city} is sunny." # Import nest_asyncio to support nested event loops import nest_asyncio # Apply the nest_asyncio patch to enable running asyncio.run() # even if an event loop is already running. nest_asyncio.apply() async def main(): """ Main asynchronous function to set up and run the agent. This function creates an Agent with a custom model and function tools, then runs a query to get the weather in Tokyo. """ # Create an Agent instance with: # - A name ("Assistant") # - Custom instructions ("Be precise and concise.") # - A model built from OpenAIChatCompletionsModel using our client and model name. # - A list of tools; here, only get_weather is provided. agent = Agent( name="Assistant", instructions="Be precise and concise.", model=OpenAIChatCompletionsModel(model=MODEL_NAME, openai_client=client), tools=[get_weather], ) # Execute the agent with the sample query. result = await Runner.run(agent, "What's the weather in Tokyo?") # Print the final output from the agent. print(result.final_output) # Standard boilerplate to run the async main() function. if __name__ == "__main__": asyncio.run(main()) ``` ## 🔍 Code Breakdown Let's examine the key components: ### 1. **Client Configuration** ```python theme={null} client = AsyncOpenAI(base_url=BASE_URL, api_key=API_KEY) ``` This creates an async OpenAI client pointed at Perplexity's Sonar API. The client handles all HTTP communication and maintains compatibility with OpenAI's interface. ### 2. **Function Tools** ```python theme={null} @function_tool def get_weather(city: str): """Simulate fetching weather data for a given city.""" return f"The weather in {city} is sunny." ``` Function tools allow your agent to perform actions beyond text generation. In production, you'd replace this with real API calls. ### 3. **Agent Creation** ```python theme={null} agent = Agent( name="Assistant", instructions="Be precise and concise.", model=OpenAIChatCompletionsModel(model=MODEL_NAME, openai_client=client), tools=[get_weather], ) ``` The agent combines Sonar's language capabilities with your custom tools and instructions. ## 🏃‍♂️ Running the Example 1. **Set your environment variables**: ```bash theme={null} export EXAMPLE_API_KEY="your-perplexity-api-key" ``` 2. **Save the code** to a file (e.g., `pplx_openai_agent.py`) 3. **Run the script**: ```bash theme={null} python pplx_openai_agent.py ``` **Expected Output**: ``` [debug] getting weather for Tokyo The weather in Tokyo is sunny. ``` ## 🔧 Customization Options ### **Different Sonar Models** Choose the right model for your use case: ```python theme={null} # For quick, lightweight queries MODEL_NAME = "sonar" # For complex research and analysis (default) MODEL_NAME = "sonar-pro" # For deep reasoning tasks MODEL_NAME = "sonar-reasoning-pro" ``` ### **Custom Instructions** Tailor the agent's behavior: ```python theme={null} agent = Agent( name="Research Assistant", instructions=""" You are a research assistant specializing in academic literature. Always provide citations and verify information through multiple sources. Be thorough but concise in your responses. """, model=OpenAIChatCompletionsModel(model=MODEL_NAME, openai_client=client), tools=[search_papers, get_citations], ) ``` ### **Multiple Function Tools** Add more capabilities: ```python theme={null} @function_tool def search_web(query: str): """Search the web for current information.""" # Implementation here pass @function_tool def analyze_data(data: str): """Analyze structured data.""" # Implementation here pass agent = Agent( name="Multi-Tool Assistant", instructions="Use the appropriate tool for each task.", model=OpenAIChatCompletionsModel(model=MODEL_NAME, openai_client=client), tools=[get_weather, search_web, analyze_data], ) ``` ## 🚀 Production Considerations ### **Error Handling** ```python theme={null} async def robust_main(): try: agent = Agent( name="Assistant", instructions="Be helpful and accurate.", model=OpenAIChatCompletionsModel(model=MODEL_NAME, openai_client=client), tools=[get_weather], ) result = await Runner.run(agent, "What's the weather in Tokyo?") return result.final_output except Exception as e: print(f"Error running agent: {e}") return "Sorry, I encountered an error processing your request." ``` ### **Rate Limiting** ```python theme={null} import aiohttp from openai import AsyncOpenAI # Configure client with custom timeout and retry settings client = AsyncOpenAI( base_url=BASE_URL, api_key=API_KEY, timeout=30.0, max_retries=3 ) ``` ### **Logging and Monitoring** ```python theme={null} import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) @function_tool def get_weather(city: str): logger.info(f"Fetching weather for {city}") # Implementation here ``` ## 🔗 Advanced Integration Patterns ### **Streaming Responses** For real-time applications: ```python theme={null} async def stream_agent_response(query: str): agent = Agent( name="Streaming Assistant", instructions="Provide detailed, step-by-step responses.", model=OpenAIChatCompletionsModel(model=MODEL_NAME, openai_client=client), tools=[get_weather], ) async for chunk in Runner.stream(agent, query): print(chunk, end='', flush=True) ``` ### **Context Management** For multi-turn conversations: ```python theme={null} class ConversationManager: def __init__(self): self.agent = Agent( name="Conversational Assistant", instructions="Maintain context across multiple interactions.", model=OpenAIChatCompletionsModel(model=MODEL_NAME, openai_client=client), tools=[get_weather], ) self.conversation_history = [] async def chat(self, message: str): result = await Runner.run(self.agent, message) self.conversation_history.append({"user": message, "assistant": result.final_output}) return result.final_output ``` ## ⚠️ Important Notes * **API Costs**: Monitor your usage as both Perplexity and OpenAI Agents may incur costs * **Rate Limits**: Respect API rate limits and implement appropriate backoff strategies * **Error Handling**: Always implement robust error handling for production applications * **Security**: Keep your API keys secure and never commit them to version control ## 🎯 Use Cases This integration pattern is perfect for: * **🔍 Research Assistants** - Combining real-time search with structured responses * **📊 Data Analysis Tools** - Using Sonar for context and agents for processing * **🤖 Customer Support** - Grounded responses with function calling capabilities * **📚 Educational Applications** - Real-time information with interactive features ## 📚 References * [Perplexity Sonar API Documentation](https://docs.perplexity.ai/home) * [OpenAI Agents SDK Documentation](https://github.com/openai/openai-agents-python) * [AsyncOpenAI Client Reference](https://platform.openai.com/docs/api-reference) * [Function Calling Best Practices](https://platform.openai.com/docs/guides/function-calling) *** **Ready to build?** This integration opens up powerful possibilities for creating intelligent, grounded agents. Start with the basic example and gradually add more sophisticated tools and capabilities! 🚀 # Examples Overview Source: https://docs.perplexity.ai/docs/cookbook/examples/README Ready-to-use applications demonstrating Perplexity Sonar API capabilities # Examples Overview Welcome to the **Perplexity Sonar API Examples** collection! These are production-ready applications that demonstrate real-world use cases of the Sonar API. ## 🚀 Quick Start Navigate to any example directory and follow the instructions in the README.md file. ## 📋 Available Examples ### 🔍 [Fact Checker CLI](fact-checker-cli/) **Purpose**: Verify claims and articles for factual accuracy\ **Type**: Command-line tool\ **Use Cases**: Journalism, research, content verification **Key Features**: * Structured claim analysis with ratings * Source citation and evidence tracking * JSON output for automation * Professional fact-checking workflow **Quick Start**: ```bash theme={null} cd fact-checker-cli/ python fact_checker.py --text "The Earth is flat" ``` *** ### 🤖 [Daily Knowledge Bot](daily-knowledge-bot/) **Purpose**: Automated daily fact delivery system\ **Type**: Scheduled Python application\ **Use Cases**: Education, newsletters, personal learning **Key Features**: * Topic rotation based on calendar * Persistent storage of facts * Configurable scheduling * Educational content generation **Quick Start**: ```bash theme={null} cd daily-knowledge-bot/ python daily_knowledge_bot.py ``` *** ### 🏥 [Disease Information App](disease-qa/) **Purpose**: Interactive medical information lookup\ **Type**: Web application (HTML/JavaScript)\ **Use Cases**: Health education, medical reference, patient information **Key Features**: * Interactive browser interface * Structured medical knowledge cards * Citation tracking for medical sources * Standalone deployment ready **Quick Start**: ```bash theme={null} cd disease-qa/ jupyter notebook disease_qa_tutorial.ipynb ``` *** ### 📊 [Financial News Tracker](financial-news-tracker/) **Purpose**: Real-time financial news monitoring and market analysis\ **Type**: Command-line tool\ **Use Cases**: Investment research, market monitoring, financial journalism **Key Features**: * Real-time financial news aggregation * Market sentiment analysis (Bullish/Bearish/Neutral) * Impact assessment and sector analysis * Investment insights and recommendations **Quick Start**: ```bash theme={null} cd financial-news-tracker/ python financial_news_tracker.py "tech stocks" ``` *** ### 📚 [Academic Research Finder](research-finder/) **Purpose**: Academic literature discovery and summarization\ **Type**: Command-line research tool\ **Use Cases**: Academic research, literature reviews, scholarly work **Key Features**: * Academic source prioritization * Paper citation extraction with DOI links * Research-focused prompting * Scholarly workflow integration **Quick Start**: ```bash theme={null} cd research-finder/ python research_finder.py "quantum computing advances" ``` ## 🔑 API Key Setup All examples require a Perplexity API key. You can set it up in several ways: ### Environment Variable (Recommended) ```bash theme={null} export PPLX_API_KEY="your-api-key-here" ``` ### .env File Create a `.env` file in the example directory: ```bash theme={null} PERPLEXITY_API_KEY=your-api-key-here ``` ### Command Line Argument ```bash theme={null} python script.py --api-key your-api-key-here ``` ## 🛠️ Common Requirements All examples require: * **Python 3.7+** * **Perplexity API Key** ([Get one here](https://docs.perplexity.ai/guides/getting-started)) * **Internet connection** for API calls Additional requirements vary by example and are listed in each `requirements.txt` file. ## 🎯 Choosing the Right Example | **If you want to...** | **Use this example** | | --------------------------- | ---------------------------- | | Verify information accuracy | **Fact Checker CLI** | | Learn something new daily | **Daily Knowledge Bot** | | Look up medical information | **Disease Information App** | | Track financial markets | **Financial News Tracker** | | Research academic topics | **Academic Research Finder** | ## 🤝 Contributing Found a bug or want to improve an example? We welcome contributions! 1. **Report Issues**: Open an issue describing the problem 2. **Suggest Features**: Propose new functionality or improvements 3. **Submit Code**: Fork, implement, and submit a pull request See our [Contributing Guidelines](https://github.com/ppl-ai/api-cookbook/blob/main/CONTRIBUTING.md) for details. ## 📄 License All examples are licensed under the [MIT License](https://github.com/ppl-ai/api-cookbook/blob/main/LICENSE). *** **Ready to explore?** Pick an example above and start building with Perplexity's Sonar API! 🚀 # Daily Knowledge Bot Source: https://docs.perplexity.ai/docs/cookbook/examples/daily-knowledge-bot/README A Python application that delivers interesting facts about rotating topics using the Perplexity AI API # Daily Knowledge Bot A Python application that delivers interesting facts about rotating topics using the Perplexity AI API. Perfect for daily learning, newsletter content, or personal education. ## 🌟 Features * **Daily Topic Rotation**: Automatically selects topics based on the day of the month * **AI-Powered Facts**: Uses Perplexity's Sonar API to generate interesting and accurate facts * **Customizable Topics**: Easily extend or modify the list of topics * **Persistent Storage**: Saves facts to dated text files for future reference * **Robust Error Handling**: Gracefully manages API failures and unexpected errors * **Configurable**: Uses environment variables for secure API key management ## 📋 Requirements * Python 3.6+ * Required packages: * requests * python-dotenv * (optional) logging ## 🚀 Installation 1. Clone this repository or download the script 2. Install the required packages: ```bash theme={null} # Install from requirements file (recommended) pip install -r requirements.txt # Or install manually pip install requests python-dotenv ``` 3. Set up your Perplexity API key: * Create a `.env` file in the same directory as the script * Add your API key: `PERPLEXITY_API_KEY=your_api_key_here` ## 🔧 Usage ### Running the Bot Simply execute the script: ```bash theme={null} python daily_knowledge_bot.py ``` This will: 1. Select a topic based on the current day 2. Fetch an interesting fact from Perplexity AI 3. Save the fact to a dated text file in your current directory 4. Display the fact in the console ### Customizing Topics Edit the `topics.txt` file (one topic per line) or modify the `topics` list directly in the script. Example topics: ``` astronomy history biology technology psychology ocean life ancient civilizations quantum physics art history culinary science ``` ### Automated Scheduling #### On Linux/macOS (using cron): ```bash theme={null} # Edit your crontab crontab -e # Add this line to run daily at 8:00 AM 0 8 * * * /path/to/python3 /path/to/daily_knowledge_bot.py ``` #### On Windows (using Task Scheduler): 1. Open Task Scheduler 2. Create a new Basic Task 3. Set it to run daily 4. Add the action: Start a program 5. Program/script: `C:\path\to\python.exe` 6. Arguments: `C:\path\to\daily_knowledge_bot.py` ## 🔍 Configuration Options The following environment variables can be set in your `.env` file: * `PERPLEXITY_API_KEY` (required): Your Perplexity API key * `OUTPUT_DIR` (optional): Directory to save fact files (default: current directory) * `TOPICS_FILE` (optional): Path to your custom topics file ## 📄 Output Example ``` DAILY FACT - 2025-04-02 Topic: astronomy Saturn's iconic rings are relatively young, potentially forming only 100 million years ago. This means dinosaurs living on Earth likely never saw Saturn with its distinctive rings, as they may have formed long after the dinosaurs went extinct. The rings are made primarily of water ice particles ranging in size from tiny dust grains to boulder-sized chunks. ``` ## 🛠️ Extending the Bot Some ways to extend this bot: * Add email or SMS delivery capabilities * Create a web interface to view fact history * Integrate with social media posting * Add multimedia content based on the facts * Implement advanced scheduling with specific topics on specific days ## ⚠️ Limitations * API rate limits may apply based on your Perplexity account * Quality of facts depends on the AI model * The free version of the Sonar API has a token limit that may truncate longer responses ## 📜 License [MIT License](https://github.com/ppl-ai/api-cookbook/blob/main/LICENSE) ## 🙏 Acknowledgements * This project uses the Perplexity AI API ([https://docs.perplexity.ai/](https://docs.perplexity.ai/)) * Inspired by daily knowledge calendars and fact-of-the-day services # Perplexity Discord Bot Source: https://docs.perplexity.ai/docs/cookbook/examples/discord-py-bot/README A simple discord.py bot that integrates Perplexity's Sonar API to bring AI answers to your Discord server. A simple `discord.py` bot that integrates [Perplexity's Sonar API](https://docs.perplexity.ai/) into your Discord server. Ask questions and get AI-powered answers with web access through slash commands or by mentioning the bot. Discord Bot Demo ## ✨ Features * **🌐 Web-Connected AI**: Uses Perplexity's Sonar API for up-to-date information * **⚡ Slash Command**: Simple `/ask` command for questions * **💬 Mention Support**: Ask questions by mentioning the bot * **🔗 Source Citations**: Automatically formats and links to sources * **🔒 Secure Setup**: Environment-based configuration for API keys ## 🛠️ Prerequisites **Python 3.8+** installed on your system ```bash theme={null} python --version # Should be 3.8 or higher ``` **Active Perplexity API Key** from [Perplexity AI Settings](https://www.perplexity.ai/settings/api) You'll need a paid Perplexity account to access the API. See the [pricing page](https://www.perplexity.ai/pricing) for current rates. **Discord Bot Token** from the [Discord Developer Portal](https://discord.com/developers/applications) ## 🚀 Quick Start ### 1. Repository Setup Clone the repository and navigate to the bot directory: ```bash theme={null} git clone https://github.com/perplexity-ai/api-cookbook.git cd api-cookbook/docs/examples/discord-py-bot/ ``` ### 2. Install Dependencies ```bash theme={null} # Create a virtual environment (recommended) python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate # Install required packages pip install -r requirements.txt ``` ### 3. Configure API Keys 1. Visit [Perplexity AI Account Settings](https://www.perplexity.ai/settings/api) 2. Generate a new API key 3. Copy the key to the .env file Keep your API key secure! Never commit it to version control or share it publicly. 1. Go to the [Discord Developer Portal](https://discord.com/developers/applications) 2. Click **"New Application"** and give it a descriptive name 3. Navigate to the **"Bot"** section 4. Click **"Reset Token"** (or "Add Bot" if first time) 5. Copy the bot token Copy the example environment file and add your keys: ```bash theme={null} cp env.example .env ``` Edit `.env` with your credentials: ```bash title=".env" theme={null} DISCORD_TOKEN="your_discord_bot_token_here" PERPLEXITY_API_KEY="your_perplexity_api_key_here" ``` ## 🎯 Usage Guide ### Bot Invitation & Setup In the Discord Developer Portal: 1. Go to **OAuth2** → **URL Generator** 2. Select scopes: `bot` and `applications.commands` 3. Select bot permissions: `Send Messages`, `Use Slash Commands` 4. Copy the generated URL 1. Paste the URL in your browser 2. Select the Discord server to add the bot to 3. Confirm the permissions ```bash theme={null} python bot.py ``` You should see output confirming the bot is online and commands are synced. ### How to Use **Slash Command:** ``` /ask [your question here] ``` Slash Command Demo **Mention the Bot:** ``` @YourBot [your question here] ``` Mention Command Demo ## 📊 Response Format The bot provides clean, readable responses with: * **AI Answer**: Direct response from Perplexity's Sonar API * **Source Citations**: Clickable links to sources (when available) * **Automatic Truncation**: Responses are trimmed to fit Discord's limits ## 🔧 Technical Details This bot uses: * **Model**: Perplexity's `sonar-pro` model * **Response Limit**: 2000 tokens from API, truncated to fit Discord * **Temperature**: 0.2 for consistent, factual responses * **No Permissions**: Anyone in the server can use the bot # Disease Information App Source: https://docs.perplexity.ai/docs/cookbook/examples/disease-qa/README An interactive browser-based application that provides structured information about diseases using Perplexity's Sonar API # Disease Information App An interactive browser-based application that provides structured information about diseases using Perplexity's Sonar API. This app generates a standalone HTML interface that allows users to ask questions about various diseases and receive organized responses with citations. ![Disease Information App Screenshot](https://via.placeholder.com/800x450.png?text=Disease+Information+App) ## 🌟 Features * **User-Friendly Interface**: Clean, responsive design that works across devices * **AI-Powered Responses**: Leverages Perplexity's Sonar API for accurate medical information * **Structured Knowledge Cards**: Organizes information into Overview, Causes, and Treatments * **Citation Tracking**: Lists sources of information with clickable links * **Client-Side Caching**: Prevents duplicate API calls for previously asked questions * **Standalone Deployment**: Generate a single HTML file that can be used without a server * **Comprehensive Error Handling**: User-friendly error messages and robust error management ## 📋 Requirements * Python 3.6+ * Jupyter Notebook or JupyterLab (for development/generation) * Required packages: * requests * pandas * python-dotenv * IPython ## 🚀 Setup & Installation 1. Clone this repository or download the notebook 2. Install the required packages: ```bash theme={null} # Install from requirements file (recommended) pip install -r requirements.txt # Or install manually pip install requests pandas python-dotenv ipython ``` 3. Set up your Perplexity API key: * Create a `.env` file in the same directory as the notebook * Add your API key: `PERPLEXITY_API_KEY=your_api_key_here` ## 🔧 Usage ### Running the Notebook 1. Open the notebook in Jupyter: ```bash theme={null} jupyter notebook Disease_Information_App.ipynb ``` 2. Run all cells to generate and launch the browser-based application 3. The app will automatically open in your default web browser ### Using the Generated HTML You can also directly use the generated `disease_qa.html` file: 1. Open it in any modern web browser 2. Enter a question about a disease (e.g., "What is diabetes?", "Tell me about Alzheimer's disease") 3. Click "Ask" to get structured information about the disease ### Deploying the App For personal or educational use, simply share the generated HTML file. For production use, consider: 1. Setting up a proper backend to secure your API key 2. Hosting the file on a web server 3. Adding analytics and user management as needed ## 🔍 How It Works This application: 1. Uses a carefully crafted prompt to instruct the AI to output structured JSON 2. Processes this JSON to extract Overview, Causes, Treatments, and Citations 3. Presents the information in a clean knowledge card format 4. Implements client-side API calls with proper error handling 5. Provides a responsive design suitable for both desktop and mobile ## ⚙️ Technical Details ### API Structure The app expects the AI to return a JSON object with this structure: ```json theme={null} { "overview": "A brief description of the disease.", "causes": "The causes of the disease.", "treatments": "Possible treatments for the disease.", "citations": ["https://example.com/citation1", "https://example.com/citation2"] } ``` ### Files Generated * `disease_qa.html` - The standalone application * `disease_app.log` - Detailed application logs (when running the notebook) ### Customization Options You can modify: * The HTML/CSS styling in the `create_html_ui` function * The AI model used (default is "sonar-pro") * The structure of the prompt for different information fields * Output file location and naming ## 🛠️ Extending the App Potential extensions: * Add a Flask/Django backend to secure the API key * Implement user accounts and saved questions * Add visualization of disease statistics * Create a comparison view for multiple diseases * Add natural language question reformatting * Implement feedback mechanisms for answer quality ## ⚠️ Important Notes * **API Key Security**: The current implementation embeds your API key in the HTML file. This is suitable for personal use but not for public deployment. * **Not Medical Advice**: This app provides general information and should not be used for medical decisions. Always consult healthcare professionals for medical advice. * **API Usage**: Be aware of Perplexity API rate limits and pricing for your account. ## 📜 License [MIT License](https://github.com/ppl-ai/api-cookbook/blob/main/LICENSE) ## 🙏 Acknowledgements * This project uses the [Perplexity AI Sonar API](https://docs.perplexity.ai/) * Inspired by interactive knowledge bases and medical information platforms # Fact Checker CLI Source: https://docs.perplexity.ai/docs/cookbook/examples/fact-checker-cli/README A command-line tool that identifies false or misleading claims in articles or statements using Perplexity's Sonar API # Fact Checker CLI A command-line tool that identifies false or misleading claims in articles or statements using Perplexity's Sonar API for web research. ## Features * Analyze claims or entire articles for factual accuracy * Identify false, misleading, or unverifiable claims * Provide explanations and corrections for inaccurate information * Output results in human-readable format or structured JSON * Cite reliable sources for fact-checking assessments * Leverages Perplexity's structured outputs for reliable JSON parsing (for Tier 3+ users) ## Installation ### 1. Install required dependencies ```bash theme={null} # Install from requirements file (recommended) pip install -r requirements.txt # Or install manually pip install requests pydantic newspaper3k ``` ### 2. Make the script executable ```bash theme={null} chmod +x fact_checker.py ``` ## API Key Setup The tool requires a Perplexity API key to function. You can provide it in one of these ways: ### 1. As a command-line argument ```bash theme={null} ./fact_checker.py --api-key YOUR_API_KEY ``` ### 2. As an environment variable ```bash theme={null} export PPLX_API_KEY=YOUR_API_KEY ``` ### 3. In a file Create a file named `pplx_api_key` or `.pplx_api_key` in the same directory as the script: ```bash theme={null} echo "YOUR_API_KEY" > .pplx_api_key chmod 600 .pplx_api_key ``` **Note:** If you're using the structured outputs feature, you'll need a Perplexity API account with Tier 3 or higher access level. ## Quick Start Run the following command immediately after setup: ```bash theme={null} ./fact_checker.py -t "The Earth is flat and NASA is hiding the truth." ``` This will analyze the claim, research it using Perplexity's Sonar API, and return a detailed fact check with ratings, explanations, and sources. ## Usage ### Check a claim ```bash theme={null} ./fact_checker.py --text "The Earth is flat and NASA is hiding the truth." ``` ### Check an article from a file ```bash theme={null} ./fact_checker.py --file article.txt ``` ### Check an article from a URL ```bash theme={null} ./fact_checker.py --url https://www.example.com/news/article-to-check ``` ### Specify a different model ```bash theme={null} ./fact_checker.py --text "Global temperatures have decreased over the past century." --model "sonar-pro" ``` ### Output results as JSON ```bash theme={null} ./fact_checker.py --text "Mars has a breathable atmosphere." --json ``` ### Use a custom prompt file ```bash theme={null} ./fact_checker.py --text "The first human heart transplant was performed in the United States." --prompt-file custom_prompt.md ``` ### Enable structured outputs (for Tier 3+ users) Structured output is disabled by default. To enable it, pass the `--structured-output` flag: ```bash theme={null} ./fact_checker.py --text "Vaccines cause autism." --structured-output ``` ### Get help ```bash theme={null} ./fact_checker.py --help ``` ## Output Format The tool provides output including: * **Overall Rating**: MOSTLY\_TRUE, MIXED, or MOSTLY\_FALSE * **Summary**: A brief overview of the fact-checking findings * **Claims Analysis**: A list of specific claims with individual ratings: * TRUE: Factually accurate and supported by evidence * FALSE: Contradicted by evidence * MISLEADING: Contains some truth but could lead to incorrect conclusions * UNVERIFIABLE: Cannot be conclusively verified with available information * **Explanations**: Detailed reasoning for each claim * **Sources**: Citations and URLs used for verification ## Example Run the following command: ```bash theme={null} ./fact_checker.py -t "The Great Wall of China is visible from the moon." ``` Example output: ``` Fact checking in progress... 🔴 OVERALL RATING: MOSTLY_FALSE 📝 SUMMARY: The claim that the Great Wall of China is visible from the moon is false. This is a common misconception that has been debunked by NASA astronauts and scientific evidence. 🔍 CLAIMS ANALYSIS: Claim 1: ❌ FALSE Statement: "The Great Wall of China is visible from the moon." Explanation: The Great Wall of China is not visible from the moon with the naked eye. NASA astronauts have confirmed this, including Neil Armstrong who stated he could not see the Wall from lunar orbit. The Wall is too narrow and is similar in color to its surroundings when viewed from such a distance. Sources: - NASA.gov - Scientific American - National Geographic ``` ## Limitations * The accuracy of fact-checking depends on the quality of information available through the Perplexity Sonar API. * Like all language models, the underlying AI may have limitations in certain specialized domains. * The structured outputs feature requires a Tier 3 or higher Perplexity API account. * The tool does not replace professional fact-checking services for highly sensitive or complex content. # Financial News Tracker Source: https://docs.perplexity.ai/docs/cookbook/examples/financial-news-tracker/README A real-time financial news monitoring tool that fetches and analyzes market news using Perplexity's Sonar API # Financial News Tracker A command-line tool that fetches and analyzes real-time financial news using Perplexity's Sonar API. Get comprehensive market insights, news summaries, and investment analysis for any financial topic. ## Features * Real-time financial news aggregation from multiple sources * Market sentiment analysis (Bullish/Bearish/Neutral) * Impact assessment for news items (High/Medium/Low) * Sector and company-specific analysis * Investment insights and recommendations * Customizable time ranges (24h to 1 year) * Structured JSON output support * Beautiful emoji-enhanced CLI output ## Installation ### 1. Install required dependencies ```bash theme={null} # Install from requirements file (recommended) pip install -r requirements.txt # Or install manually pip install requests pydantic ``` ### 2. Make the script executable ```bash theme={null} chmod +x financial_news_tracker.py ``` ## API Key Setup The tool requires a Perplexity API key. You can provide it in one of these ways: ### 1. As an environment variable (recommended) ```bash theme={null} export PPLX_API_KEY=YOUR_API_KEY ``` ### 2. As a command-line argument ```bash theme={null} ./financial_news_tracker.py "tech stocks" --api-key YOUR_API_KEY ``` ### 3. In a file Create a file named `pplx_api_key` or `.pplx_api_key` in the same directory: ```bash theme={null} echo "YOUR_API_KEY" > .pplx_api_key chmod 600 .pplx_api_key ``` ## Quick Start Get the latest tech stock news: ```bash theme={null} ./financial_news_tracker.py "tech stocks" ``` This will fetch recent financial news about tech stocks, analyze market sentiment, and provide actionable insights. ## Usage Examples ### Basic usage - Get news for a specific topic ```bash theme={null} ./financial_news_tracker.py "S&P 500" ``` ### Get cryptocurrency news from the past week ```bash theme={null} ./financial_news_tracker.py "cryptocurrency" --time-range 1w ``` ### Track specific company news ```bash theme={null} ./financial_news_tracker.py "AAPL Apple stock" ``` ### Get news about market sectors ```bash theme={null} ./financial_news_tracker.py "energy sector oil prices" ``` ### Output as JSON for programmatic use ```bash theme={null} ./financial_news_tracker.py "inflation rates" --json ``` ### Use a different model ```bash theme={null} ./financial_news_tracker.py "Federal Reserve interest rates" --model sonar ``` ### Enable structured output (requires Tier 3+ API access) ```bash theme={null} ./financial_news_tracker.py "tech earnings" --structured-output ``` ## Time Range Options * `24h` - Last 24 hours (default) * `1w` - Last week * `1m` - Last month * `3m` - Last 3 months * `1y` - Last year ## Output Format The tool provides comprehensive financial analysis including: ### 1. Executive Summary A brief overview of the key financial developments ### 2. Market Analysis * **Market Sentiment**: Overall market mood (🐂 Bullish, 🐻 Bearish, ⚖️ Neutral) * **Key Drivers**: Factors influencing the market * **Risks**: Current market risks and concerns * **Opportunities**: Potential investment opportunities ### 3. News Items Each news item includes: * **Headline**: The main news title * **Impact**: Market impact level (🔴 High, 🟡 Medium, 🟢 Low) * **Summary**: Brief description of the news * **Affected Sectors**: Industries or companies impacted * **Source**: News source attribution ### 4. Investment Insights Actionable recommendations and analysis based on the news ## Example Output ``` 📊 FINANCIAL NEWS REPORT: tech stocks 📅 Period: Last 24 hours 📝 EXECUTIVE SUMMARY: Tech stocks showed mixed performance today as AI-related companies surged while semiconductor stocks faced pressure from supply chain concerns... 📈 MARKET ANALYSIS: Sentiment: 🐂 BULLISH Key Drivers: • Strong Q4 earnings from major tech companies • AI sector momentum continues • Federal Reserve signals potential rate cuts ⚠️ Risks: • Semiconductor supply chain disruptions • Regulatory scrutiny on big tech • Valuation concerns in AI sector 💡 Opportunities: • Cloud computing growth • AI infrastructure plays • Cybersecurity demand surge 📰 KEY NEWS ITEMS: 1. Microsoft Hits All-Time High on AI Growth Impact: 🔴 HIGH Summary: Microsoft stock reached record levels following strong Azure AI revenue... Sectors: Cloud Computing, AI, Software Source: Bloomberg 💼 INSIGHTS & RECOMMENDATIONS: • Consider diversifying within tech sector • AI infrastructure companies show strong momentum • Monitor semiconductor sector for buying opportunities ``` ## Advanced Features ### Custom Queries You can combine multiple topics for comprehensive analysis: ```bash theme={null} # Get news about multiple related topics ./financial_news_tracker.py "NVIDIA AMD semiconductor AI chips" # Track geopolitical impacts on markets ./financial_news_tracker.py "oil prices Middle East geopolitics" # Monitor economic indicators ./financial_news_tracker.py "inflation CPI unemployment Federal Reserve" ``` ### JSON Output For integration with other tools or scripts: ```bash theme={null} ./financial_news_tracker.py "bitcoin" --json | jq '.market_analysis.market_sentiment' ``` ## Tips for Best Results 1. **Be Specific**: Include company tickers, sector names, or specific events 2. **Combine Topics**: Mix company names with relevant themes (e.g., "TSLA electric vehicles") 3. **Use Time Ranges**: Match the time range to your investment horizon 4. **Regular Monitoring**: Set up cron jobs for daily market updates ## Limitations * Results depend on available public information * Not financial advice - always do your own research * Historical data may be limited for very recent events * Structured output requires Tier 3+ Perplexity API access ## Error Handling The tool includes comprehensive error handling for: * Invalid API keys * Network connectivity issues * API rate limits * Invalid queries * Parsing errors ## Integration Examples ### Daily Market Report Create a script for daily updates: ```bash theme={null} #!/bin/bash # daily_market_report.sh echo "=== Daily Market Report ===" > market_report.txt echo "Date: $(date)" >> market_report.txt echo "" >> market_report.txt ./financial_news_tracker.py "S&P 500 market overview" >> market_report.txt ./financial_news_tracker.py "top gaining stocks" >> market_report.txt ./financial_news_tracker.py "cryptocurrency bitcoin ethereum" >> market_report.txt ``` ### Python Integration ```python theme={null} import subprocess import json def get_financial_news(query, time_range="24h"): result = subprocess.run( ["./financial_news_tracker.py", query, "--time-range", time_range, "--json"], capture_output=True, text=True ) if result.returncode == 0: return json.loads(result.stdout) else: raise Exception(f"Error fetching news: {result.stderr}") # Example usage news = get_financial_news("tech stocks", "1w") print(f"Market sentiment: {news['market_analysis']['market_sentiment']}") ``` # Academic Research Finder CLI Source: https://docs.perplexity.ai/docs/cookbook/examples/research-finder/README A command-line tool that uses Perplexity's Sonar API to find and summarize academic literature # Academic Research Finder CLI A command-line tool that uses Perplexity's Sonar API to find and summarize academic literature (research papers, articles, etc.) related to a given question or topic. ## Features * Takes a natural language question or topic as input, ideally suited for academic inquiry. * Leverages Perplexity Sonar API, guided by a specialized prompt to prioritize scholarly sources (e.g., journals, conference proceedings, academic databases). * Outputs a concise summary based on the findings from academic literature. * Lists the primary academic sources used, aiming to include details like authors, year, title, publication, and DOI/link when possible. * Supports different Perplexity models (defaults to `sonar-pro`). * Allows results to be output in JSON format. ## Installation ### 1. Install required dependencies Ensure you are using the Python environment you intend to run the script with (e.g., `python3.10` if that's your target). ```bash theme={null} # Install from requirements file (recommended) pip install -r requirements.txt # Or install manually pip install requests ``` ### 2. Make the script executable (Optional) ```bash theme={null} chmod +x research_finder.py ``` Alternatively, you can run the script using `python3 research_finder.py ...`. ## API Key Setup The tool requires a Perplexity API key (`PPLX_API_KEY`) to function. You can provide it in one of these ways (checked in this order): 1. **As a command-line argument:** ```bash theme={null} python3 research_finder.py "Your query" --api-key YOUR_API_KEY ``` 2. **As an environment variable:** ```bash theme={null} export PPLX_API_KEY=YOUR_API_KEY python3 research_finder.py "Your query" ``` 3. **In a file:** Create a file named `pplx_api_key`, `.pplx_api_key`, `PPLX_API_KEY`, or `.PPLX_API_KEY` in the *same directory as the script* or in the *current working directory* containing just your API key. ```bash theme={null} echo "YOUR_API_KEY" > .pplx_api_key chmod 600 .pplx_api_key # Optional: restrict permissions python3 research_finder.py "Your query" ``` ## Usage Run the script from the `sonar-use-cases/research_finder` directory or provide the full path. ```bash theme={null} # Basic usage python3 research_finder.py "What are the latest advancements in quantum computing?" # Using a specific model python3 research_finder.py "Explain the concept of Large Language Models" --model sonar-small-online # Getting output as JSON python3 research_finder.py "Summarize the plot of Dune Part Two" --json # Using a custom system prompt file python3 research_finder.py "Benefits of renewable energy" --prompt-file /path/to/your/custom_prompt.md # Using an API key via argument python3 research_finder.py "Who won the last FIFA World Cup?" --api-key sk-... # Using the executable (if chmod +x was used) ./research_finder.py "Latest news about Mars exploration" ``` ### Arguments * `query`: (Required) The research question or topic (enclose in quotes if it contains spaces). * `-m`, `--model`: Specify the Perplexity model (default: `sonar-pro`). * `-k`, `--api-key`: Provide the API key directly. * `-p`, `--prompt-file`: Path to a custom system prompt file. * `-j`, `--json`: Output the results in JSON format. ## Example Output (Human-Readable - *Note: Actual output depends heavily on the query and API results*) ``` Initializing research assistant for query: "Recent studies on transformer models in NLP"... Researching in progress... ✅ Research Complete! 📝 SUMMARY: Recent studies on transformer models in Natural Language Processing (NLP) continue to explore architectural improvements, efficiency optimizations, and new applications. Key areas include modifications to the attention mechanism (e.g., sparse attention, linear attention) to handle longer sequences more efficiently, techniques for model compression and knowledge distillation, and applications beyond text, such as in computer vision and multimodal tasks. Research also focuses on understanding the internal workings and limitations of large transformer models. 🔗 SOURCES: 1. Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., ... & Polosukhin, I. (2017). Attention is all you need. Advances in neural information processing systems, 30. (arXiv:1706.03762) 2. Tay, Y., Dehghani, M., Bahri, D., & Metzler, D. (2020). Efficient transformers: A survey. arXiv preprint arXiv:2009.06732. 3. Beltagy, I., Peters, M. E., & Cohan, A. (2020). Longformer: The long-document transformer. arXiv preprint arXiv:2004.05150. 4. Rogers, A., Kovaleva, O., & Rumshisky, A. (2020). A primer in bertology: What we know about how bert works. Transactions of the Association for Computational Linguistics, 8, 842-866. (arXiv:2002.12327) ``` ## Limitations * The ability of the Sonar API to consistently prioritize and access specific academic databases or extract detailed citation information (like DOIs) may vary. The quality depends on the API's search capabilities and the structure of the source websites. * The script performs basic parsing to separate summary and sources; complex or unusual API responses might not be parsed perfectly. Check the raw response in case of issues. * Queries that are too broad or not well-suited for academic search might yield less relevant results. * Error handling for API rate limits or specific API errors could be more granular. # Perplexity API Cookbook Source: https://docs.perplexity.ai/docs/cookbook/index A collection of practical examples and guides for building with Perplexity's API Platform A collection of practical examples and guides for building with [**Perplexity's API Platform**](https://docs.perplexity.ai/) - the fastest, most cost-effective AI answer engine with real-time search capabilities. ## Quick Start To get started with any project in this cookbook: 1. **Browse examples** - Find the use case that matches your needs 2. **Follow the guide** - Each example includes complete setup instructions 3. **Get the code** - Full implementations are available in our [GitHub repository](https://github.com/perplexityai/api-cookbook) 4. **Build and customize** - Use the examples as starting points for your projects ## What's Inside ### [Examples](/docs/cookbook/examples/README) Ready-to-run projects that demonstrate specific use cases and implementation patterns. ### [Showcase](/docs/cookbook/showcase/briefo/) Community-built applications that demonstrate real-world implementations of the API Platform. ### [Integration Guides](/docs/cookbook/articles/memory-management/chat-summary-memory-buffer/README) In-depth tutorials for advanced implementations and integrations with other tools. > **Note**: All complete code examples, scripts, and project files can be found in our [GitHub repository](https://github.com/perplexityai/api-cookbook). The documentation here provides guides and explanations, while the repository contains the full runnable implementations. ## Contributing Have a project built with API Platform? We'd love to feature it! Check our [Contributing Guidelines](https://github.com/perplexityai/api-cookbook/blob/main/CONTRIBUTING.md) to learn how to: * Submit example tutorials * Add your project to the showcase * Improve existing content ## Resources * [API Documentation](https://docs.perplexity.ai/home) * [GitHub Repository](https://github.com/perplexityai/api-cookbook) *** *Maintained by the Perplexity community* # 4Point Hoops | AI Basketball Analytics Platform Source: https://docs.perplexity.ai/docs/cookbook/showcase/4point-Hoops Advanced NBA analytics platform that combines live Basketball-Reference data with Perplexity Sonar to deliver deep-dive player stats, cross-season comparisons and expert-grade AI explanations ![4Point Hoops Dashboard](https://d112y698adiu2z.cloudfront.net/photos/production/software_photos/003/442/047/datas/original.png) **4Point Hoops** is an advanced NBA analytics platform that turns raw basketball statistics into actionable, narrative-driven insights. By scraping Basketball-Reference in real time and routing context-rich prompts to Perplexity's Sonar Pro model, it helps fans, analysts, and fantasy players understand the "why" and "what's next" – not just the numbers.