Skip to content
Connect AI Assets

OpenTelemetry SDK (vendor-neutral) ​

If you're not using a SAP SDK, instrument directly with the OpenTelemetry SDK in any language. Boidra Platform only cares that your spans carry the GenAI attributes and reach the OTLP/HTTP endpoint.

Configure the exporter ​

bash
export OTEL_EXPORTER_OTLP_ENDPOINT="https://<your-dashboard-host>/otel"
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"   # if your SDK defaults to gRPC

The SDK appends /v1/traces, so spans post to /otel/v1/traces.

The attributes per span type ​

Set gen_ai.operation.name to classify the span, then the fields for that type.

Agent turn (invoke_agent) ​

gen_ai.operation.name = "invoke_agent"
gen_ai.agent.name      = "support-agent"
gen_ai.request.model   = "gpt-4o"           # optional at the agent level
gen_ai.conversation.id = "conv-123"         # optional; groups a conversation

LLM call (chat) ​

gen_ai.operation.name       = "chat"
gen_ai.request.model        = "gpt-4o"
gen_ai.usage.input_tokens   = 1200
gen_ai.usage.output_tokens  = 340

Tool / MCP call (execute_tool) ​

gen_ai.operation.name = "execute_tool"
gen_ai.tool.name      = "get_incident"
gen_ai.tool.type      = "mcp"               # or "function"

Nest chat/tool spans under the agent span (via the active context / parent span) so they group into one trace.

Example (Node/TypeScript) ​

ts
import { NodeSDK } from "@opentelemetry/sdk-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
import { trace, SpanStatusCode } from "@opentelemetry/api";

new NodeSDK({ traceExporter: new OTLPTraceExporter() }).start();

const tracer = trace.getTracer("support-agent");

export async function handleTurn(query: string) {
  return tracer.startActiveSpan("invoke_agent support-agent", async (agentSpan) => {
    agentSpan.setAttributes({
      "gen_ai.operation.name": "invoke_agent",
      "gen_ai.agent.name": "support-agent",
      "gen_ai.conversation.id": "conv-123",
    });
    try {
      // LLM call as a child span
      await tracer.startActiveSpan("chat", async (chatSpan) => {
        chatSpan.setAttributes({
          "gen_ai.operation.name": "chat",
          "gen_ai.request.model": "gpt-4o",
          "gen_ai.usage.input_tokens": 1200,
          "gen_ai.usage.output_tokens": 340,
        });
        // ... call the model ...
        chatSpan.end();
      });

      // Tool call as a child span
      await tracer.startActiveSpan("execute_tool", async (toolSpan) => {
        toolSpan.setAttributes({
          "gen_ai.operation.name": "execute_tool",
          "gen_ai.tool.name": "get_incident",
          "gen_ai.tool.type": "mcp",
        });
        // ... run the tool ...
        toolSpan.end();
      });
    } catch (err) {
      agentSpan.setStatus({ code: SpanStatusCode.ERROR, message: String(err) });
      throw err;
    } finally {
      agentSpan.end();
    }
  });
}

Errors ​

Boidra Platform marks a span as ERROR when the OpenTelemetry span status is ERROR (SpanStatusCode.ERROR), or when the attribute error = true / outcome = "error" is set. The status message becomes the error message in the UI.

Other languages ​

The same attributes apply in Python, Java, Go, etc. — set gen_ai.* on your spans and export via OTLP/HTTP to /otel/v1/traces. See the OTLP attributes reference for the complete list.

Boidra — multi-agent AI systems in the SAP ecosystem.