Skip to content
BroccolitoPublic

About

R-native AI agent harness for scientific computing.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

gptr gptr logo

gptr runs language model agents in your current R session. Agents can analyze objects already in memory and create R objects that you can inspect, reuse or modify.

  • Work with live R objects. Continue an analysis across prompts using the same data and intermediate results.
  • Use agents or typed decisions. Conversational models return an agent session; decision models return R vectors of logical answers, labels or scores.
  • Keep a record you can rerun. Record agent calls and their executed R code alongside your analysis, then replay the code with the required inputs and packages.
  • Improve the agent on your own task. Models revise the agent's instructions from runs of your task; gptr keeps only revisions that pass its checks and any of yours, round after round.

Installation

gptr is on CRAN. It requires R 4.2 or later and has no compiled code.

install.packages("gptr")

The development version on GitHub gets fixes and features before they reach CRAN:

if (!requireNamespace("pak", quietly = TRUE)) install.packages("pak")
pak::pak("Broccolito/gptr")

This README describes gptr 1.0.1; packageVersion("gptr") shows yours. After installation, load the package:

library(gptr)

Connect a model

Choose one of the following routes before running the analysis examples.

API key. Put your provider's key in a private .env file. For example, the Anthropic route needs ANTHROPIC_API_KEY:

gptr_env("~/keys/.env")
gptr_config(model = "anthropic/claude-sonnet-5-5", .scope = "user")

This saves the default model for future R sessions. Use .scope = "session" to limit a setting to the current R process. gptr_providers() lists configured routes.

Existing CLI login. Install and sign in to Claude Code or Codex outside R, then open the chat:

peter()

With no default model set, the console offers the available CLI routes and saves your choice. Enter /exit to return to R. CLI sign-in is separate from API credentials.

Use gptr_models(provider = "codex", refresh = TRUE) to refresh that CLI's advertised model choices; see ?gptr_models for listing limits.

Local Ollama model. Start Ollama separately and install a chat model that supports tool calls. Select an installed model, for example:

gptr_config(model = "ollama/qwen3:1.7b", .scope = "session")

gptr does not install Ollama or download models. Local-only Ollama inference is on by default; a workflow remains local only when every model and tool it uses is local.

The first interactive use of a remote provider asks you to acknowledge the data it receives, including with context = "none": project instructions and environment details still go. For unattended runs, review ?gptr_egress, then save consent for the provider beforehand:

gptr_config(egress = utils::modifyList(gptr_config()$egress, list(anthropic = "ack")),
            .scope = "user")

Use the provider you selected; offline scripted models and local loopback routes remain exempt (Ollama only while local-only inference is on). See Language models for setup.

Run an analysis

With a model configured, ask for a task and continue the same agent session:

session = peter("Fit mpg on wt in mtcars and store the model as fit.", mtcars)
session |> peter("Store the residuals of fit as res. Which cars have the largest?")
session$text
coef(fit)

The pipe adds a turn to the same conversation and reuses fit. The returned objects have different roles:

Object What it contains
session The agent conversation, status and usage, as a gptr_session
session$text The latest text answer
fit The fitted R model, available in your workspace

session$value holds the most recent R result selected with gptr_return(); a turn that selects no result leaves that value unchanged.

At the console, agent code runs in your R workspace. R computes on the full objects, while the model receives size-limited descriptions, previews and tool output that may include data values. R's usual memory allocation and copy-on-modify rules apply. See Execution model and Data sent to providers.

In the default manual mode, actions classified as read-only run directly and actions classified as changes ask for approval, unless a permission rule applies; an allow rule never approves a critical action. The check is advisory and provides no sandbox; see Security considerations or ?gptr_security in R.

Record and replay an analysis

Choose a recording file before starting the calls you want to keep. This example records a new analysis using R's built-in mtcars data:

gptr_doc("analysis.R")
session = peter("Fit mpg on wt in mtcars and store the model as fit.")
session |> peter("Summarize the residuals in fit.")
gptr_doc(FALSE)

gptr writes eligible top-level calls and their executed R code into analysis.R, with model and execution metadata. These are local files you can review and version with your analysis. In a new R session, replay the recorded code:

library(gptr)
gptr_source("analysis.R", replay = "replay")

Replay makes no model calls. It executes the recorded R code, including its side effects, and requires that code's input data, files and packages.

To ask the model again, use gptr_source("analysis.R", replay = "live"); model = picks your own model. The new run can produce different code or results. gptr_export() can turn an eligible recorded .R file into an ordinary R script.

Recording also supports R Markdown, Quarto and Jupyter. See Record, replay and export for document setup, recording limits and export requirements.

Return typed decisions

A decision model returns one answer per input: a logical value, a label selected with choices, or a numeric score defined by levels. The selected model type determines whether peter() returns a decision vector or an agent session.

This example uses hosted Jev and requires TYPESAFE_API_KEY, which gptr_env() can load from your key file:

abstracts = c("We randomized 200 adults to drug or placebo.",
              "We followed 5000 nurses for 20 years.")
is_rct = peter("Is this a randomized trial?", abstracts, model = "jev")
is_rct
gptr_prob(is_rct)

is_rct is a logical vector. Here, gptr_prob() returns the model's probability of TRUE for each abstract. It does not establish the probability that a classification is correct.

Local Clef and Clef Flash provide typed decisions through Ollama 0.35.1 or later. gptr calls typed decision models System 1 and conversational agents System 2. See Typed decisions for scores, uncertainty, calibration and a complete offline example.

A peter of your own

gptr_tailor() builds a harness, a function you call exactly like peter(), with fixed arguments, your own hard rules and coaching (a note, skills, a review). gptr_coach() improves the coaching by running your task in separate R processes and keeps a change only when the new run passes gptr's checks and your check. Rules and coaching never loosen permission checks. A gptr_coach() call runs your task several times (4 runs and 3 coach sessions by default) and takes minutes.

auto_peter = gptr_tailor(peter, mode = "auto")
slope_peter = gptr_coach(
  "Regress mpg on wt in mtcars; store the slope as b.", mtcars,
  harness = auto_peter,
  check = function(r) is.numeric(r$objects$b)
)
slope_peter("Regress mpg on hp in mtcars; store the slope as b.", mtcars)
saveRDS(slope_peter, "slope_peter.rds")
# load and check it in a later session
slope_peter = gptr_tailor(readRDS("slope_peter.rds"))

The result is a harness too, so gptr_coach(..., harness = slope_peter) coaches it again on your next task: recursive self-improvement, limited to the coaching. See Harnesses and coaching for what coaching may change and how gptr decides what to keep.

Learn more

Start with Getting started; its examples run offline with a scripted gptr_fake_provider(). With a CRAN install, open it in R with vignette("getting-started", package = "gptr").

Why Peter?

gptr reads as a grammar for Peter: g for grammar, as in ggplot2's grammar of graphics, and ptr for Peter, your agent in R. The name honors two Peters. Peter Naur edited the ALGOL 60 report, which defined the language's syntax in a readable grammar notation now called Backus-Naur Form; in that spirit, gptr records sessions as runnable documents. Peter Cathcart Wason studied human reasoning, and his dual-process account with Jonathan Evans inspires gptr's System 1 and System 2, names for software roles that imply nothing about human cognition. See Why Peter? for the history and sources.

Upgrading from gptr 0.7.0

gptr 1.0.0 is a rewrite. get_response() and dataframe_to_text() were removed: use peter("your prompt")$text and pass a data frame to peter() as context. See NEWS.md.

Installation troubleshooting

If pak reports Subprocess is busy or cannot start, or loading gptr reports a missing or corrupt gptr.rdb, restart R and reinstall before loading the package. The development version also installs with remotes::install_github("Broccolito/gptr").

License and acknowledgments

gptr is licensed under the Apache License 2.0. Third-party notices are in inst/COPYRIGHTS.

gptr was inspired by Mario Zechner's 'pi' coding agent. The tool descriptions, edit guidelines and prompt-template grammar are derived from 'pi', the model catalog from models.dev and the secret patterns from gitleaks, and the System 1 emulation prompt follows TypeSafe AI's system-one-adapter-python. All four are MIT-licensed. Ideas came from 'ellmer', 'tidyllm', 'btw' and 'mcptools', none of which gptr depends on. Anthropic, OpenAI, Google, TypeSafe AI, Ollama and the vendors of the command-line tools are third-party services; gptr is not affiliated with or endorsed by them.

About

R-native AI agent harness for scientific computing.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages