NAME
Langertha::Chat - Chat abstraction wrapping an engine with optional overrides
VERSION
version 0.503
SYNOPSIS
use Langertha::Engine::OpenAI;
use Langertha::Chat;
my $engine = Langertha::Engine::OpenAI->new(
api_key => $ENV{OPENAI_API_KEY},
model => 'gpt-4o',
);
my $chat = Langertha::Chat->new(
engine => $engine,
system_prompt => 'You are a helpful assistant.',
plugins => ['Langfuse'],
);
my $reply = $chat->simple_chat('Hello!');
# With MCP tool calling
my $chat_tools = Langertha::Chat->new(
engine => $engine,
mcp_servers => [$mcp],
plugins => ['Langfuse'],
);
my $result = $chat_tools->simple_chat_with_tools('List files in /tmp');
DESCRIPTION
Langertha::Chat wraps any engine that consumes Langertha::Role::Chat and adds optional overrides for model, system prompt, and temperature, plus plugin lifecycle hooks via Langertha::Role::PluginHost.
Use this class when you want to share a single engine instance across multiple chat contexts with different configurations, or when you need plugin observability (e.g. Langertha::Plugin::Langfuse) without modifying the engine itself.
engine
The LLM engine to delegate chat requests to. Must consume Langertha::Role::Chat.
system_prompt
Optional system prompt. When set, prepended to messages for each request in place of the engine's own system_prompt. When not set, the engine's system_prompt is sent, exactly as the engine's own chat_messages would send it. System messages the engine itself mandates still apply either way: with Langertha::Engine::NousResearch and reasoning enabled, its reasoning_prompt leads the conversation, followed by this system prompt. Plugins see these system messages in the conversation passed to plugin_before_llm_call.
model
Optional model name override. When set, it is passed to the engine's request builder as a per-request model through %extra: it replaces the model in the request body, or in the URL on engines that name the model there (Langertha::Engine::Gemini, Langertha::Engine::AKI). It does not change the engine's chat_model, and every model-scoped decision (capabilities, tool wire format, reasoning profile, body details) is still taken for chat_model, as for a model passed to "chat_f" in Langertha::Role::Chat. When one of those decisions that the call uses would differ for this model, each chat call warns once and names the decisions; the request is sent unchanged. For a different model, use an engine whose chat_model is that model.
temperature
Optional temperature override. When set, overrides the engine's temperature.
mcp_servers
ArrayRef of MCP client objects for tool calling — any Net::Async::MCP-compatible client (for example a Net::Async::MCP client as used by the langertha-raider distribution). Each must respond to list_tools and call_tool.
tool_max_iterations
Maximum tool-calling round trips. Defaults to 10.
simple_chat
my $response = $chat->simple_chat('Hello!');
Sends a synchronous chat request. Fires plugin_before_llm_call and plugin_after_llm_response hooks.
simple_chat_f
my $response = await $chat->simple_chat_f('Hello!');
Async version of "simple_chat".
simple_chat_stream
my $content = $chat->simple_chat_stream(sub { print shift->content }, 'Hi');
Synchronous streaming chat. Calls $callback with each chunk.
simple_chat_with_tools
my $text = $chat->simple_chat_with_tools(@messages);
Synchronous tool-calling chat loop. Gathers tools from "mcp_servers", sends chat requests, executes tool calls, and iterates until the LLM returns a final text response. Fires plugin hooks at each step: plugin_before_llm_call, plugin_after_llm_response, plugin_before_tool_call, and plugin_after_tool_call.
Each reply is read by the engine's chat_response, as in "chat_f" in Langertha::Role::Chat: a response whose body reports an error fails with the same text, the final text is the reply's content, and the calls run are its "tool_calls" in Langertha::Response. plugin_after_llm_response receives the raw decoded wire body before it is read, and the body it returns is what the turn is read from: the calls run, the final text and the assistant turn echoed back to the provider all follow its edits, so a call a plugin removes is neither run nor echoed. A failed request dies with tool chat request failed, in the sync and the async loop alike. A call whose arguments were cut off by the token limit is not run, a call whose arguments otherwise do not decode is answered with an error result, a call to an unknown tool is answered with an error result, and a tool name two servers offer runs on the first, and a blocked prompt dies with prompt blocked, as in "chat_with_tools_f" in Langertha::Role::Tools. Whether a tool is unknown is decided on the name plugin_before_tool_call returns: every call reaches the plugins, and one may map a hallucinated name onto a real tool.
simple_chat_with_tools_f
my $text = await $chat->simple_chat_with_tools_f(@messages);
Async version of "simple_chat_with_tools".
SEE ALSO
Langertha::Role::PluginHost - Plugin system consumed by this class
Langertha::Role::Chat - Chat role required by the engine
Langertha::Role::Tools - Tool-calling role required for MCP methods
Langertha::Plugin::Langfuse - Observability plugin for chat sessions
Langertha::Embedder - Embedding counterpart to this class
Langertha::ImageGen - Image generation counterpart to this class
Langertha::Raider - Autonomous agent with full conversation history
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.