NAME

Langertha::Knarr::Request - Normalized chat request shared across all Knarr protocols

VERSION

version 1.102

DESCRIPTION

The normalized request shape that every Langertha::Knarr::Protocol parser produces and every Langertha::Knarr::Handler receives. Wire-protocol-specific quirks (OpenAI's choices, Anthropic's system outside messages, A2A's JSON-RPC envelope, etc.) are handled by the protocol's parse_chat_request and don't leak into the handler API.

The original wire-format body is preserved in "raw" for handlers (like Langertha::Knarr::Handler::Passthrough) that need to forward it verbatim.

protocol

Required. Short string identifying the parser that produced this request: openai, anthropic, ollama, a2a, acp, agui.

model

Optional model id from the request body.

messages

ArrayRef of message hashes ({ role => ..., content => ... }).

stream

Boolean. Whether the client requested streaming.

temperature, max_tokens, reasoning_effort, seed, parallel_tool_use, prompt_cache_key, tools, tool_choice, response_format, system

Optional generation parameters and tool definitions, if the protocol extracted them. tool_choice and response_format are passed to Langertha::Engine via chat_f in their canonical form; Langertha normalizes them to the target engine's wire format. reasoning_effort is the per-request reasoning effort (e.g. low/medium/high), capability-gated like the other generation parameters. The OpenAI face carries it natively; the Anthropic face's thinking and the Ollama face's think are mapped onto it by Langertha::Knarr::Reasoning.

seed, parallel_tool_use and prompt_cache_key are further per-request controls, each extracted by a protocol parser only where the inbound wire format actually carries the field (OpenAI's top-level seed / parallel_tool_calls / prompt_cache_key, and Ollama's options.seed) and each capability-gated in "chat_f_args". Knarr only validates and forwards them; Langertha does the honoring and places each on the target engine's own wire.

session_id

Optional session id, used for per-session state. Pulled from protocol-specific fields (e.g. OpenAI's user, A2A's sessionId, or the x-session-id header).

raw

The original decoded request body. Useful for passthrough handlers that need to forward without re-encoding.

extra

Per-protocol scratch space (e.g. JSON-RPC id for A2A, run_id for ACP). The Ollama parser records the path the client asked for as path (/api/chat or /api/generate): it picks the answer's shape, and Langertha::Knarr::Handler::Passthrough sends the request to the same path upstream.

The OpenAI, Anthropic and Ollama parsers record the client's auth headers as forward_headers, an ArrayRef of [ name, value ] pairs with one pair per header line the client sent, in its order (a header sent twice is two pairs). Langertha::Knarr takes its own proxy key out of every pair; Langertha::Knarr::Handler::Passthrough sends each pair upstream as a line of its own. Read them with "forward_header_pairs" and "forward_header".

chat_f_args

my @args = $request->chat_f_args($engine);
my $r    = await $engine->chat_f(@args);

Builds a named-argument list suitable for "chat_f" in Langertha::Role::Chat. Always includes messages; conditionally adds tools, tool_choice, response_format, temperature, max_tokens, reasoning_effort, seed, parallel_tool_use, prompt_cache_key when set on the request and the engine reports support for the matching capability via $engine->supports($cap). Engines without supports() get every defined parameter — older Langertha versions accepted unknown args silently.

Per-request generation controls are handed to chat_f as canonical named arguments; Langertha extracts them as controls and places each on the target engine's own wire (top-level reasoning_effort on OpenAI, output_config plus thinking on Anthropic, seed under Ollama's options, OpenAI's parallel_tool_calls / prompt_cache_key, and so on). The capability gate is strict: a control is forwarded only to an engine whose wire actually advertises it, so e.g. a seed is dropped onto an engine that does not compose Langertha::Role::Seed even where its wire would technically accept the field.

response_format is gated on the capability matching the kind of format requested, because Langertha registers the two separately (Langertha::Role::Capabilities): an explicit { type => 'json_schema' } needs response_format_json_schema, while everything else — OpenAI's { type => 'json_object' } and Ollama's bare 'json' — needs only response_format_json_object. Gating both on the schema flag would drop a plain json_object request on an engine that can only do the loose form.

tools and tool_choice are forwarded when the engine supports either tools_native or tools_hermes. Hermes-wire engines (NousResearch, AKI native) carry tools in the system prompt rather than as a native tools field, and Langertha's chat_f renders them there and handles tool_choice per wire, so gating on tools_native alone would silently drop a client's tools on those backends.

forward_header_pairs

for my $pair ( $request->forward_header_pairs ) {
  my ($name, $value) = @$pair;
  ...
}

The client headers recorded in extra->{forward_headers} as a list of [ name, value ] pairs, in their order, repeats kept (copies: changing one leaves the request alone). A forward_headers hash, as a request built by hand may carry, reads as one pair per key, sorted by name. Empty when the request has none.

forward_header

my @values = $request->forward_header('authorization');

Every value of one forwarded header, the name matched without regard to case, in the order the client sent them. Empty when there is none.

SUPPORT

Issues

Please report bugs and feature requests on GitHub at https://github.com/Getty/langertha-knarr/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 <torsten@raudssus.de> https://raudssus.de/

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus.

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