Connect your agent
OpenTelemetry
Send existing OpenTelemetry traces through the project endpoint without replacing your instrumentation.
Send your application’s existing OpenTelemetry traces to Radiant through its SDK provider or collector. Choose the provider setup when the application exports directly, or configure the collector when it already receives your traces.
Export configuration preserves the recorded operations and their relationships. If you need to instrument a custom agent, add agent and tool spans after configuring export.
Get the project’s traces endpoint and ingestion key from Set up your project. The examples below use OTLP over HTTP/protobuf.
Add an exporter to an existing provider
Section titled “Add an exporter to an existing provider”For a Python application using the OpenTelemetry SDK:
python -m pip install opentelemetry-exporter-otlp-proto-httpexport RADIANT_TRACES_ENDPOINT='https://YOUR_INGESTION_HOST/v1/traces'export RADIANT_INGESTION_KEY='YOUR_INGESTION_KEY'Add the processor during application initialization, using the existing SDK TracerProvider as provider:
import osfrom opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporterfrom opentelemetry.sdk.trace.export import BatchSpanProcessor
provider.add_span_processor( BatchSpanProcessor( OTLPSpanExporter( endpoint=os.environ["RADIANT_TRACES_ENDPOINT"], headers={"Authorization": "Bearer " + os.environ["RADIANT_INGESTION_KEY"]}, ) ))Keep the provider’s existing resource attributes, including service.name, and its other exporters. Configure shutdown or flushing through the lifecycle that already owns the provider. Do not initialize another global provider or create one for every request.
If the application has no SDK provider yet, create a TracerProvider with the application’s resource attributes, add the processor, and register it with trace.set_tracer_provider(provider) before instrumented work begins.
Export through a collector
Section titled “Export through a collector”If the application already sends spans to an OpenTelemetry Collector, add a named OTLP/HTTP exporter instead of sending a duplicate stream from the application. Add this exporter definition, then append otlp_http/radiant to the existing traces pipeline’s exporters list. Keep its receivers, processors, and other exporters. Set the same Radiant endpoint and key in the collector’s environment.
exporters: otlp_http/radiant: traces_endpoint: ${env:RADIANT_TRACES_ENDPOINT} headers: Authorization: 'Bearer ${env:RADIANT_INGESTION_KEY}' compression: noneRadiant requires uncompressed requests; the collector exporter enables gzip by default. Current collectors name the component otlp_http. On older collectors, use otlphttp/radiant in both the exporter definition and the pipeline.
Use the collector’s OTLP/HTTP exporter configuration for the exact configuration keys. A traces-specific endpoint contains /v1/traces; a base OTLP endpoint can have that path appended automatically, so do not append it twice.
Add agent and tool spans
Section titled “Add agent and tool spans”If your application already emits agent and tool spans, keep that instrumentation. For a custom agent, follow the OpenTelemetry GenAI agent and tool conventions at the existing invocation and tool-execution boundaries.
With your SDK provider registered, obtain a tracer and wrap the application’s existing agent call. Here, agent_name, run_agent and request are the name, invocation function and input already used by your application:
from opentelemetry import trace
tracer = trace.get_tracer(__name__)with tracer.start_as_current_span( f"invoke_agent {agent_name}", attributes={ "gen_ai.operation.name": "invoke_agent", "gen_ai.agent.name": agent_name, },) as agent_span: result = run_agent(request)Inside the existing tool dispatcher or tool function, add a span around the call it already makes. tool_name, execute_tool and arguments below represent that existing tool and its input:
with tracer.start_as_current_span( f"execute_tool {tool_name}", attributes={ "gen_ai.operation.name": "execute_tool", "gen_ai.tool.name": tool_name, },) as span: result = execute_tool(arguments)When the tool executes within the active agent span, it becomes that invocation’s child. Keep the parent span open through asynchronous work or stream consumption. Propagate OpenTelemetry context explicitly across process or queue boundaries.
If the application captures tool payloads, record the selected arguments and result as JSON strings on the tool span:
import json
span.set_attribute("gen_ai.tool.call.arguments", json.dumps(arguments))span.set_attribute("gen_ai.tool.call.result", json.dumps(result))Set these attributes before the tool span ends. Include only the values intended for telemetry. You can also record gen_ai.tool.call.id when the application has a stable call identifier. See the telemetry reference for additional recognized agent, model, and tool fields.
Record model inputs and outputs
Section titled “Record model inputs and outputs”Agent and tool spans do not capture model requests automatically. Add the instrumentation for the model client your application actually uses. For an OpenAI Python client, the upstream instrumentor records Chat Completions and Responses calls, including model identity and token usage:
python -m pip install opentelemetry-instrumentation-genai-openai==1.3b0Enable message content before starting the application, then register the instrumentor at startup, after the provider and before creating model clients:
export OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT='SPAN_ONLY'from opentelemetry.instrumentation.genai.openai import OpenAIInstrumentor
OpenAIInstrumentor().instrument()Existing client calls inside the active agent span now produce child model spans. With content capture enabled, those spans contain the actual request and response messages in gen_ai.input.messages and gen_ai.output.messages. Token usage comes from the model response. Radiant uses the captured messages to render the model record’s Thread.
This configuration applies to the OpenAI client; use the corresponding instrumentation for other model libraries. If you instrument a model client yourself, record its actual messages and usage using the GenAI model fields and message format. Avoid adding another client instrumentor when a framework integration already records the same model calls.
The upstream OpenAI instrumentor documents supported client versions and content-capture controls. Message capture is off by default; enable it for the payloads your application intends to export.
Add attributes
Section titled “Add attributes”Resource attributes describe the process and apply to all of its spans. Put request-specific identifiers on the operation that owns them.
Inside the agent span, add identifiers that your application already uses. Set these before run_agent(request) in the invocation example:
agent_span.set_attribute("gen_ai.conversation.id", conversation_id)agent_span.set_attribute("gen_ai.agent.version", agent_version)Here, conversation_id identifies the conversation and agent_version identifies the agent release. These attributes apply to this invocation, not automatically to its child spans. The Conversations view groups agent runs by gen_ai.conversation.id; the version appears in Agents and versions. See Telemetry reference for field definitions.
Inspect the exported activity
Section titled “Inspect the exported activity”Run an existing application request and find its service in the project’s Logs. Open the trace and confirm that the expected operations and relationships are present. The exporter sends recorded values; it does not infer missing messages, token usage or agent identity.
Recognized agent invocations also require the agent span attributes. The telemetry reference defines model and tool fields, usage, content formats and correlation. For missing traces, check export and authentication troubleshooting.
Copyright © 2026, Radiant AI Limited.