NAME
Langertha - The clan of fierce vikings with 🪓 and 🛡️ to AId your rAId
VERSION
version 0.303
SYNOPSIS
my $system_prompt = 'You are a helpful assistant.';
# Local models via Ollama
use Langertha::Engine::Ollama;
my $ollama = Langertha::Engine::Ollama->new(
url => 'http://127.0.0.1:11434',
model => 'llama3.1',
system_prompt => $system_prompt,
);
print $ollama->simple_chat('Do you wanna build a snowman?');
# OpenAI
use Langertha::Engine::OpenAI;
my $openai = Langertha::Engine::OpenAI->new(
api_key => $ENV{OPENAI_API_KEY},
model => 'gpt-4o-mini',
system_prompt => $system_prompt,
);
print $openai->simple_chat('Do you wanna build a snowman?');
# Anthropic Claude
use Langertha::Engine::Anthropic;
my $claude = Langertha::Engine::Anthropic->new(
api_key => $ENV{ANTHROPIC_API_KEY},
model => 'claude-sonnet-4-6',
);
print $claude->simple_chat('Generate Perl Moose classes to represent GeoJSON data.');
# Google Gemini
use Langertha::Engine::Gemini;
my $gemini = Langertha::Engine::Gemini->new(
api_key => $ENV{GEMINI_API_KEY},
model => 'gemini-2.5-flash',
);
print $gemini->simple_chat('Explain the difference between Moose and Moo.');
DESCRIPTION
Langertha provides a unified Perl interface for interacting with various Large Language Model (LLM) APIs. It abstracts away provider-specific differences, giving you a consistent API whether you're using OpenAI, Anthropic Claude, Ollama, Groq, Mistral, or other providers.
THIS API IS WORK IN PROGRESS.
Key Features
20 engines -- unified API across cloud and local LLM providers
Chat, streaming, embeddings, transcription, image generation
MCP tool calling -- automatic multi-round tool loops via Net::Async::MCP
Raider -- autonomous agent with history, compression, and plugins
Response metadata -- token usage, model, timing, rate limits
Async/await via Future::AsyncAwait, sync via LWP::UserAgent
Langfuse observability -- traces, generations, and tool spans
Dynamic model discovery -- query provider APIs with caching
Chain-of-thought -- native extraction and
<think>tag filteringPlugin system for extending Raider, Chat, Embedder, and ImageGen
Class Sugar
Langertha can set up your package as a Raider subclass or Plugin role:
# Build a custom Raider agent
package MyAgent;
use Langertha qw( Raider );
plugin 'Langfuse';
around plugin_before_llm_call => async sub {
my ($orig, $self, $conversation, $iteration) = @_;
$conversation = await $self->$orig($conversation, $iteration);
# ... custom logic ...
return $conversation;
};
__PACKAGE__->meta->make_immutable;
# Build a custom Plugin
package MyApp::Guardrails;
use Langertha qw( Plugin );
around plugin_before_tool_call => async sub {
my ($orig, $self, $name, $input) = @_;
my @result = await $self->$orig($name, $input);
return unless @result;
return if $name eq 'dangerous_tool';
return @result;
};
use Langertha qw( Raider ) imports Moose and Future::AsyncAwait, sets Langertha::Raider as superclass, and provides the plugin function for applying plugins by short name.
use Langertha qw( Plugin ) imports Moose and Future::AsyncAwait, and sets Langertha::Plugin as superclass.
Engine Modules
Langertha::Engine::Anthropic - Claude models (Sonnet, Opus, Haiku)
Langertha::Engine::OpenAI - GPT-4, GPT-4o, GPT-3.5, o1, embeddings
Langertha::Engine::Ollama - Local LLM hosting via https://ollama.com/
Langertha::Engine::Groq - Fast inference API
Langertha::Engine::Mistral - Mistral AI models
Langertha::Engine::DeepSeek - DeepSeek models
Langertha::Engine::MiniMax - MiniMax AI models (M2.5, M2.1)
Langertha::Engine::Gemini - Google Gemini models (Flash, Pro)
Langertha::Engine::vLLM - vLLM inference server
Langertha::Engine::HuggingFace - HuggingFace Inference Providers
Langertha::Engine::Perplexity - Perplexity AI models
Langertha::Engine::NousResearch - Nous Research (Hermes models)
Langertha::Engine::Cerebras - Cerebras (wafer-scale, fastest inference)
Langertha::Engine::OpenRouter - OpenRouter (300+ models, meta-provider)
Langertha::Engine::Replicate - Replicate (thousands of open-source models)
Langertha::Engine::OllamaOpenAI - Ollama via OpenAI-compatible API
Langertha::Engine::LlamaCpp - llama.cpp server (chat, embeddings)
Langertha::Engine::AKI - AKI.IO native API (EU/Germany)
Langertha::Engine::AKIOpenAI - AKI.IO via OpenAI-compatible API
Langertha::Engine::Whisper - OpenAI Whisper speech-to-text
Roles
Roles provide composable functionality to engines:
Langertha::Role::Chat - Synchronous and async chat methods
Langertha::Role::HTTP - HTTP request/response handling
Langertha::Role::Streaming - Streaming response processing
Langertha::Role::JSON - JSON encode/decode
Langertha::Role::OpenAICompatible - OpenAI-compatible API behaviour
Langertha::Role::SystemPrompt - System prompt attribute
Langertha::Role::Temperature - Temperature parameter
Langertha::Role::ResponseSize - Max response size parameter
Langertha::Role::ResponseFormat - Response format (JSON mode)
Langertha::Role::ContextSize - Context window size parameter
Langertha::Role::Seed - Deterministic seed parameter
Langertha::Role::Models - Model listing
Langertha::Role::Embedding - Embedding generation
Langertha::Role::Transcription - Audio transcription
Langertha::Role::Tools - Tool/function calling
Langertha::Role::ImageGeneration - Image generation
Langertha::Role::KeepAlive - Keep-alive duration for local models
Langertha::Role::PluginHost - Plugin system for wrapper classes and Raider
Langertha::Role::Langfuse - Langfuse observability integration (engine-level)
Langertha::Role::OpenAPI - OpenAPI spec support
Wrapper Classes
These classes wrap an engine with optional overrides and plugin lifecycle hooks:
Langertha::Chat - Chat wrapper with system prompt, model, and temperature overrides
Langertha::Embedder - Embedding wrapper with optional model override
Langertha::ImageGen - Image generation wrapper with model, size, and quality overrides
Plugins
Langertha::Plugin - Base class for all plugins
Langertha::Plugin::Langfuse - Langfuse observability (traces, generations, spans)
Data Objects
Langertha::Response - LLM response with content, usage, and rate limit metadata
Langertha::RateLimit - Normalized rate limit data from HTTP response headers
Langertha::Stream - Iterator over streaming chunks
Langertha::Stream::Chunk - A single chunk from a streaming response
Langertha::Raider - Autonomous agent with history and tool calling
Langertha::Raider::Result - Typed raid result (final, question, pause, abort)
Langertha::Request::HTTP - Internal HTTP request object
Streaming
All engines that implement Langertha::Role::Chat support streaming. There are several ways to consume a stream:
Synchronous with callback:
$engine->simple_chat_stream(sub {
my ($chunk) = @_;
print $chunk->content;
}, 'Tell me a story');
Synchronous with iterator (Langertha::Stream):
my $stream = $engine->simple_chat_stream_iterator('Tell me a story');
while (my $chunk = $stream->next) {
print $chunk->content;
}
Async with Future (traditional):
my $future = $engine->simple_chat_f('Hello');
my $response = $future->get;
my $future = $engine->simple_chat_stream_f('Tell me a story');
my ($content, $chunks) = $future->get;
Async with Future::AsyncAwait (recommended):
use Future::AsyncAwait;
async sub chat_with_ai {
my ($engine) = @_;
my $response = await $engine->simple_chat_f('Hello');
say "AI says: $response";
return $response;
}
async sub stream_chat {
my ($engine) = @_;
my ($content, $chunks) = await $engine->simple_chat_stream_realtime_f(
sub { print shift->content },
'Tell me a story',
);
say "\nReceived ", scalar(@$chunks), " chunks";
return $content;
}
chat_with_ai($engine)->get;
stream_chat($engine)->get;
The _f methods use IO::Async and Net::Async::HTTP internally, loaded lazily only when you call them. See examples/async_await_example.pl for complete working examples.
Using with Mojolicious:
use Mojo::Base -strict;
use Future::Mojo;
use Langertha::Engine::OpenAI;
my $openai = Langertha::Engine::OpenAI->new(
api_key => $ENV{OPENAI_API_KEY},
model => 'gpt-4o-mini',
);
my $future = $openai->simple_chat_stream_realtime_f(
sub { print shift->content },
'Hello!',
);
$future->on_done(sub {
my ($content, $chunks) = @_;
say "Done: $content";
});
Mojo::IOLoop->start;
Response Metadata
simple_chat returns Langertha::Response objects that stringify to text content (backward compatible) but carry full metadata:
my $r = $engine->simple_chat('Hello!');
print $r; # prints the text
say $r->model; # actual model used
say $r->prompt_tokens; # input tokens
say $r->completion_tokens; # output tokens
say $r->total_tokens; # total
say $r->finish_reason; # stop, end_turn, tool_calls, ...
say $r->thinking; # chain-of-thought (if available)
Rate Limiting
Rate limit information from HTTP response headers is extracted automatically into Langertha::RateLimit objects. Available per-response and on the engine:
if ($r->has_rate_limit) {
say $r->requests_remaining;
say $r->tokens_remaining;
say $r->rate_limit->requests_reset;
}
# Engine always reflects the latest response
say $engine->rate_limit->requests_remaining
if $engine->has_rate_limit;
Supported: OpenAI, Groq, Cerebras, OpenRouter, Replicate, HuggingFace (x-ratelimit-*) and Anthropic (anthropic-ratelimit-*).
MCP Tool Calling
Integrates with Net::Async::MCP for automatic multi-round tool calling:
my $engine = Langertha::Engine::OpenAI->new(
api_key => $ENV{OPENAI_API_KEY},
mcp_servers => [$mcp],
);
my $response = await $engine->chat_with_tools_f('Search for Perl modules');
Works with all engines that support tool calling. See Langertha::Role::Tools.
Raider (Autonomous Agent)
Langertha::Raider is a stateful agent with conversation history, MCP tool calling, context compression, session history, and a plugin system:
my $raider = Langertha::Raider->new(
engine => $engine,
mission => 'You are a code explorer.',
);
my $r1 = await $raider->raid_f('What files are in lib/?');
my $r2 = await $raider->raid_f('Read the main module.');
Langfuse Observability
Every engine has Langfuse observability built in. Set LANGFUSE_PUBLIC_KEY and LANGFUSE_SECRET_KEY env vars to enable auto-instrumented traces and generations. See Langertha::Role::Langfuse.
Extensions
The LangerthaX namespace is reserved for third-party extensions. See LangerthaX.
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/Getty/langertha/issues.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHOR
Torsten Raudssus <torsten@raudssus.de> https://raudss.us/
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.