NAME

Langertha::Engine::Perplexity - Perplexity Agent API (search-augmented)

VERSION

version 0.503

SYNOPSIS

use Langertha::Engine::Perplexity;

my $perplexity = Langertha::Engine::Perplexity->new(
    api_key => $ENV{PERPLEXITY_API_KEY},
    model   => 'sonar-pro',
);

my $response = $perplexity->simple_chat('What are the latest Perl releases?');
print $response;              # the answer text
print $response->citations;   # ArrayRef of search sources

# Streaming
$perplexity->simple_chat_stream(sub {
    print shift->content;
}, 'Summarize recent Perl news');

# Async with Future::AsyncAwait
use Future::AsyncAwait;
my $response = await $perplexity->simple_chat_f('What is new in Perl?');

DESCRIPTION

Provides access to Perplexity's Agent API (POST /v1/agent), the successor to the retired Sonar Chat Completions surface (Sonar Chat Completions reached end of life 2026-09-27). The Agent API speaks the Open-Responses wire envelope (input / instructions / typed output[] / input_tokens usage), not /chat/completions, so this engine composes Langertha::Role::ResponsesCompatible (shared with Langertha::Engine::OpenAIResponses) over a bare Langertha::Engine::Remote for Bearer auth and HTTP.

Perplexity models are search-augmented LLMs with real-time web access; responses carry "citations" in Langertha::Response alongside the generated text.

Models and presets

The four user-facing model ids are kept as the selector; each maps to an Agent API preset, which is what actually reaches the wire. Presets bundle the web_search tool and inline citations automatically — a bare model call on the Agent API no longer searches (web search became opt-in), so the preset path is what preserves Perplexity's search+citations identity.

sonar                 -> preset "fast"
sonar-pro             -> preset "low"
sonar-reasoning-pro   -> preset "medium"
sonar-deep-research   -> preset "high"

$response->model reports the real model the chosen preset ran — a preset is a routing label, not a fixed model (in mid-September 2026 fast, low and medium all resolved to openai/gpt-5.6-luna on the wire; by 2026-09-29 fast resolved to openai/gpt-6-luna), so read the model off the response rather than inferring it from the preset.

Capabilities

Client function tools work: pass tools to chat_f, or set mcp_servers and use chat_with_tools_f. They go out as flat { type => 'function', name, description, parameters } tools, the model's function_call items land on "tool_calls" in Langertha::Response, and the tool loop answers them with function_call_output items. Perplexity never runs a function tool itself. A preset still runs its own web_search alongside your tools (presets merge tools). The echo of a tool turn keeps only what the Agent input accepts: the function calls and the assistant's text; the search results and other built-in tool items are left out. The call turn, its echo (the call with its id and status, then the function_call_output) and a streamed call turn were checked against the live API (2026-09-29). For a turn with search results and an assistant preamble (a constructed turn: the model did not produce one live), only this is live-confirmed: the filtered echo is accepted with HTTP 200. That the Agent input rejects the unfiltered items comes from Perplexity's documentation.

There is no tool_choice and no parallel_tool_calls on the Agent API, so every tool_choice_* capability and parallel_tool_use are off and neither field is ever sent (a forced choice that cannot be sent carps). tool_choice => 'none' is honored by leaving the request's tools out (with a carp); a choice Langertha cannot read is dropped with a carp. A request without tools may still carry earlier function_call and function_call_output items; the Agent API accepts them (checked live, 2026-09-29). Perplexity's built-in tools (web_search, fetch_url, sandbox, ...) are not modelled yet; a native hash of one in tools is sent as given.

No json_object mode: the only structured response_format the Agent API accepts is json_schema (the type enum is json_schema/text; a json_object body is rejected with HTTP 400). A forced named tool still works as structured output — chat_f rewrites it into a top-level response_format=json_schema plus a synthetic Langertha::ToolCall (ADR 0005 rewrite direction 1; Perplexity remains its exemplar), and strict is enforced on the returned JSON. reasoning_effort is accepted (wire reasoning.effort), though the non-reasoning presets (fast/low) echo it back without spending reasoning tokens. Prompt caching is automatic (no request-side key).

Limitations: embeddings and transcription are not supported.

Get your API key at https://www.perplexity.ai/settings/api and set LANGERTHA_PERPLEXITY_API_KEY.

api_key

Perplexity API key, sent as Authorization: Bearer. Defaults to LANGERTHA_PERPLEXITY_API_KEY.

update_request

Adds the Authorization: Bearer {api_key} header. Auth is unchanged from the Sonar surface — only the endpoint and body shape moved to the Agent API.

SEE ALSO

SUPPORT

Issues

Please report bugs and feature requests on GitHub at https://github.com/Getty/langertha/issues.

IRC

Join #langertha on irc.perl.org or message Getty directly.

CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

AUTHOR

Torsten Raudssus <getty@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus https://raudssus.de/.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.