Skip to Content

How do I trace tool calls in AutoGen?

Rius traces AutoGen tool calls with no wrappers: the framework emits an execute_tool span for each tool call, and Rius nests it under the agent run. Call rius.init() and put one observe wrapper on your entrypoint, and each tool call appears inside that trace. Do not wrap AutoGen tool functions with observe, because that splits the tool into its own trace.

How it works

AutoGen (AgentChat, Python) emits create_agent, invoke_agent and execute_tool spans through the global tracer provider, which rius.init() installs. Rius records them as they arrive. Model calls go through the OpenAI client, so the openai integration adds a ChatCompletion generation with model, tokens and cost.

The tool spans nest under the agent run, which nests under your entrypoint. A run that calls one tool looks like this:

handle-ticket AGENT 2.8s ├─ create_agent support_agent 0ms └─ invoke_agent support_agent 2.8s ├─ ChatCompletion LLM 2.6s └─ execute_tool account_status 0ms

The execute_tool span is named after the tool, so each tool you give an agent shows up under its own name.

A few details to expect, verified against autogen-agentchat 0.7.5:

  • Framework spans arrive with status UNSET rather than OK on success. The trace status still reads Ok.
  • Generation spans share the generic name ChatCompletion.
  • AutoGen runs tools in a detached context. A tool function wrapped with observe cannot find the run, so its span splits off as a single-span trace.

There is no TypeScript integration for AutoGen. This page covers the Python framework.

Set it up

  1. Install the SDK with the openai extra, plus AutoGen. The AutoGen integration page covers this setup in full.
pip install "glassflow-rius[openai]" "autogen-agentchat" "autogen-ext[openai]"
  1. Initialize Rius and wrap only your entrypoint with observe. Pass the plain tool function to the agent, with no decorator on it:
import rius from autogen_agentchat.agents import AssistantAgent from autogen_ext.models.openai import OpenAIChatCompletionClient from rius import SpanKind rius.init(api_key="ri_...", service_name="my-agent") def account_status(email: str) -> str: """Fetch a customer's account standing by email.""" return lookup(email) @rius.observe(name="handle-ticket", kind=SpanKind.AGENT) async def handle_ticket(ticket: str) -> str: agent = AssistantAgent( name="support_agent", model_client=OpenAIChatCompletionClient(model="gpt-5-mini"), tools=[account_status], system_message="Answer support questions; check accounts with the tool.", ) result = await agent.run(task=ticket) return str(result.messages[-1].content)
  1. To trace a tool-like step that is not an AutoGen tool, such as a helper your entrypoint calls directly, wrap it yourself. Use observe with the TOOL kind and a tool_name, as the tracing page describes. The span is named execute_tool followed by the tool name and nests under the current span. Replace fetch_invoice with your own function:
@rius.observe(kind=SpanKind.TOOL, tool_name="fetch_invoice") def fetch_invoice(invoice_id: str) -> dict: ...

Call it from the body of handle_ticket, not from inside a tool function you pass to the agent. A bare observe with no kind gives a CHAIN span, so set the kind.

  1. Scope each conversation with rius.session(), reusing your conversation id, so the traces of one conversation group together:
with rius.session(conversation_id): await handle_ticket(ticket)
  1. Run one request that calls a tool and open the trace in the console. You should see the root span, the invoke_agent span, the execute_tool span and the ChatCompletion generation with model, tokens and cost.

What you get

  • One trace per unit of work, with each tool call as an execute_tool span under the invoke_agent span for the run.
  • Each model call as a generation with model, tokens and cost, next to the tool span that follows it.
  • Your own helpers recorded as tool spans, named execute_tool plus the tool name, when you wrap them with the TOOL kind.
  • Conversations grouped by session, using the id you already have.

Cost is a list-price estimate in US dollars that Rius computes from the model and token counts. You never send a cost value.

When something else fits

If your agent runs on a framework other than AutoGen, or calls a model client directly, see Integrations for the matching recipe. If you work in TypeScript, AutoGen has no integration there, so trace its calls with the manual observe and generation helpers on the tracing page.

Still stuck? Get help

Last updated on