NAME
Langertha::Knarr::Protocol::Ollama - Ollama-compatible wire protocol (/api/chat, /api/generate, /api/tags, /api/version, /api/show) for Knarr
VERSION
version 1.102
DESCRIPTION
Implements the Ollama wire format on top of Langertha::Knarr::Protocol. Loaded by default.
POST /api/chat,POST /api/generate— chat with NDJSON streaming;/api/generateanswers in Ollama's generate shape, the text onresponseinstead ofmessage(see "format_chat_response")GET /api/tags— model listingGET /api/version— version probe, answered with Ollama's shape{"version":"x.y.z"}and the Ollama version Knarr claims compatibility with ("ollama_compat_version" in Langertha::Knarr), not Knarr's own versionPOST /api/show— model details for a listed model (see "format_show_response");modelor the legacynamein the body,400without one, Ollama's404{"error":"model 'x' not found"}for a model Knarr does not list
The client's Authorization header is kept as forward_headers, like the OpenAI and Anthropic protocols do, so a Langertha::Knarr::Handler::Passthrough in the handler chain reaches an authenticated remote Ollama with it.
Streaming uses newline-delimited JSON (NDJSON) rather than SSE — the Content-Type is application/x-ndjson and each chunk is a single JSON object per line. The final chunk has done: true.
reasoning
The Langertha::Knarr::Reasoning that maps the body's think (a boolean or a level string) onto the request's reasoning_effort. Pass your own to override the level think: true maps to.
format_chat_response
my ($status, $headers, $body) = $proto->format_chat_response( $response, $request );
The non-streaming answer: model, created_at, done, done_reason and the usage counters (prompt_eval_count, eval_count, ...) when the backend reported usage. A /api/chat request gets the text on message (with tool_calls), a /api/generate request on response, as Ollama answers it -- streaming alike, where every chunk carries its piece on message.content or response and the final {"done": true} line an empty one, with the usage counters when the backend reported usage.
format_error_response
my ($status, $headers, $body) = $proto->format_error_response( 404, "model 'x' not found" );
Ollama's error answer: {"error":"..."} with a plain string, not the {"error":{"message":...}} object of the OpenAI wire.
format_show_response
my ($status, $headers, $body) = $proto->format_show_response( $model, {
capabilities => [ 'completion', 'tools' ],
context_length => 131072, # optional
} );
The POST /api/show answer for a model Knarr serves (k29). Only what Knarr knows is claimed: capabilities as given, model_info with general.architecture (knarr) and knarr.context_length when a context length is known -- the pair VS Code Copilot reads, {} otherwise -- and empty details, template and parameters, since there are no local weights, template or Modelfile behind a routed model.
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.