Sends messages together with native tool definitions, executes every tool
the model calls, feeds the results back, and repeats until the model
answers in plain text (or max_rounds is reached). Supported for
OpenAI-compatible providers (openai, groq, together, deepseek, xai,
alibaba, zhipu, moonshot, xiaomi, ollama) and Anthropic.
Usage
call_llm_tools(
config,
messages,
tools,
max_rounds = 8L,
max_tool_calls = Inf,
verbose = FALSE,
tries = 3L,
wait_seconds = 2
)Arguments
- config
An llm_config for a generative model.
- messages
Messages as in
call_llm().- tools
One
llm_tool()or a list of them.- max_rounds
Maximum model turns (a turn may contain several tool calls). When reached, the last response is returned as-is with a warning.
- max_tool_calls
Maximum tool executions across the whole loop. Exceeding it raises a condition of class
llmr_tool_limitrather than continuing to spend; the default is unlimited. Callers enforcing spend ceilings (e.g. agent frameworks) can catch that class.- verbose
Print each tool invocation as it happens.
- tries, wait_seconds
Retry controls passed to
call_llm_robust().
Value
The final llmr_response. The full conversation (including tool
results) is attached as attr(x, "messages"); a tibble of executed
calls as attr(x, "tool_history") with columns round, name,
arguments (JSON), result; and aggregate spend across the whole loop
as attr(x, "tool_loop"), a list with model_calls, sent, rec
(token totals over every internal model call, NA when the provider
reported none), and tool_calls. Note that tokens(x) alone covers
only the final model call.
Examples
if (FALSE) { # \dontrun{
weather <- llm_tool(
function(city) paste0("22C and clear in ", city),
name = "get_weather",
description = "Current weather for a city.",
parameters = list(city = list(type = "string"))
)
cfg <- llm_config("groq", "openai/gpt-oss-20b", temperature = 0)
r <- call_llm_tools(cfg, "What is the weather in Tunis?", tools = weather)
as.character(r)
attr(r, "tool_history")
} # }