Keep data and computation in R, and send models enough context to choose useful actions. For inline work, an object around 4 GB can remain in the same R session across turns. The model sees a compact description while its R tool computes on the object. No repeated export and reload cycle is required; R copies, computation time and request latency still depend on the workflow. Workers receive serialized context rather than sharing the parent workspace. Four practices help:
- Refer to live objects with a compact description rather than
printing large tables into a prompt. The model can compute on those
objects with the
rtool. - Compose several deterministic operations in one R call and return a bounded result.
- Reuse a session’s stable prompt and growing conversation when the provider supports prompt caching. Changing models, tools, compaction or rewind can change that prefix.
- Inspect usage and set budgets before starting a costly workflow.
The executed examples use fake providers. Their request counts and estimates demonstrate the interfaces; they are not measurements of a real model’s speed, quality or bill.
Inspecting the prompt
library(gptr)
view = gptr_prompt(preset = "minimal")
attr(view, "tool_names")
#> [1] "read" "r" "edit" "write"
view$sections
#> name tier tokens
#> 1 preamble T0 42
#> 2 tools T0 86
#> 3 rules T0 348
#> 4 modes T0 84
#> 5 context T0 152
view$total_tokens
#> [1] 1875gptr_prompt() inspects the system sections and tool
definitions with estimated token counts; printing it shows their text.
It does not query a provider. The standard preset describes
most capabilities as functions in peter$, with the core
model-visible r, read, edit and
write tools and ask when applicable.
view$total_tokens already counts the tool array and a
preview of the first message; your prompt and the objects you attach add
to it.
Object descriptions and result size
writeLines(gptr_describe(iris))
#> <data.frame> 150 x 5, 7.1 KB
#> $ Sepal.Length <dbl> min 4.3, median 5.8, max 7.9; no NA
#> $ Sepal.Width <dbl> min 2, median 3, max 4.4; no NA
#> $ Petal.Length <dbl> min 1, median 4.35, max 6.9; no NA
#> $ Petal.Width <dbl> min 0.1, median 1.3, max 2.5; no NA
#> $ Species <fct> 3 levels, top: setosa (50), versicolor (50), virginica (50); no NA
writeLines(gptr_describe(iris, budget = 60))
#> <data.frame> 150 x 5, 7.1 KB
#> Sepal.Length:dbl Sepal.Width:dbl Petal.Length:dbl Petal.Width:dbl Species:fctgptr_describe() summarizes class, shape and values
within a budget (150 tokens by default). Packages can register methods
for their own classes. Generative-model context normally uses these
descriptions and names; System 1 questions send their input
states, so their egress and size rules differ. See System 1 decisions.
work = new.env()
session = peter("Compare mpg and weight by cylinder count.", mtcars,
model = fake, envir = work, mode = auto)
work$slopes
#> 4 6 8
#> -5.647025 -2.780106 -2.192438The calculation runs in R once the model requests it. Return a small
table, statistic or plot rather than a full intermediate object. Long
r output keeps a bounded head and tail; the full spilled
text can be read through peter$out(id) when an output ID
was supplied.
Reported usage and estimated components
gptr_usage(session, by = "model")
#> group requests input output cache_read cache_write cost
#> 1 fake/fake-1 2 3290 48 0 0 0
#>
#> # 1 row
#> 2 requests, 3.3k tokens in, $0.0000
ledger = gptr_usage(session, detail = TRUE)
aggregate(tokens ~ component, data = ledger, FUN = sum)
#> component tokens
#> 1 attached 130
#> 2 environment 210
#> 3 images 0
#> 4 other 162
#> 5 project 0
#> 6 t0 2684
#> 7 t1 562
#> 8 tool_results 53
#> 9 tools 1926
#> 10 transcript 70
#> 11 workspace 58The usage summary contains provider-reported input, output, cache
reads/writes and cost. by = "session",
"agent", "model" or "route"
groups it; child requests are included once. gptr_usage()
without a session also includes the process-level System 1 log.
The detailed ledger estimates components such as tools, workspace,
attached objects, transcript and tool results. Its sum can differ from
reported usage because tokenizers, provider accounting, images and
fake-provider behavior differ. Unknown reported usage or cost stays
NA, not zero. A local model’s known zero metered charge
does not imply zero hardware cost or latency.
Budgets and partial results
budget_error = tryCatch(
peter("Summarize mpg.", model = small, budget = list(tokens = 500)),
gptr_error_budget = function(e) e
)
class(budget_error)[1]
#> [1] "gptr_error_budget_tokens"
budget_error$session$status
#> [1] "budget"The estimated input for the first request already exceeds 500 tokens,
so this call stops before that request. A top-level run’s defaults are 2
million tokens and 5 US dollars;
budget = list(tokens = ..., cost = ..., turns = ...)
supplies limits for that call. Change settings deliberately when
different defaults are needed:
gptr_config(budget = list(tokens = 20000, cost = 1, turns = 10), .scope = "session")
session = peter("Review this analysis.", budget = list(tokens = 12000, turns = 6))Checks happen before requests using estimated next-input tokens and
usage already recorded. The next output or final provider charge can
exceed a remaining allowance; unknown usage cannot establish a hard
monetary ceiling. A budget is a stopping policy, not a billing
reservation. At the console the UI can ask to extend it; without a
person present the call signals a budget condition carrying the partial
session as e$session. Inspect that session’s status,
transcript, workspace and usage before deciding whether to continue.
Teams and fan-outs share the root call’s budget; launching more
children does not give each one a fresh root allowance. With
gptr_parallel(), member budget =,
tools = and per-run .opts are not applied. Set
the intended limits through the governing settings or enclosing run, cap
concurrency and inspect the returned children’s statuses. See Teams and background work.
Compaction
At the chat prompt, /compact replaces older model
context with a summary. Add a focus when particular details must
survive, for example
/compact retain the model comparison and next steps.
Automatic compaction follows the configured context and cold-cache
thresholds; see Configuration.
Compaction can make a model request and add usage. It keeps the R objects already in your session, while the model no longer sees every older turn verbatim. Preserve important decisions in project files and named R objects. A changed request prefix can also affect provider cache reuse.
Three different caches
| Mechanism | What is reused | Inspect |
|---|---|---|
| Provider prompt cache | A repeated request prefix | gptr_usage(session) |
| System 1 answer cache | Matching input, question and model | Metadata and gptr_cache()
|
| Replay / System 2 cache | Recorded code and saved answer |
gptr_blocks(path), gptr_cache()
|
A stable prefix makes provider cache reuse possible. Providers decide whether a cache hit occurs, subject to their support, minimum size, expiry and pricing; gptr does not guarantee a hit after the first request. Compaction, image elision, changed resources or rewind can break the prefix. Document replay makes no model request for a usable recorded call but still runs its R code. Clearing an answer cache changes what can be reused.
Explicit ways to reduce context
peter("Summarize the model fit.", fit, .opts = list(context = "names"))
peter("Find the mean of x. Return one number.", .opts = list(context = "none"))
peter("Compute the mean.", x, .opts = list(preset = "minimal"))context = "names" lists workspace names and uses headers
for explicitly attached objects. "none" omits both built-in
workspace and attached-object descriptions; the R bindings still exist
and can be used by tool code, as x is in the second
example. Prompt text, tool results, images and other context blocks can
still reach the model. System 1 input states use a separate encoding
route. Execution model explains these
boundaries. preset = "minimal" reduces the tool/prompt
surface; it does not authorize actions or remove required safety
checks.
{identifier} in a literal prompt can insert a short
atomic value when that is sufficient. For a long workflow, continue one
session, keep intermediate data in R and request concise reports between
stages. Use a new session or an explicit fork when a separate analysis
is intended.