Skip to main content
Spectrum-TS has built-in OpenTelemetry instrumentation. Enable it with telemetry: true, then route its OTLP exporter to Agnost with standard OTEL_EXPORTER_OTLP_* environment variables. Note: Spectrum telemetry is exported by the spectrum-ts package itself, so the app must have spectrum-ts installed. The umbrella package includes the official provider packages; install a scoped @spectrum-ts/* package only if the app imports that provider directly.

1. Install

Already have spectrum-ts installed? Skip.
npm install spectrum-ts
Official provider imports:
ProviderUmbrella importDirect package
Telegramspectrum-ts/providers/telegram@spectrum-ts/telegram
Slackspectrum-ts/providers/slack@spectrum-ts/slack
WhatsApp Businessspectrum-ts/providers/whatsapp-business@spectrum-ts/whatsapp-business
iMessagespectrum-ts/providers/imessage@spectrum-ts/imessage
Terminalspectrum-ts/providers/terminal@spectrum-ts/terminal

2. Point Spectrum telemetry at Agnost

Set these before starting the Spectrum app:
export AGNOST_ORG_ID=<your-org-id>
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://otel.agnost.ai/v1/traces
export OTEL_EXPORTER_OTLP_HEADERS="X-Agnost-Org-ID=$AGNOST_ORG_ID"
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

3. Enable Spectrum telemetry

import { randomBytes } from "node:crypto";
import { Spectrum } from "spectrum-ts";
import { telegram } from "spectrum-ts/providers/telegram";

const hex = (bytes: number) => randomBytes(bytes).toString("hex");
const nsNow = () => String(BigInt(Date.now()) * 1_000_000n);
const otelValue = (value: string) => ({ stringValue: value });

async function emitAgnostTurn(input: string, output: string, spaceId: string, userId?: string) {
  await fetch(process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT!, {
    method: "POST",
    headers: {
      "content-type": "application/json",
      "X-Agnost-Org-ID": process.env.AGNOST_ORG_ID!,
    },
    body: JSON.stringify({
      resourceSpans: [{
        resource: { attributes: [{ key: "service.name", value: otelValue("spectrum-ts") }] },
        scopeSpans: [{
          scope: { name: "agnost-spectrum-text" },
          spans: [{
            traceId: hex(16),
            spanId: hex(8),
            name: "tool.spectrum.turn",
            kind: 1,
            startTimeUnixNano: nsNow(),
            endTimeUnixNano: nsNow(),
            status: { code: 1 },
            attributes: [
              { key: "agnost.session_id", value: otelValue(spaceId) },
              ...(userId ? [{ key: "agnost.user_id", value: otelValue(userId) }] : []),
              { key: "input", value: otelValue(input) },
              { key: "output", value: otelValue(output) },
            ],
          }],
        }],
      }],
    }),
  });
}

const app = await Spectrum({
  projectId: process.env.PROJECT_ID!,
  projectSecret: process.env.PROJECT_SECRET!,
  providers: [
    // Telegram is only an example. Any official Spectrum provider works with
    // the same telemetry config.
    telegram.config({ botToken: process.env.TELEGRAM_BOT_TOKEN! }),
  ],
  telemetry: true,
});

for await (const [space, message] of app.messages) {
  if (message.content.type !== "text") continue;

  const input = message.content.text;
  const output = `Echo: ${input}`;
  await space.send(output);
  await emitAgnostTurn(input, output, space.id, message.sender?.id);
}
telemetry: true sends Spectrum’s native spans for provider/session/message metadata. The tool.spectrum.turn span sends the transcript text that Agnost Chat View renders.

Local Sample

npm create spectrum-project@latest clank -- --providers telegram
cd clank

export PROJECT_ID=<spectrum-project-id>
export PROJECT_SECRET=<spectrum-project-secret>
export TELEGRAM_BOT_TOKEN=<telegram-bot-token>
export AGNOST_ORG_ID=<your-org-id>
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://otel.agnost.ai/v1/traces
export OTEL_EXPORTER_OTLP_HEADERS="X-Agnost-Org-ID=$AGNOST_ORG_ID"
export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
Use the provider you need, for example telegram, slack, whatsapp-business, imessage, or terminal. Then set telemetry: true in the generated Spectrum(...) config. For transcript text, add the small tool.spectrum.turn OTLP JSON helper from the sample app.

References