trace_graph()
Auto-instrument every node in a compiled graph: one span per node, zero handler changes.
gb <- graph_builder()
gb$add_node("fetch", function(state, config) list(data = mtcars[1:5, ]))
gb$add_node("summarize", function(state, config) list(summary = summary(state$data)))
gb$add_edge("fetch", "summarize")
gb$add_edge("summarize", END)
gb$set_entry_point("fetch")
graph <- gb$compile()
result <- trace_graph(graph, list(data = NULL, summary = NULL))trace_agent()
Wrap a single agent invocation; model name and token deltas are extracted from the ellmer chat object automatically.
chat <- ellmer::chat_openai(model = "gpt-4o")
assistant <- agent("assistant", chat)
response <- trace_agent(assistant, "Summarize the iris dataset.")With exporters
Pass an exporter to persist the trace as JSONL.
exp <- jsonl_exporter(tempfile(fileext = ".jsonl"))
result <- trace_graph(graph, list(data = NULL, summary = NULL), exporter = exp)
# Or set a default for all traces
set_default_exporter(jsonl_exporter(tempfile(fileext = ".jsonl")))
result <- trace_graph(graph, list(data = NULL, summary = NULL))Cost tracking
Aggregate costs across all spans. Useful for ReAct loops where call count is unpredictable.
chat <- ellmer::chat_openai(model = "gpt-4o")
graph <- react_graph(agent("analyst", chat))
result <- trace_graph(graph, list(messages = list("Analyze sales trends.")))
trace_total_cost(current_trace())Manual spans in nodes
Add with_span() inside a handler for sub-node detail.
Combine with trace_graph() freely.
analyze_node <- function(state, config) {
with_span("llm-call", type = "llm", {
record_tokens(500, 120, model = "claude-sonnet-4-5")
list(result = "analysis complete")
})
}
gb <- graph_builder()
gb$add_node("analyze", analyze_node)
gb$add_edge("analyze", END)
gb$set_entry_point("analyze")
with_trace("custom-graph-run", {
gb$compile()$invoke(list(result = NULL))
})
#> $result
#> [1] "analysis complete"