Configuring Telemetry for Your AI Application
Rhesis traces every LLM call, tool invocation, retrieval, and agent handoff your application makes, then renders them as a navigable trace tree in the dashboard. This guide helps you pick the right way to wire that up and points you to a focused subguide for each mode.
What You’ll Achieve
- A working trace pipeline from your application to the Rhesis dashboard
- The right level of abstraction for your stack: zero-code, decorator-based, fully manual, or spec-native
- Multi-turn conversation tracking, if your application is a chat or agent loop rather than single-shot calls
Prerequisites
Every mode below builds on the same client initialization:
Or via environment variables, so RhesisClient() needs no arguments:
Initializing RhesisClient wires up the full export pipeline behind the scenes: see How Telemetry Flows below.
Already using the SDK to run tests? RhesisClient() is likely initialized somewhere already. You do not need a second instance for telemetry; the same client wires up tracing.
Which Mode Fits Your Stack?
The table below has the full detail (which frameworks, which code changes); the diagram only needs to carry the decision logic.
| Mode | Best for | Code changes | Guide |
|---|---|---|---|
| Auto-instrumentation | LangChain, LangGraph, Microsoft Agent Framework, Pydantic AI apps | None | Auto-Instrumentation |
| Decorators | Custom code, unsupported frameworks (CrewAI, OpenAI Agents SDK, …) | Add @observe / @endpoint | Decorators |
| Raw OpenTelemetry | Third-party code you can’t decorate, or full control over span attributes | Manual span creation | Raw OpenTelemetry |
| GenAI semantic conventions | Framework/runtime authors who want backend-neutral telemetry | Emit gen_ai.* spans | GenAI Semantic Conventions |
These modes compose. Most real applications mix at least two: for example auto_instrument("langchain") for the framework layer plus @observe.guardrail() around a hand-rolled safety check.
How Telemetry Flows
Regardless of which mode you pick, every span ends up funneled through the same pipeline:
RhesisClient() creates this pipeline once as a process-wide singleton (get_tracer_provider()), registers it as the global OpenTelemetry TracerProvider, and every trace.get_tracer(...) call afterward feeds into it automatically. You only need to set this up manually if you skip RhesisClient() entirely: see Raw OpenTelemetry.
Tracking Multi-Turn Conversations
Single-shot calls need no extra configuration: each gets its own trace. Chat and agent applications that span multiple turns need two additional pieces of context so the dashboard groups turns into one conversation:
conversation_id: a stable identifier shared across turns (your session ID)conversation_trace_id: the sharedtrace_idall turns reuse, so the whole conversation renders as a single trace with turn markers
The easiest path is returning a session_id from an @endpoint-decorated function: the Rhesis connector manages trace continuity for you automatically. Manual context management (for @observe or raw OTel) is covered in each subguide’s conversation section. For the full reference, see Conversation Tracing.
Next Steps
Related:
- Tracing Overview - concepts and terminology
- Multi-Agent Tracing - agent and handoff spans
- Semantic Conventions Reference - full
ai.*attribute reference