OpenTelemetry
If your stack already emits OpenTelemetry traces, point them at Kelet. No re-instrumentation needed.
OTLP endpoint
Section titled “OTLP endpoint”https://api.kelet.ai/api/tracesAuthentication
Section titled “Authentication”Authorization: <your-api-key>X-Kelet-Project: <project-name>Note: no Bearer prefix — just the raw API key.
Python
Section titled “Python”from opentelemetry.sdk.trace import TracerProviderfrom opentelemetry.sdk.trace.export import BatchSpanProcessorfrom opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
exporter = OTLPSpanExporter( endpoint="https://api.kelet.ai/api/traces", headers={ "Authorization": "your-api-key", "X-Kelet-Project": "my-project", },)
provider = TracerProvider()provider.add_span_processor(BatchSpanProcessor(exporter))Node.js
Section titled “Node.js”import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
const exporter = new OTLPTraceExporter({ url: 'https://api.kelet.ai/api/traces', headers: { Authorization: process.env.KELET_API_KEY, 'X-Kelet-Project': 'my-project', },});
provider.addSpanProcessor(new BatchSpanProcessor(exporter));Multi-project routing
Section titled “Multi-project routing”One process can emit traces to multiple Kelet projects. Tag a root span with kelet.project=<name> — all descendant
spans inherit that project automatically.
with tracer.start_as_current_span("my-agent-root") as span: span.set_attribute("kelet.project", "my-project") # all spans below this go to "my-project" result = await agent.run(...)Priority order per span (highest wins):
span.attributes["kelet.project"]— explicit subtree tag- Ancestor span’s resolved project — inherited automatically
resource["kelet.project"]— resource-level fallback- W3C
baggage: kelet.project=...header — SDK propagation across services X-Kelet-Projectrequest header"default"project
When to use direct OTEL
Section titled “When to use direct OTEL”Use this path if:
- You already emit OTEL traces and want to add Kelet as a second destination
- You use a framework that generates OTEL natively (Langfuse SDK, LiteLLM, OpenInference-based frameworks)
- You need to integrate from a language without a Kelet SDK
Supported frameworks (via OTEL)
Section titled “Supported frameworks (via OTEL)”Tier 1 (tested, fully supported): pydantic-ai, Langfuse SDK, LiteLLM
Tier 2 (community-supported): Vercel AI SDK, OpenLLMetry/Traceloop, OpenInference/Phoenix
Tier 3 (via Tier 1/2 instrumentation): LangChain, LlamaIndex, CrewAI, Agno, OpenAI SDK, Anthropic SDK
Langfuse
Section titled “Langfuse”Langfuse supports OTEL export natively. Point it at Kelet:
import osos.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "https://api.kelet.ai/api/traces"os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = "Authorization=your-api-key,X-Kelet-Project=my-project"Or use the Langfuse integration for polling-based sync without any code changes.