Skip to content
AgentEnsemble AgentEnsemble
Get Started

OpenTelemetry Integration

The agentensemble-telemetry-opentelemetry module creates OpenTelemetry spans at framework boundaries for distributed tracing.


dependencies {
implementation("net.agentensemble:agentensemble-telemetry-opentelemetry:3.3.0")
implementation("io.opentelemetry:opentelemetry-api:1.47.0")
}
import net.agentensemble.telemetry.otel.OTelTracingListener;
OpenTelemetry otel = // configure your OTel SDK
OTelTracingListener listener = OTelTracingListener.create(otel);
Ensemble.builder()
.chatLanguageModel(model)
.listener(listener)
.task(Task.of("Research AI trends"))
.build()
.run();
// After run, the trace ID is available
String traceId = listener.getTraceId();

SpanWhenKind
ensemble.runRoot span for an ensemble executionINTERNAL
task.executePer-task child spanINTERNAL
tool.executePer-tool-call child spanINTERNAL
network.delegateWhen calling another ensembleCLIENT

All spans carry AgentEnsemble-specific attributes:

AttributeDescription
agentensemble.ensemble.nameEnsemble ID
agentensemble.task.descriptionTask description
agentensemble.agent.roleAgent role
agentensemble.delegation.targetTarget worker role
agentensemble.tool.nameTool name
agentensemble.task.indexTask index (1-based)
agentensemble.duration_msDuration in milliseconds

Cross-ensemble requests carry W3C trace context via the TraceContextPropagator:

// Extract trace context from incoming WorkRequest
SpanContext remoteCtx = TraceContextPropagator.extractFromTraceparent(
request.traceContext().traceparent());
// Inject trace context into outgoing request
String traceparent = TraceContextPropagator.injectTraceparent(currentSpan);

When OTelTracingListener is registered, the ExecutionTrace.traceId field is populated with the OTel trace ID. This allows linking the AgentEnsemble trace to the distributed trace in your external viewer (Jaeger, Grafana Tempo, etc.).

EnsembleOutput output = ensemble.run();
String traceId = output.getTrace().getTraceId();
// -> "4bf92f3577b34da6a3ce929d0e0e4736"

The module is backend-agnostic. Configure your OTel SDK to export to your preferred backend: Jaeger, Grafana Tempo, Zipkin, Datadog, etc.