Skip to main content
An Agent is a configured harness (the program that drives the model), a model, and a runtime (where the harness executes), built from an AgentConfig alone. An agent is given a Task and produces a Trace.
Every run is a standard rollout producing a vf.Trace. By default, the agent is self-contained: each run brings up the machinery it needs — interception server, network tunnel — and tears it down afterwards.

Borrowed Resources

At scale (large evals, training), per-run machinery adds up. make_agent accepts live resources to borrow instead of creating its own.

Interception Server

Pass interception= to reuse interception servers.

Client

Pass client= to reuse an existing client — agents on the same endpoint should share a single Client (one connection pool).
The caller is responsible for correctly handling the lifecycle of such borrowed resources: they must be live for every run placed on them, and the agent never tears them down.

Trace

A Trace holds all information on a single agent’s rollout: the message graph, model calls, usage, timing, the rewards, metrics, and errors it recorded. Whatever a run did, the trace is the artifact you store, chain, and train on.

Examples

Chaining agents

Agents are chained via vf.Task. For example, a common pattern is one agent’s task depending on another agent’s task. Use the Task.from_trace API, to construct such “glue” tasks.

Shared Runtimes

Runtimes can be borrowed too: agent.provision(task) provisions a box from the agent’s runtime policy as a context manager, and run(..., runtime=box) places a run into it instead of provisioning a fresh one. Chained agents then share one file system — here, the judge inspects what the solver left behind:
The box lives exactly as long as the async with: borrowed runs never provision or tear it down.