react() builds an agent that alternates between reasoning and calling
tools until it can answer, then returns a structured answer that follows
the signature (the ReAct pattern).
Arguments
- signature
A signature from
signature(), or a signature string.- tools
A list of ellmer tool definitions, made with
ellmer::tool(),ragnar_tool(),create_search_tool()oras_ellmer_tool(). Their names must be unique. The module's$add_tool(tool, replace = FALSE)adds one later; withreplace = TRUEit replaces the tool of the same name.- max_iterations
Maximum number of tool-calling rounds. Several tool calls in one model turn count as one round. Exceeding the limit is an error.
- chat, template, demos, config
As in
module().- ...
Must be empty.
Value
A module (an R6 object of class ReactModule) to use with run()
and run_dataset().
Details
ellmer runs the tool-calling loop: the model's tool requests are executed and their results sent back, keeping ellmer's turn history and tool-call IDs. After the loop, one more request asks for the final answer in the signature's output format. ReAct calls do not use the response cache.
run() accepts one input at a time for this module; use run_dataset()
for several. With .return_format = "structured", the metadata records
iterations, tool_calls and tools_used.
See also
Other program constructors:
chain_of_thought(),
code_act(),
flex(),
module(),
module_fn(),
multi_chain_comparison(),
program_of_thought(),
rag_module(),
rlm(),
rlm_module()
Examples
lookup_population <- ellmer::tool(
function(city) {
switch(city, Paris = "2.1 million", Lyon = "0.5 million", "unknown")
},
name = "lookup_population",
description = "Look up the population of a French city.",
arguments = list(city = ellmer::type_string("City name"))
)
agent <- react(
"question -> answer",
tools = list(lookup_population),
max_iterations = 5L
)
agent
#>
#> ── ReactModule ──
#>
#> ── Signature
#>
#> ── Signature ──
#>
#> ── Inputs
#> • question: "string" - Input: question
#>
#> ── Output
#> Type: "object(answer: string)"
#>
#> ── Instructions
#> Given the fields `question`, produce the fields `answer`.
#>
#> ── Tools
#> • lookup_population
#> Max iterations: 5
if (FALSE) { # \dontrun{
llm <- ellmer::chat_openai(model = "gpt-6-luna")
run(agent, question = "How many more people live in Paris than in Lyon?", .llm = llm)
questions <- data.frame(question = c("Population of Paris?", "Population of Lyon?"))
run_dataset(agent, questions, .llm = llm)
} # }