gptr runs a language model agent inside your R session. It computes
on objects you already loaded and keeps named results available for the
next iteration. A dataset around 4 GB can stay in R while the model sees
a bounded description and the results its tools report. You can revise
one analysis step without exporting and reloading the dataset for each
turn. The same function, peter(), is an interactive chat at
the console and a programmable call in scripts, loops and
if statements.
The Execution model explains what reaches the provider and what still costs memory and time. Choose a model in Language models; the examples below run offline with a scripted fake provider.
A first call
library(gptr)
session = peter("Fit mpg from wt in mtcars. Save the model as fit.", mtcars)
session |> peter("Use fit to predict mpg and plot the predictions.")Peter writes and runs R through its tools. The pipe adds work to the
same session, so the next turn can reuse fit.
Try it offline
This fake provider supplies a fixed sequence of tool calls and replies. It does not infer code from the prompt.
library(gptr)
fake = gptr_fake_provider(list(
list(tool = "r", input = list(
code = "fit = lm(mpg ~ wt, data = mtcars)\ngptr_return(coef(fit))"
)),
"Each 1000 lb of weight lowers mpg by about 5.3.",
list(tool = "r", input = list(
code = "predicted = predict(fit)\ngptr_return(head(predicted))"
)),
"The first six predictions are ready."
))
work = new.env()
session = peter("Fit mpg on wt in mtcars and return the coefficients.", mtcars,
model = fake, envir = work, mode = auto)
session$text
#> [1] "Each 1000 lb of weight lowers mpg by about 5.3."
session$value
#> (Intercept) wt
#> 37.285126 -5.344472Prompts are always quoted strings. Identifiers such as the mode can
be bare names, the way library(gptr) needs no quotes:
mode = auto and mode = "auto" are the same.
The auto mode lets ordinary agent actions run without
asking, while retaining the critical and secret guards. This guide needs
it because nobody is there to answer. At the console the default mode,
manual, asks before changes unless a permission rule
already allows them.
session$text is the final answer, and
session$value is the value the tool selected with
gptr_return(). The object the agent created is in
work, like any object you created yourself:
Reuse that fitted object in the next turn. No data file or repeated fit is needed:
session |> peter("Reuse fit to predict mpg and return the first six predictions.")
#> The first six predictions are ready.
#> idle . fake/fake-1 . 2 turns . 6.7k tokens . $0.0000 . s83b855e07c
session$value
#> Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive
#> 23.28261 21.91977 24.88595 20.10265
#> Hornet Sportabout Valiant
#> 18.90014 18.79325
head(work$predicted)
#> Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive
#> 23.28261 21.91977 24.88595 20.10265
#> Hornet Sportabout Valiant
#> 18.90014 18.79325peter() returned a session object. It holds the
conversation, the model, the status and the token usage:
session$status
#> [1] "idle"
session$turns
#> [1] 2
gptr_usage(session, by = "model")
#> group requests input output cache_read cache_write cost
#> 1 fake/fake-1 4 6613 51 0 0 0
#>
#> # 1 row
#> 4 requests, 6.6k tokens in, $0.0000The pipe steers one session
Piping a session into peter() adds a turn to the same
session: the same history, the same model and the same workspace. This
continuation does not duplicate the dataset; ordinary R code can still
allocate copies when it modifies objects or computes new results.
fake2 = gptr_fake_provider(list(
list(tool = "r", input = list(
code = "cyl_mpg = tapply(mtcars$mpg, mtcars$cyl, mean)"
)),
"The mean fuel economy per number of cylinders is stored in `cyl_mpg`.",
"Four-cylinder cars are the most economical, at about 26.7 miles per gallon.",
"Four."
))
session = peter("Compute the mean mpg for each number of cylinders.",
model = fake2, envir = work, mode = auto)
session |> peter("Which group is the most economical?")
#> Four-cylinder cars are the most economical, at about 26.7 miles per gallon.
#> idle . fake/fake-1 . 2 turns . 5.0k tokens . $0.0000 . s7d512ac107
session$turns
#> [1] 2
session$text
#> [1] "Four-cylinder cars are the most economical, at about 26.7 miles per gallon."A branch is always explicit. gptr_fork() copies the
conversation into a new session whose workspace looks up objects in the
parent environment and keeps ordinary assignments local:
branch = gptr_fork(session)
branch |> peter("Answer in one word.")
#> Four.
#> idle . fake/fake-1 . 3 turns . 1.7k tokens . $0.0000 . sdc891944b4
c(original = session$turns, branch = branch$turns)
#> original branch
#> 2 3The overlay separates ordinary bindings, rather than making a full data snapshot. Reference objects and arbitrary side effects require their usual care; see Execution model.
Stopping instead of guessing
In manual mode a change needs approval unless an allow
rule already permits it. When nobody can answer (an Rscript
job, a knitted report), the run stops with a classed condition that says
how to allow the action:
careful = gptr_fake_provider(list(
list(tool = "r", input = list(code = "mtcars$kpl = mtcars$mpg * 0.425")),
"Added the column kpl."
))
res = tryCatch(
peter("Add fuel economy in km per liter to mtcars.", model = careful,
envir = new.env(), mode = manual),
gptr_error_permission = function(e) e
)
class(res)[1]
#> [1] "gptr_error_permission"
res$session$status
#> [1] "blocked"mode = plan inspects and proposes while preserving the
user workspace; level-1 R exploration can create intermediate objects in
its scratch environment. mode = edits allows file edits
inside the project, and gptr_permissions() adds rules such
as "r(level<=1)" that allow low-risk code without a
question.
At the console
Called without a prompt in an interactive console,
peter() opens a chat. Piping a session into it continues
that session, and /exit returns the session. Inside chat,
/help lists commands, @name attaches an object
and !code runs your own R immediately. Interactive console explains input
syntax, permissions and interrupts.
Connecting a real model
Choose a route explicitly. API providers use their named environment
variables, which you can load from a private file with
gptr_env(). Subscription CLI routes use the executable’s
own sign-in; Ollama uses an already-running local server and an
installed model. Language models
gives setup examples for each route.
gptr_env("~/keys/.env")
gptr_providers()
gptr_models(provider = "openai")
gptr_config(model = "openai/gpt-6-sol", .scope = "user")
session = peter("Describe the mpg and wt columns.", mtcars)
session$textThe first time a provider is used interactively, gptr shows what is
sent to it and records your acknowledgment; ?gptr_egress
lists what a request contains. For persistent storage, call
gptr_init("/path/to/project") to create a
.gptr/ workspace and review its separate trust decision.
Without a project workspace, session storage is temporary. Defaults and
storage policy are covered in Configuration.
Where to go next
- Language models: connect a route and use sessions in functions and scripts.
- Interactive console: all built-in commands and inline R.
- Configuration: scopes, settings, options and credentials.
-
System 1 decisions: typed decisions
inside
if,forandwhile. - Script as history: documents that record and replay agent work.
- Extending gptr: tools, policies, hooks and plugins.
- Token efficiency: costs, budgets and compact context.
-
?gptr_security,?gptr_egressand?gptr_options.