LLMClient for Perplexity's Agent API: POST <baseUrl>/v1/agent, Perplexity's canonical path for its OpenAI Responses-format endpoint (/v1/responses is its alias).
The request and response shapes are those of Perplexity's API reference ("Create Agent Response", https://docs.perplexity.ai/api-reference/agent-post) and its Agent API guides, read 2026-11-05. Nothing here has been run against the live service; the @Cloud suite PerplexitySmokeSpec in modules/it does that with a key.
== Request ==
The model goes in model, in the Agent API's provider/model form. System messages are joined, in order, into instructions; every other message becomes an input item: a user or assistant turn a message item, a tool call a function_call item (its arguments a JSON string) and a ToolMessage a function_call_output item carrying the call's call_id. Only text parts are sent; any other part is refused before anything is sent.
temperature is always sent, top_p when not 1.0 and max_output_tokens when set. The Agent API rejects an anthropic/ model without max_output_tokens, so such a request that sets no limit is sent the config's reserveCompletion. CompletionOptions.reasoning is sent as reasoning.effort (ReasoningEffort.None as minimal, the least the API takes; budgetTokens has no counterpart). The penalties have no counterpart in the Agent API and are not sent. A ResponseFormat.JsonSchema is sent as response_format ({"type":"json_schema","json_schema":{"name","schema","strict"}}); the Agent API takes no plain JSON mode, so ResponseFormat.Json is refused before anything is sent.
== Tools and web search ==
With webSearch on (the default) every request offers Perplexity's web_search tool, which Perplexity runs itself and bills per search; the model decides whether to search. CompletionOptions.tools are sent as function tools. A function_call item in the reply becomes a ToolCall whose id is the item's call_id. A model may attach a thought_signature to a call, which Perplexity says to send back with it: it is kept as a sealed ThinkingBlock.Opaque block of provider perplexity and replayed on the call it came with, only to the same provider and model (see ThinkingReplay.bindOrigin).
== Reply ==
The answer is the text of the message items' output_text parts. Completion.citations holds the url_citation annotations on that text, then each result of the search_results items (URL, title, and the snippet as citedText) whose URL is not already there: the answer's [web:N] markers point at those results. A response whose status is failed, or anything but completed or incomplete, is an error; incomplete (a limit reached) is returned as an answer cut short, with finish reason length on a stream. The usage's input_tokens_details and output_tokens_details.reasoning_tokens fill the cached and thinking token counts, and the cost Perplexity reports (usage.cost.total_cost, in USD) is the completion's estimatedCost. The Agent API returns no reasoning text, so a completion has no thinking text.
== Streaming ==
stream: true returns server-sent events, each a JSON object discriminated by type. Each response.output_text.delta is passed on as a content chunk; the stream's response.completed event carries the whole response, which gives the tool calls (sent as whole calls after the text), citations and usage. A response.failed event, or a stream that ends without response.completed, is an error.
Value parameters
- config
-
model, key, endpoint and web-search setting.
- exchangeLogging
-
optional provider exchange logging.
- httpClient
-
the HTTP client; by default one built from the config's network settings.
- metrics
-
receives per-call latency and token-usage events.
Attributes
- Companion
- object
- Graph
-
- Supertypes
-
trait BaseLifecycleLLMClienttrait MetricsRecordingtrait LLMClienttrait AutoCloseableclass Objecttrait Matchableclass Any