Skip to content

OpenTelemetry

AgentLens supports OpenTelemetry in two directions:

  1. Export — bridge AgentLens spans to any OTel-compatible backend (Jaeger, Tempo, DataDog, etc.)
  2. Ingest — receive OTLP HTTP JSON spans from any OTel-instrumented app
from agentlens.exporters.otel import AgentLensOTelExporter
import agentlens
agentlens.configure(server_url="http://localhost:3000")
agentlens.add_exporter(AgentLensOTelExporter())
# Now spans are sent to both AgentLens AND your OTel backend
@agentlens.trace(name="MyAgent")
def run():
with agentlens.span("search", "tool_call") as s:
result = do_search()
s.set_output(result)

Any app instrumented with the OpenTelemetry SDK can send spans directly to AgentLens via the OTLP HTTP JSON endpoint.

Terminal window
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:3000/api/otel
export OTEL_EXPORTER_OTLP_PROTOCOL=http/json
import requests
requests.post("http://localhost:3000/api/otel/v1/traces", json={
"resourceSpans": [{
"resource": {
"attributes": [
{"key": "service.name", "value": {"stringValue": "my-agent"}}
]
},
"scopeSpans": [{
"spans": [{
"traceId": "abc123",
"spanId": "span001",
"parentSpanId": "",
"name": "agent_run",
"kind": 2,
"startTimeUnixNano": "1700000000000000000",
"endTimeUnixNano": "1700000001000000000",
"attributes": [],
"status": {"code": 1}
}]
}]
}]
})

OTel span kinds are mapped to AgentLens span types:

OTel KindAgentLens Type
SERVER (2)agent_run
CLIENT (3)tool_call
INTERNAL (1)llm_call
anything elsetask

The service.name resource attribute becomes the agent_name in AgentLens (fallback: "otel").

AgentLens accepts OTLP HTTP JSON only. gRPC and binary protobuf are not supported.