A subprocess execution backend for running R code generated by LLMs. Uses callr for process isolation, timeout protection, output capture, and structured result handling.
Details
RCodeRunner provides:
Process isolation: Code runs in a separate R process via callr
Timeout protection: Configurable timeout prevents runaway execution
Output capture: Captures stdout, stderr, messages, and warnings
Context passing: Inject data into the execution environment
Output limiting: Truncates large outputs to prevent memory issues
Security note: r_code_runner() is a trusted-input-only backend. callr
starts a separate process, but that process retains the host user's file,
network, environment, and operating-system permissions. Pattern checks are
only defense in depth and can be bypassed. For untrusted inputs, provide a
runner backed by a container or OS-level sandbox.
Code-executing modules accept any runner that implements the dsprrr runner
protocol. A runner must expose execute(code, context = list()) and
policy() methods. policy() returns a named list containing at least
backend (character), trust (character), and sandboxed (logical).
execute() returns a list with success, result, stdout, stderr,
messages, warnings, error, and duration_ms fields.
Examples
if (FALSE) { # \dontrun{
runner <- r_code_runner(timeout = 5)
# Simple execution
result <- runner$execute("1 + 1")
result$result
# [1] 2
# With context
result <- runner$execute(
"mean(.context$data$mpg)",
context = list(data = mtcars)
)
result$result
# [1] 20.09062
# Timeout handling
result <- runner$execute("Sys.sleep(100)")
result$success
# [1] FALSE
result$error
# "Execution timed out after 5 seconds"
} # }