Tool calling for LLM responses.
Most modern LLMs (OpenAI, Anthropic, llama.cpp with --jinja /
function-calling grammar) support tool calling: the model returns
structured JSON instead of (or alongside) free-form text.
This module:
- Serialises a list of
Candil.Tool.t/0schemas into the prompt (or the API'stoolsparameter) —schemas_to_prompt/1. - Parses the model's response into a list of
%ToolCall{}structs —parse_tool_calls/1.
OpenAI-compatible wire format
%{
"type" => "function",
"function" => %{
"name" => "get_weather",
"description" => "Get the current weather",
"parameters" => %{
"type" => "object",
"properties" => %{
"city" => %{"type" => "string"}
},
"required" => ["city"]
}
}
}Local (llama.cpp) prompt format
A <|tool_call|> style marker followed by JSON. The parser is
forgiving: leading/trailing whitespace and stray markdown fences
are tolerated.
Summary
Functions
Parse a model's response into a list of tool_call/0 maps.
Serialise a list of Candil.Tool.t/0 into OpenAI-compatible wire
schemas suitable for body["tools"].
Types
Functions
Parse a model's response into a list of tool_call/0 maps.
Accepts either:
- A string with
<|tool_call|>(or<tool_call>) markers followed by JSON, separated by whitespace and possibly surrounded by markdown fences. - An OpenAI-style response map with a
tool_callsarray.
Returns {:ok, [tool_call()]} on success or
{:error, %Candil.Error{}} if a JSON block fails to parse.
@spec schemas_to_prompt([Candil.Tool.t()]) :: [wire_schema()]
Serialise a list of Candil.Tool.t/0 into OpenAI-compatible wire
schemas suitable for body["tools"].
Each entry is %{"type" => "function", "function" => %{...}}.