What does Rius record when my agent calls AutoGen?
Rius records the agent and tool structure that AutoGen (AgentChat) emits, plus each model call as a generation with model, tokens and cost. The spans for agent creation, agent runs and tool calls come from AutoGen’s own OpenTelemetry output. The model calls come from Rius’s OpenAI integration. The integration is Python only, and it has a few quirks you should know before you read your first trace.
How it works
AutoGen combines two ways of getting coverage, so Rius records two kinds of spans:
- Framework spans. AutoGen emits
create_agent,invoke_agentandexecute_toolspans through the global tracer provider, whichrius.init()installs. Agent and tool structure arrives without any wrappers. - Generations. Model calls go through the OpenAI client from
autogen-ext[openai], so the OpenAI integration records each one with its model and token counts. Rius computes the cost from the model and the tokens. You never send a cost value, and the figure is a list-price estimate in US dollars.
One observe wrapper on your entrypoint groups agent creation and invocation into a single trace for each unit of work. Prompt and response content follows the SDK-wide RIUS_CAPTURE_CONTENT setting. Set it to false and content is stripped at export.
The full recipe is on the AutoGen integration page.
Set it up
- Install the SDK with the OpenAI extra, together with AutoGen:
pip install "glassflow-rius[openai]" "autogen-agentchat" "autogen-ext[openai]"- Call
rius.init()once, then wrap your entrypoint withobserveas anAGENTspan. Pass the tool as a plain function in the agent’stoolslist:
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)-
Do not wrap AutoGen tool functions with
observe. AutoGen runs tools in a detached context, so the wrapper’s span cannot find the run and splits off as its own single-span trace. The framework’sexecute_toolspans already cover tools. -
To group a conversation, scope each run with
rius.session()and reuse your conversation id. One conversation is then one session. -
Run one request that calls a tool and open the trace in the console. You should see the root span, the
invoke_agentandexecute_toolspans, and the generation with model, tokens and cost.
What you get
A run that calls a tool looks like this, from a real trace of the example on autogen-agentchat 0.7.5:
handle-ticket AGENT 2.8s
├─ create_agent support_agent 0ms
└─ invoke_agent support_agent 2.8s
├─ ChatCompletion LLM 2.6s
└─ execute_tool account_status 0msEach part of the framework maps to a span:
- Your entrypoint: the root
AGENTspan, from yourobservewrapper. - Agent construction: a
create_agentspan named for the agent. - An agent run: an
invoke_agentspan named for the agent. - A model call: a
ChatCompletiongeneration with model, tokens and cost. - A tool call: an
execute_toolspan named for the tool.
Known limits, verified against autogen-agentchat 0.7.5:
- Tool wrappers split traces. Leave
observeoff AutoGen tool functions, as described above. - Framework span statuses arrive as unset. AutoGen’s spans are not marked OK on success, but the trace status still reads Ok.
- Generation names are generic. Every model call is named
ChatCompletion, so tell calls apart by their position in the tree. - Python only. There is no AutoGen integration for TypeScript today.
When something else fits
If your agent calls models through a client other than the OpenAI client, check the integrations list for the integration that covers that client. For an agent in TypeScript, the same list shows which frameworks have TypeScript support. You can trace those calls yourself with manual generations.