Skip to main content

Overview

This guide shows how to expose Perplexity’s Search API to an OpenAI model as a function tool. The Responses API uses a manual tool-call loop: the model emits a function_call item with a call_id, you execute the tool (in this case, call client.search.create), and you send the result back as a function_call_output item paired by call_id. The loop continues until the response no longer contains pending function calls.
This page uses the Responses API (client.responses.create), the newer OpenAI surface. The tool shape is flat ({type: "function", name, description, parameters, strict}) — different from the legacy chat.completions function-calling shape that nests under function: {…}.

Prerequisites

Tool definition

The Responses API takes a flat tool object: type, name, description, parameters (JSON Schema), and optional strict. The description below was tuned for Perplexity’s Search API; keep it verbatim — the wording is what produces good, short, keyword-style queries.
Strict mode constraints. When strict: true, the JSON Schema must set additionalProperties: false and list every property in required. OpenAI rejects maxItems/minItems and similar constraints in strict mode — enforce the “max three queries” guidance through the description, then truncate defensively in your handler.

Tool handler

The handler is a thin wrapper around client.search.create. The Search API natively accepts an array of queries, so the array the model emits can be passed straight through.

Tool-call loop

The Responses API returns response.output as a flat list of items. Walk it for items whose type is "function_call", execute each call, and append a paired function_call_output item to the running input array. Re-call responses.create until the response has no more function calls.

Streaming

For streaming, use client.responses.stream(...). The SDK emits typed events: response.output_item.added when a function_call item starts, response.function_call_arguments.delta for each chunk of the arguments JSON, and response.function_call_arguments.done when the argument string is complete. The loop structure is otherwise identical to the non-streaming version.

Notes

  • call_id pairs requests with results. Every function_call_output item must include the originating call_id. Multiple parallel function calls in one assistant turn each get their own paired output.
  • Server-side state. Instead of resending the whole input array on each turn, you can pass previous_response_id=<id> and only append new items. This is useful for long agent loops.
  • output_text shortcut. response.output_text flattens the assistant text content for you. If you need granular access (annotations, segments), iterate response.output and pull output_text blocks out of the message item.
  • Domains and dates. Pass search_domain_filter, country, and other Search API parameters inside run_web_search if you want fixed retrieval constraints. See the Search API quickstart for the full parameter list.

Next Steps

Use with Anthropic SDK

Wire Search API into the Anthropic Messages API.

Use with Gemini SDK

Wire Search API into Google’s google-genai SDK.

Search API Quickstart

Full Search API parameter reference.

Search Best Practices

Patterns for production search workloads.