Observability

Choose Who Exports Your Traces

Decide whether ArmorIQ or your application owns the OpenTelemetry tracer provider, and set the destination for your traces.

This page is for developers and platform engineers who already run OpenTelemetry, or who want to send ArmorIQ traces to another tool. You learn the three export choices, who owns the tracer provider in each one, and how to configure them.

Terms used on this page

  • A span is one timed step in an agent run, for example one tool call. A trace is all the spans of one run.
  • A TracerProvider is the OpenTelemetry object that creates spans and passes them to an exporter.
  • An exporter sends finished spans to a destination.
  • OTLP (OpenTelemetry Protocol) is the standard format and HTTP route that OpenTelemetry tools use to exchange traces. The SDK sends OTLP over HTTP with protobuf encoding (http/protobuf). It supports no other OTLP encoding.
  • An OpenTelemetry Collector is a service that you run. It receives spans, processes them, and forwards them to one or more destinations. See Deploy an OpenTelemetry Collector.

The three choices

One SDK runtime has exactly one export choice. You set it with the exporter option.

exporterWho owns the TracerProviderWhere spans goData limit
armoriq (default)ArmorIQ (a private provider inside the SDK)POST /v1/traces on your ArmorIQ backend, with your API keyThe organization capture policy
externalArmorIQ (a private provider inside the SDK)The OTLP endpoint that you set, for example a CollectorThe organization capture policy. Prompt and tool content leave only if the organization also allows external content.
providerYour applicationWherever your own provider sends themMetadata only, always

If you set an unknown value in the exporter option, the SDK uses armoriq.

ArmorIQ-owned provider

With armoriq and external, the SDK builds a private tracer provider with its own batch exporter. The provider stays isolated from your application:

  • The SDK never registers its provider as the global OpenTelemetry provider.
  • The SDK never changes, replaces, or shuts down a provider that your application created.
  • In TypeScript, ArmorIQ spans start from an empty trace context. The trace context of your own web request does not leak into the ArmorIQ trace.
  • When the session or client closes, the SDK flushes its own provider, and shuts it down when the last user of that provider closes. A close is bounded in time. It never blocks your agent for long.

Use these choices when you want ArmorIQ to manage export and keep your own OpenTelemetry setup unchanged.

Application-owned provider

With provider, you pass your own tracer provider. The SDK only asks it for a tracer named armoriq_sdk. Then:

  • The SDK adds no span processor and no exporter to your provider.
  • The SDK never flushes, shuts down, or changes your provider. You control destination, sampling, and batching.
  • ArmorIQ capture is limited to metadata. The SDK cannot re-check the organization policy on spans that wait in a queue that it does not own. So it never records prompts, completions, tool arguments, or tool results in this mode. To capture content, use armoriq or external.
  • In TypeScript, the root span of a session becomes a child of the active span in your application.

Provider mode needs a provider. If you set exporter to provider and give no provider, the SDK exports nothing. See Troubleshooting.

Configure the export

import os
from armoriq_sdk import ArmorIQClient, ObservabilityOptions

# 1. ArmorIQ OTLP (default). No options needed.
client = ArmorIQClient(api_key=os.environ["ARMORIQ_API_KEY"])

# 2. Your own OTLP endpoint, for example a Collector.
client = ArmorIQClient(
    api_key=os.environ["ARMORIQ_API_KEY"],
    observability=ObservabilityOptions(
        exporter="external",
        endpoint="https://collector.example.com/v1/traces",
        headers={"authorization": f"Bearer {os.environ['COLLECTOR_TOKEN']}"},
    ),
)

# 3. Your own tracer provider.
client = ArmorIQClient(
    api_key=os.environ["ARMORIQ_API_KEY"],
    observability=ObservabilityOptions(
        exporter="provider",
        tracer_provider=my_tracer_provider,
    ),
)
import { ArmorIQClient } from '@armoriq/sdk';

// 1. ArmorIQ OTLP (default). No options needed.
const client = new ArmorIQClient({ apiKey: process.env.ARMORIQ_API_KEY! });

// 2. Your own OTLP endpoint, for example a Collector.
const external = new ArmorIQClient({
  apiKey: process.env.ARMORIQ_API_KEY!,
  observability: {
    exporter: 'external',
    endpoint: 'https://collector.example.com/v1/traces',
    headers: { Authorization: `Bearer ${process.env.COLLECTOR_TOKEN}` },
  },
});

// 3. Your own tracer provider.
const session = client.startSession({
  observability: { exporter: 'provider', tracerProvider: myTracerProvider },
});

You can use the standard OpenTelemetry environment variables instead of code. Keep tokens in a secret store and inject them as environment variables. Do not write them in source files.

export ARMORIQ_OTEL_EXPORTER=external
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://collector.example.com/v1/traces
export OTEL_EXPORTER_OTLP_TRACES_HEADERS="authorization=Bearer%20${COLLECTOR_TOKEN}"

Header values use URL encoding, so a space is %20. Do not set a content-type header. The SDK always sends application/x-protobuf.

Rules for the endpoint

  • Use https: for any host that is not on your own machine. The SDK accepts http: only for localhost, 127.0.0.1, and ::1. A plain http: request would send your headers and permitted content in clear text.
  • Do not put a user name, password, query string, or fragment in the URL.
  • The SDK uses the first endpoint setting that it finds. It does not try the next one when the first is invalid. If that setting is not valid, the SDK exports nothing.
  • If you set no endpoint, the SDK exports nothing. It does not fall back to localhost. It does not fall back to ArmorIQ.
  • After an export fails, the SDK does not switch to another destination.

Settings reference

SettingPythonTypeScript
Pick the exporterObservabilityOptions(exporter=...). The variable ARMORIQ_OTEL_EXPORTER overrides the option.observability.exporter. The option wins over ARMORIQ_OTEL_EXPORTER. If you set neither and an endpoint setting exists, the SDK chooses external.
Endpoint order (first one set is used)endpoint option, ARMORIQ_OTEL_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, then OTEL_EXPORTER_OTLP_ENDPOINTendpoint option, baseEndpoint option, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_ENDPOINT, then ARMORIQ_OTEL_ENDPOINT
Base endpoint formOTEL_EXPORTER_OTLP_ENDPOINT. The SDK adds /v1/traces.baseEndpoint option or OTEL_EXPORTER_OTLP_ENDPOINT. The SDK adds /v1/traces.
HeadersOTEL_EXPORTER_OTLP_HEADERS, then OTEL_EXPORTER_OTLP_TRACES_HEADERS, then the headers option. Later items win.Same order
Timeouttimeout_millis, OTEL_EXPORTER_OTLP_TRACES_TIMEOUT, OTEL_EXPORTER_OTLP_TIMEOUT, ARMORIQ_OTEL_EXPORT_TIMEOUT_MS. Default 10 seconds. The SDK keeps the value between 0.1 and 30 seconds.timeoutMillis, OTEL_EXPORTER_OTLP_TRACES_TIMEOUT, OTEL_EXPORTER_OTLP_TIMEOUT. Default 10 seconds. A value that is not a positive whole number turns external export off.
Custom CA and client certificateOTEL_EXPORTER_OTLP_CERTIFICATE, OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE, OTEL_EXPORTER_OTLP_CLIENT_KEY (and the _TRACES_ forms). external only.Not supported. Terminate TLS settings in a Collector.
Service nameservice_name option or OTEL_SERVICE_NAME. The client uses agent_id when you set neither.serviceName option or OTEL_SERVICE_NAME. The default is armoriq-sdk.
Local data ceilingcapture_mode option or ARMORIQ_OTEL_CAPTURE_MODE. The variable overrides the option.captureMode option or ARMORIQ_OTEL_CAPTURE_MODE. The option wins.
Turn tracing offobservability_enabled=False on the session, ObservabilityOptions(enabled=False), or ARMORIQ_OBSERVABILITYobservability.enabled = false, ARMORIQ_OBSERVABILITY, OTEL_SDK_DISABLED=true, or OTEL_TRACES_EXPORTER=none

The TypeScript SDK does not support gRPC, OTLP/JSON, request compression, HTTP proxy settings, or mTLS in its own exporter. If you need one of these, send to a Collector and set it there.

What every export choice still obeys

  • The organization policy is the upper limit. The SDK reads your organization capture policy with your API key. A local setting can only lower the data that you capture. It can never raise it. See Organization controls.
  • External export waits for the policy. With external, the TypeScript SDK waits up to 1.4 seconds for the policy before the first trace of a session. If the policy does not arrive in time, external export stays off for that session. The agent runs as normal.
  • Failures never change the agent result. A slow or broken destination can drop spans. It never changes what your agent returns.
  • No API key leaves ArmorIQ. The external choice sends only the headers that you configure. It does not send your ArmorIQ API key to the destination.

Which choice should I use?

  • Use armoriq if you only need ArmorIQ dashboards. This is the default.
  • Use external with a Collector if you want to send traces to ArmorIQ and to another tool. The Collector can send the same spans to both. See Deploy an OpenTelemetry Collector.
  • Use provider only if your application must own the export pipeline. You accept the metadata-only limit.

Next steps

On this page