One global client
Call rollout.init() once at startup. It creates and stores a global client; the module-level helpers and decorators all use it. It takes the same arguments as the Rollout constructor and reads the same environment variables.
import mv37.rollout as rolloutrollout.init(api_key="...", agent_name="support_agent", environment="production")The decorator set
Every decorator accepts an optional name (defaulting to the function name) and works on sync and async functions.
| Decorator | What it does |
|---|---|
@rollout.agent | Agent entry point — opens a fresh trace per call, captures input/output, flushes, and re-raises errors. |
@rollout.trace | Opens a trace per call. |
@rollout.span | Opens a typed span (requires an active trace). |
@rollout.tool | Records a tool.call / tool.result pair. |
@rollout.task | Opens a task span — a multi-step unit of work. |
Note
Use @agent at the outermost entry point of a run — it owns the trace and flushes when the call returns. Use @tracewhen you want a trace per call but don't need the agent-boundary behavior (input/output capture is off by default on @span and @task, on by default for @tool).
A traced function
Decorate an entry point to open a trace per call, and decorate tools to capture their inputs and outputs. Inside the call, rollout.current_trace() returns the active trace so you can attach messages from anywhere.
import mv37.rollout as rollout@rollout.tool("get_weather")def get_weather(city: str) -> dict: return {"city": city, "temp": 21}@rollout.trace("support_agent")def handle_request(text: str) -> str: rollout.current_trace().message(role="user", content=text) weather = get_weather("Paris") # recorded as a tool span return f"It's {weather['temp']}°C."Context managers
rollout.trace(...) and rollout.span(...)also work as plain context managers when you don't want to decorate a whole function.
with rollout.trace("support_agent") as trace: with rollout.span("retrieval") as span: span.record_input({"query": "orders"})Reaching the active trace
rollout.current_trace() and rollout.current_span() return the active objects (or None), so you can attach messages, feedback, usage, or signals from helper functions deep inside a call without threading the trace through every argument.
def record_outcome(ok: bool) -> None: trace = rollout.current_trace() if trace is not None: trace.signal("resolved", ok)