Skip to contents

An experimental inference-time analyst for inputs whose useful evidence is too large, irregular, or unpredictable to place in one prompt. RLM keeps the inputs in an R environment and lets the model iteratively inspect summaries, run computations, and decide what to examine next.

Details

Each input is available under .context. Generated R code can use ordinary R plus peek(), search(), value-returning llm_query() calls, declared host tools, and SUBMIT(...). RLM requires a runner whose policy() advertises persistent = TRUE; variables therefore remain available across turns within one invocation. Invalid submitted fields or types become iteration errors that the model can repair. If no valid submission is produced, the separate extract predictor performs one typed fallback. RLM validates explicit ellmer string, number, integer, boolean, enum, array, and object outputs. Opaque TypeJsonSchema nodes are rejected at construction because they cannot participate in this strict repair loop.

The generate_action and extract predictors are graph-visible through named_modules(). GEPA can tune them; nested MIPROv2 is instruction-only with bootstrapped demos disabled. BootstrapFewShot and LabeledFewShot reject programs containing an RLM until predictor-local demonstrations are available. Model-visible execution evidence defaults to a 10,000-character head-and-tail view after any runner-level transport limit; that formatted evidence is retained in the returned trajectory. Trace state retains hashes and sizes for input objects, not their full values. Structured metadata separates logical action, recursive, and extraction counts from verified provider calls. A child-predictor cache hit contributes zero provider calls and zero current-run usage; totals remain NA whenever every contributing provider turn cannot be verified.

For generated code, prefer a fresh sandboxed mcp_repl_runner() factory. Its managed transport is intentionally bounded and is best for compact, JSON-compatible context. Its default policy disables network access but allows writes within the configured workspace. Declared host tools execute in the dsprrr host process, outside that guest sandbox. This backend requires the suggested mcptools package and Posit's external mcp-repl executable. For large data frames or richer local R objects, r_code_runner(persistent = TRUE) can stage context once, but it is trusted-input-only: the child process retains the host user's file, network, and environment permissions.

Supply exactly one runtime source. A caller-owned runner is reused and never closed by dsprrr. An interpreter_factory creates one invocation-owned runner which dsprrr shuts down on success, error, or interrupt. Factory-backed RLM supports run_async() and isolated run_dataset() execution; token streaming is unavailable. A direct run() call always stages each supplied value as one REPL variable, regardless of its R length. Use run_dataset() for multiple invocations, with list-columns for data frames, vectors, lists, matrices, or other rich per-row values.

Examples

if (FALSE) { # \dontrun{
analyst <- rlm_module(
  signature = "document, question -> answer",
  interpreter_factory = function() mcp_repl_runner(timeout = 30)
)
compact_doc <- "Section 1: ...\nSection 2: ..."
result <- run(
  analyst,
  document = compact_doc,
  question = "What evidence supports the conclusion?",
  .llm = ellmer::chat_openai()
)
} # }