
Language-model agents for R, built on LLMR.
LLMRagent defines governed single-agent and multi-agent studies. An agent combines a model configuration and persona with memory, declared tool powers, boundary checks, and a budget. Designed conversations and factorial studies return classed results with transcripts, question-and-answer tables, votes, or condition-level results. Calls, tool use, and state changes can be collected in an analysis-ready run record.
# install.packages("remotes")
remotes::install_github("asanaei/LLMRagent")
library(LLMRagent)
cfg <- LLMR::llm_config("groq", "openai/gpt-oss-20b")agent() accepts any model configuration supported by
LLMR. Provider credentials remain in the environment rather than in the
agent definition.
ada <- agent(
"Ada",
cfg,
persona = "A meticulous statistician. Be brief.",
memory = memory_buffer(keep = 20L),
budget = budget(
max_calls = 6L,
max_tokens = 8000L,
max_tool_calls = 4L,
max_seconds = 120
)
)
ada$chat("What is overfitting?")
ada$chat("How do I detect it?")
ada$usage()
ada$trace()chat() stores successful exchanges in the selected
memory policy. Call and tool-call ceilings are checked before the
corresponding operation. Token and elapsed-time limits stop the next
model round after recorded use reaches the limit. Failures raise
conditions and are not stored as model replies.
agent_tool() exposes an R function while declaring its
side_effects, approval requirement, and per-tool limits.
side_effects is one of "none",
"read", "write", or "external". A
guardrail() checks an agent input, output, or tool call at
a named boundary.
lookup_gdp <- agent_tool(
fn = function(country) {
values <- c(chile = 335, uruguay = 81, bolivia = 47)
value <- values[tolower(country)]
if (is.na(value)) "unknown" else paste0("$", value, " billion")
},
name = "lookup_gdp",
description = "Look up a country's illustrative GDP in USD billions.",
parameters = list(country = list(type = "string")),
required = "country",
side_effects = "read",
requires_approval = FALSE,
max_calls = 5L
)
no_file_writes <- guardrail(
"no_file_writes",
check = function(payload, context) {
if (identical(payload$name, "write_file")) "file writes are not allowed" else TRUE
},
stage = "tool"
)
analyst <- agent(
"Analyst",
cfg,
tools = list(lookup_gdp),
guardrails = guardrails(no_file_writes)
)Use human_gate() to add the same requirement as
requires_approval = TRUE. A gated call pauses before the
function runs. The checkpoint exposes the proposed tool name and
arguments for a decision.
write_note <- human_gate(agent_tool(
function(path, text) writeLines(text, path),
name = "write_note",
description = "Write text to a file.",
parameters = list(
path = list(type = "string"),
text = list(type = "string")
),
required = c("path", "text"),
side_effects = "write"
))
scribe <- agent("Scribe", cfg, tools = list(write_note))
pending <- tryCatch(
scribe$chat("Write a short note to notes.txt."),
llmragent_pending_approval = function(e) e$checkpoint
)
pending$pending
approved <- approve_tool_call(pending, decision = "approve")
resumed <- resume_run(approved)
resumed$textApproval can approve, reject, or edit the proposed arguments. Plain
LLMR::llm_tool() objects remain accepted, but they do not
carry the declared powers and limits supplied by
agent_tool().
conversation() provides general dialogue over one
attributed transcript. The study presets define turn structure according
to the result sought.
| Function | Purpose | Primary result |
|---|---|---|
conversation() |
General multi-agent exchange | Attributed transcript |
debate() |
Phased opposing cases | Transcript and optional verdict |
focus_group() |
Reactions within a moderated group | Transcript and moderator synthesis |
interview() |
Questions and probes for one respondent | Tidy question-and-answer data in $qa |
deliberate() |
Discussion followed by a group decision | Transcript, private votes, and decision |
panel <- list(
agent("Morgan", cfg, persona = "An operations manager who values predictability."),
agent("Sam", cfg, persona = "A young engineer who values flexibility."),
agent("Ren", cfg, persona = "A finance director focused on costs.")
)
d <- deliberate(panel, "Adopt a four-day work week for a one-year pilot.")
d$transcript
d$votes
d$decisionagent_experiment() expands a design by replication, runs
one fresh procedure per cell, and records cell-level errors without
stopping the study.
design <- expand.grid(
framing = c("benefit", "cost"),
stringsAsFactors = FALSE
)
study <- agent_experiment(design, reps = 3L, run_fn = function(cond, rep) {
subject <- agent("Subject", cfg, quiet = TRUE)
subject$reply(paste("Assess the proposal using a", cond$framing, "frame."))
})agent_robustness() applies declared perturbation axes
and reports how a chosen measure changes. The axis helpers are
vary_models(), vary_temperature(),
vary_prompt(), vary_persona(), and
vary_option_order(). persona_variants() builds
planned persona contrasts. mark_claim_type() records
whether a run is an instrument pilot, theory probe, or coding exercise;
none of these labels turns model output into a population estimate.
as_agent_run() gives high-level results a common record
with utterance, event, call, tool, and state views. Diagnostics, methods
text, and a manifest are derived from that record.
run <- as_agent_run(d)
tibble::as_tibble(run, level = "utterance")
tibble::as_tibble(run, level = "tool")
diagnostics(run)
report(run)
manifest <- agent_manifest(run)
archive <- archive_agent_study(
run,
path = "four-day-study",
include_messages = FALSE
)archive_agent_study() writes an inspectable directory
containing projected run data, call records, the study manifest, methods
text, artifacts, and file hashes. The archive omits live agents and
functions. It is a record for inspection, not a general mechanism for
executing the study again.
agent_as_tool() lets a supervisor decide when to consult
a specialist. The specialist’s calls count against its own budget and
appear in its usage record.
stat <- agent(
"Stat",
cfg,
persona = "A statistician who states assumptions and threats to inference."
)
lead <- agent(
"Lead",
cfg,
persona = "A research lead who consults specialists before synthesis.",
tools = list(agent_as_tool(stat))
)
lead$chat("Could falling crime cause rising policing budgets, rather than vice versa?")agent_pipeline() runs a fixed sequence of specialists
and retains each intermediate result in its steps table.
agent_fanout_synthesis() assigns several independent
approaches to one worker configuration, then uses another configuration
for planning, synthesis, and optional verification.
Workflows represent procedures that need branches, checkpoints, forks, or resumption beyond the higher-level study functions.
wf <- agent_workflow("triage")
wf <- add_node(wf, "clean", function(state) {
state$text <- trimws(state$input)
state
})
wf <- add_node(wf, "review", function(state) {
state$ok <- nzchar(state$text)
state
})
wf <- add_edge(wf, "clean", "review")
wrun <- run_workflow(wf, input = " a claim ")
replayed <- replay_run(wrun, wf, verify = "structural")run_workflow() records state transitions and can write
checkpoints. resume_workflow() continues a checkpointed
workflow, and fork_workflow() branches from recorded state.
replay_run() re-executes a workflow run and checks it at
the requested verification level. It does not re-execute an arbitrary
archived agent run.
mcp_tools() exposes tools from a Model Context Protocol
server under a read-only or read-write policy, with optional approval
for writes and schema pinning. view_run() writes a
self-contained HTML view of a run record.
Agent persistence is separate from study archives.
save_agent() stores an agent’s configuration, memory,
budget, guardrails, and accounting, but omits tool functions.
load_agent() restores that state and accepts tools to
reattach.
All articles and reference: https://asanaei.github.io/LLMRagent/
LLMR version 0.8.11 or
later supplies the common provider interface used by LLMRagent.
agent() accepts an LLMR::llm_config() object,
so provider and model settings are shared between the packages.
LLMRagent is one of a family of packages for LLM-assisted research built on LLMR, the shared provider interface. LLMRcontent codes text from a codebook and evaluates the resulting labels against held-out human labels. LLMRpanel administers survey and experimental instruments to panels of model personas for design-stage studies. FocusGroup runs simulated moderated discussions and supports experiments on how one turn changes the next. The ecosystem page introduces the whole family.
Report bugs and feature requests in the GitHub repository. Pull requests may be submitted there.
This project uses the MIT License; see LICENSE.