Use a team for several roles working on one task, a fan-out for the
same task over several inputs, or gptr_parallel() for
independently specified calls. Each returns a session whose children can
be inspected. Model requests run concurrently; ordinary inline R code
still executes in the one R process.
The examples below need a configured model and are shown without running them.
A team of named roles
library(gptr)
session = peter("Review the analysis workflow.", agents = list(
statistics = gptr_agent(system = "Check the statistical assumptions."),
code = gptr_agent(system = "Check the code and input/output handling.")
))
session$statistics$text
session$code$statusThe member names identify roles. gptr_agent() can
specify each role’s model, system text, tools, skills, backend and
exported object names. A multi-member inline team uses child workspace
overlays: reads can use the parent’s already-loaded objects, while
ordinary assignments stay in each child until requested exports are
collected. That is not a security boundary or protection against
arbitrary code mutating an external resource. Worker backends use
separate R processes and serialize selected inputs, with their own
memory and temporary file costs; CLI backends need their external CLI
and authentication. See Execution
model for copy-on-modify and backend boundaries. Role definitions do
not waive the usual tool permission checks.
session$text joins member reports under headings;
session$value is their named list of values, and
session$statistics is the member session. A report is
model-generated output, not verification. Inspect each child’s status
and the actual results before relying on it.
Continuing a team without agents = asks the container’s
model to synthesize those reports:
session |> peter("Reconcile the reviews into one prioritized list of fixes.")This adds a model request. agents = starts new children;
it cannot be used to continue a piped session. Teams and fan-outs run in
the foreground and cannot be combined with
background = TRUE, .run = FALSE, or nested as
gptr_parallel() members.
A fan-out over input elements
cohorts = list(A = 1:3, B = 4:6, C = 7:9)
session = peter("Summarize this cohort.", cohorts, parallel = 2)
session$A$textparallel = 2 limits active children, not the number of
inputs processed: every element is queued. Exactly one attached context
object must supply the batch, as a list, atomic vector or data-frame
rows. Each child receives its own element. Unique nonempty element names
become child names; otherwise positions are used. Inspect a child with
session$A or session[[1]].
For object-producing work, keep each child’s results separate and specify exports only when needed. Export-name collisions are reported and results are collected in task order; this is not an automatic merge of competing analyses.
Independent calls with gptr_parallel()
session = gptr_parallel(
planner = peter("Plan the analysis."),
review = peter("Review the inputs."),
max_active = 2
)
session$planner$text
session$review$textThe calls are deferred while the members are constructed, then
scheduled together. You can also pass .list = a named list
of sessions created with .run = FALSE. Member names must
not collide with session accessors such as text or
status. A member must be idle with queued input, rather
than an already completed call passed by variable.
Each member retains its own model and workspace, but member
tools =, budget = and per-run
.opts (including max_turns) are not applied.
Members share the call’s budget. Set applicable defaults before launch
or run under an enclosing budget; see Token efficiency.
on_error = "return" keeps failed members for inspection;
"stop" signals the first failed member’s condition after
all members settle.
Deferred sessions and SDK control
.run = FALSE constructs an idle session with queued
input without requesting a model yet. gptr_step() advances
it by model turns; gptr_wait() runs queued work until it
finishes or times out. Returned sessions can be inspected at each
stage.
session = peter("Prepare a plan.", .run = FALSE)
session$status
gptr_step(session, turns = 1)
session$text
gptr_steer(session, "Include an input validation step.", as = "follow_up")
gptr_wait(session, timeout = 10)
session$textA steer reaches a running agent after its current tool results; a
follow-up is delivered when it would otherwise stop. On an idle session,
either remains queued until the next run. Piping a prompt into a running
session uses the same steering mechanism. gptr_wait()
timing out leaves the run running; it does not cancel it.
gptr_cancel() aborts active runs, keeps partial history and
leaves idle sessions alone.
gptr_on(session, event, function(event, ctx) ...)
subscribes to cataloged session events and returns a function that
removes the listener. Keep reporting state outside the agent’s workspace
and remove listeners when finished:
Experimental background work
A background session runs through idle-console callbacks from the
optional later package. It is not an independent R
execution thread. Given an existing fitted model fit, start
with a short task and an explicit workspace:
work = new.env()
work$fit = fit
session = peter("Inspect fit and propose follow-up checks.", fit = work$fit,
envir = work, background = TRUE)
session$status
gptr_jobs()
session |> peter("Prioritize residual diagnostics.")
gptr_wait(session, timeout = 30)
# Cancel only if the run is still active and you want to stop it.
gptr_cancel(session)With gptr.background_tools = "idle" (default), an R tool
can run at an idle tick and occupy the R console until it finishes.
"wait" defers those tools to a blocking gptr call. Rscript,
knitr and Quarto have no idle-console progress: use
gptr_wait() or another blocking call. Other front ends have
the support limits documented in
help("gptr-background", package = "gptr"); do not infer
support from the mere return of a session object.
An approval or question at an idle tick parks the session as
waiting, without performing the action. A later blocking
call resumes it and the model repeats its request before the usual
prompt. That extra request can use tokens. A waiting session has no
active run for gptr_cancel() to abort; inspect its status
before choosing how to resume or stop jobs.
Checkpoints, usage and durable history
After a modifying run, inspect checkpoints and preview a rewind before restoring state:
gptr_checkpoints(session)
gptr_rewind(session, preview = TRUE)
gptr_rewind(session)
gptr_usage(session, by = "agent")restore = "conversation" changes the conversation;
"workspace" restores captured workspace state;
"all" requests both. Restoration covers captured
objects/files and registered checkpointers, with conflicts and
unsupported changes reported. It does not undo arbitrary external
services or uncaptured side effects. Check the report and restored data.
Assigning a session to another name keeps the same object; use
gptr_fork() for a branch.
For a top-level team or fan-out call in a designated history document, child code is recorded under that statement and replay can reconstruct the children. Recording, answer caches and usable blocks must be present; a narrative team report alone is not a replayable workflow. See Script as history for recording and summary recipes, and Token efficiency for shared budgets and usage.