pi-otel

OpenTelemetry traces for pi-coding-agent — per-prompt span tree (interaction → llm_request, tool.<name>) exported via OTLP. Aspire-dashboard ready.

Packages

Package details

extension

Install pi-otel from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-otel
Package
pi-otel
Version
0.3.0
Published
Sep 13, 2026
Downloads
4,497/mo · 1,349/wk
Author
nikiforovall
License
Apache-2.0
Types
extension
Size
174.1 KB
Dependencies
8 dependencies · 1 peer
Pi manifest JSON
{
  "image": "https://raw.githubusercontent.com/nikiforovall/pi-otel/master/assets/pi-otel-poster.png",
  "video": "https://raw.githubusercontent.com/NikiforovAll/pi-otel/master/assets/demo.mp4",
  "extensions": [
    "./dist/index.js"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-otel

npm version npm downloads Docs

OpenTelemetry tracing for pi agent.

Full OTel GenAI semantic-convention coverage (gen_ai.*) for token usage, cost, model, finish reasons, and tool calls.

Install

pi install npm:pi-otel

Quickstart

/otel start         # spawn local Aspire dashboard

Backend auto-detect: Aspire CLI first, then Docker / Podman. Install one:

  • Aspire CLI
  • Docker or Podman

Configuration

.pi/settings.json (project) or ~/.pi/agent/settings.json (global):

{
  "otel": {
    "enabled": true,
    "endpoint": "http://localhost:4317",
    "protocol": "grpc",
    "headers": {},
    "serviceName": "pi",
    "captureContent": "metadata_only",
    "spanNaming": "legacy",
    "sampleRatio": 1.0,
    "signals": { "traces": true, "metrics": false, "logs": false }
  }
}

For the http/protobuf and http/json protocols, endpoint is the base URL — each signal appends its own resource path (/v1/traces, /v1/metrics, /v1/logs). For grpc the endpoint is used as-is.

spanNaming: "genai" (default "legacy") renames spans to the OTel GenAI agent conventions — invoke_agent pi / chat {model} / execute_tool {tool} — and adds gen_ai.operation.name plus the spec SpanKind, so backends recognise pi as an agent. It also adds gen_ai.agent.name on the interaction span and, on chat spans only, gen_ai.provider.name (the request's inference provider, e.g. openai, aws.bedrock). No existing attribute is ever removed in either mode; legacy keeps the pi.* names existing dashboards query.

Key env var overrides: OTEL_EXPORTER_OTLP_ENDPOINT, PI_OTEL_SPAN_NAMING=genai, PI_OTEL_METRICS=1, PI_OTEL_LOGS=1, PI_OTEL_DISABLED=1.

Custom providers that skip pi's onPayload hook (pi-vertex and others) still get a pi.llm_request span with tokens and cost, opened from the assistant message_start and tagged pi.llm_request.synthesized=true. See custom providers.

propagateToShell: true (default false) passes TRACEPARENT to processes started by the bash and powershell tools, so instrumented children nest under the tool span. It overrides the built-in tool, which pi reports with a one-time warning. See shell propagation.

Only one OpenTelemetry SDK can own a process. If another extension registers its providers first, pi-otel warns once and stays disabled instead of silently routing spans into the other SDK. See running alongside other OTel extensions.

Full reference — settings, env vars, content capture modes, sampling, logs signal, and extensibility: nikiforovall.blog/pi-otel/configuration