Langertha-Knarr
view release on metacpan or search on metacpan
lib/Langertha/Knarr.pm view on Meta::CPAN
__PACKAGE__->meta->make_immutable;
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Langertha::Knarr - Universal LLM hub â proxy, server, and translator across OpenAI/Anthropic/Ollama/A2A/ACP/AG-UI
=head1 VERSION
version 1.100
=head1 SYNOPSIS
The fastest way to use Knarr is the Docker image:
docker run -e ANTHROPIC_API_KEY -p 8080:8080 raudssus/langertha-knarr
ANTHROPIC_BASE_URL=http://localhost:8080 claude
The Perl API behind it:
use IO::Async::Loop;
use Langertha::Knarr;
use Langertha::Knarr::Config;
use Langertha::Knarr::Router;
use Langertha::Knarr::Handler::Router;
my $loop = IO::Async::Loop->new;
my $config = Langertha::Knarr::Config->new(file => 'knarr.yaml');
my $router = Langertha::Knarr::Router->new(config => $config);
my $knarr = Langertha::Knarr->new(
handler => Langertha::Knarr::Handler::Router->new(router => $router),
loop => $loop,
listen => $config->listen,
);
$knarr->run; # blocks; OpenWebUI etc. can now connect
=head1 DESCRIPTION
Langertha::Knarr is a universal LLM hub that exposes any backend â a
L<Langertha::Raider>, a raw L<Langertha::Engine>, a remote A2A or ACP
agent, or any custom L<Langertha::Knarr::Handler> â over the standard
LLM HTTP wire protocols spoken by OpenWebUI, the OpenAI / Anthropic /
Ollama SDKs, and the agent ecosystems around A2A, ACP, and AG-UI.
By default a single running Knarr answers OpenAI
C</v1/chat/completions>, Anthropic C</v1/messages>, Ollama
C</api/chat>, A2A's C</.well-known/agent.json> plus JSON-RPC C</>,
ACP's C</runs>, and AG-UI's C</awp> simultaneously on every listening
port. The same handler implementation drives all of them.
Knarr 1.000 is built on L<IO::Async> and L<Net::Async::HTTP::Server>
with native L<Future::AsyncAwait> integration into Langertha engines,
so streaming works end-to-end token-by-token without any thread or
event-loop bridges.
=head1 ARCHITECTURE
Three pluggable layers:
=over
=item B<Protocols>
Wire formats live in C<Langertha::Knarr::Protocol::*>. Each consumes
L<Langertha::Knarr::Protocol> and is loaded by default. See
L<Langertha::Knarr::Protocol::OpenAI>,
L<Langertha::Knarr::Protocol::Anthropic>,
L<Langertha::Knarr::Protocol::Ollama>,
L<Langertha::Knarr::Protocol::A2A>,
L<Langertha::Knarr::Protocol::ACP>,
L<Langertha::Knarr::Protocol::AGUI>.
=item B<Handlers>
Backend logic â what answers the request. Knarr ships with
L<Langertha::Knarr::Handler::Router> (the default, modelâengine via
L<Langertha::Knarr::Router>), L<Langertha::Knarr::Handler::Engine>
(single engine), L<Langertha::Knarr::Handler::Raider> (per-session
agent), L<Langertha::Knarr::Handler::Passthrough> (raw HTTP forward),
L<Langertha::Knarr::Handler::A2AClient> /
L<Langertha::Knarr::Handler::ACPClient> (consume remote agents), and
L<Langertha::Knarr::Handler::Code> (coderef-backed for tests). Implement
L<Langertha::Knarr::Handler> to write your own. Decorators
(L<Langertha::Knarr::Handler::Tracing>,
L<Langertha::Knarr::Handler::RequestLog>) wrap any inner handler and
add behavior on top â they themselves consume the Handler role and
compose freely.
=item B<Transport>
Default is L<Net::Async::HTTP::Server> with chunked SSE / NDJSON
streaming on one or more listen sockets. For Plack deployments,
L<Langertha::Knarr::PSGI> wraps the same Knarr instance into a PSGI
app (buffered â see its docs for the streaming caveat).
=back
=head2 handler
Required. An object consuming L<Langertha::Knarr::Handler>.
=head2 listen
ArrayRef of C<host:port> strings or C<< { host => ..., port => ... } >>
hashes. Defaults to a single entry composed from L</host> and L</port>.
=head2 host
Default C<127.0.0.1>. Used when L</listen> is not given.
=head2 port
Default C<8088>. Used when L</listen> is not given.
=head2 loop
Optional L<IO::Async::Loop> instance. Defaults to a fresh one.
=head2 protocols
ArrayRef of protocol class basenames to load. Defaults to all six
shipped protocols.
=head2 auth_token
Optional shared secret. When set, every incoming request must present
it as C<Authorization: Bearer> or C<x-api-key>. Discovery routes
(C</.well-known/agent.json>) stay anonymous.
=head2 start
$knarr->start;
Binds all listen sockets and registers the dispatcher. Returns
C<$self>. Does not enter the event loop.
=head2 run
$knarr->run; # blocks
Calls L</start> if needed, then enters the L</loop> and blocks.
=head2 session
my $session = $knarr->session($id);
Returns the L<Langertha::Knarr::Session> for the given id, creating
one on demand. Used internally by the dispatcher.
=head1 SUPPORT
=head2 Issues
Please report bugs and feature requests on GitHub at
( run in 1.369 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )