NAME
Langertha::ToolCall - Immutable canonical tool invocation emitted by an LLM
VERSION
version 0.503
synthetic
Boolean. True when the tool call was synthesized by Langertha — for example when "chat_f" in Langertha::Role::Chat rewrote a forced named tool into a response_format JSON Schema request and parsed the output back into a ToolCall. False (the default) for native model output.
to_hash (and therefore TO_JSON) always carries this flag, so a serialized trace can tell a synthesized call apart from a native one — without it a forced-tool fallback would look exactly like a call the model decided to make.
arguments_undecodable
Boolean. True when the provider sent arguments that do not decode to a JSON object (typically a JSON string cut off when the reply hit its token limit); "arguments" is then {}. The MCP tool loops do not run such a call: when the reply ended on its token limit they drop it, otherwise they answer it with an error result naming "arguments_error". Missing or empty arguments are not undecodable.
arguments_error
The reason the arguments did not decode, set whenever "arguments_undecodable" is true: the JSON parser's message (without its source location) or not a JSON object.
locate
my $raw_calls = Langertha::ToolCall->locate( $fmt, $data );
Returns an ArrayRef of the raw tool-call structures in a decoded response for the wire $fmt, without parsing them. Only calls the client must execute are located; a server-side call item (web_search_call, mcp_call, ...) never is (see Langertha::ServerToolCall). On responses it croaks on an output item the client must answer that Langertha does not map -- custom_tool_call, computer_call, local_shell_call, apply_patch_call, mcp_approval_request, a tool_search_call with execution => 'client' -- rather than report no calls. Croaks on an unknown $fmt.
extract
my @calls = Langertha::ToolCall->extract( $fmt, $data );
The canonical inbound door: every tool call the client must execute in a decoded response, as Langertha::ToolCall objects (possibly none). Built on "locate", so on the responses wire it croaks on a client-actionable output item Langertha cannot map (mcp_approval_request, computer_call, custom_tool_call, local_shell_call, apply_patch_call, a client tool_search_call) instead of returning an empty list that looks like "the model is done". Croaks when $fmt is a reference.
extract_sniff
my @calls = Langertha::ToolCall->extract_sniff( $data );
"extract" for a caller with no wire format in scope: sniffs the format from the top-level shape, then extracts. Returns an empty list for an unknown shape. Croaks like "extract", including on a client-actionable responses item.
extract_hermes_from_text
my ( $clean, $calls ) = Langertha::ToolCall->extract_hermes_from_text($text);
my ( $clean, $calls ) = Langertha::ToolCall->extract_hermes_from_text(
$text, tag => 'function_call' );
Lifts Hermes-style <tool_call>{"name":...,"arguments":{...}}</tool_call> blocks out of model text. Returns the trimmed text without the lifted blocks and an ArrayRef of Langertha::ToolCall. tag names the call tag (default tool_call); engines pass their hermes_call_tag. A block that carries no call (invalid JSON, a non-object, an object without a name) stays in the text where it was. arguments that are not a JSON object (or a string that does not decode to one) become {} with "arguments_undecodable" and "arguments_error" set, exactly as the wire constructors flag them.
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.