Skip to main content
Conduit emits OpenTelemetry signals for everything it does: a trace for every request and tool call, an event (an OTel log record) for every sign-in, configuration change, provisioning action and tool call, the application’s own logs, and aggregate metrics. Exporters deliver them over OTLP to any backend that ingests it — an OpenTelemetry Collector, Datadog, Honeycomb, Grafana, HyperDX, and the rest. Exporters exist at two levels, and they answer different questions. Exporters hot-reload: saving takes effect on every replica within moments, no restart needed.

What telemetry contains

Telemetry describes what Conduit did, not what your members’ tools said.
  • People are identified by id. Spans and events carry user.id, never an email address or a display name. The audit log is where the actor’s email lives, and each audit entry carries actor_user_id, trace_id and span_id to join it to telemetry. Client IP (client.address) and user agent (user_agent.original, capped at 256 bytes) remain, as the source signal for security events.
  • Names a workspace gives its own settings — its policies, groups, identity providers, SCIM tokens and API clients — are sent only to that workspace’s exporters. Instance exporters get their ids, since they are the operator’s backend. Names of instance-level settings (instance identity providers, workspace assignment rules) go to instance exporters.
  • Connector names and verified domains go to every exporter, instance exporters included. Traces, events and the connector label on metrics use connector names, and so do tool and prompt names, which begin with their connector’s name. The event recording a workspace domain change carries the domain. Don’t put anything in a connector name that the operator’s backend shouldn’t hold.
  • Never included: tool call arguments and results, prompt arguments, completion input, resource URIs (a resource read carries only the URI’s scheme), the bodies of upstream requests and responses, and credentials. Connector URLs appear as scheme://host only, since a URL can carry a key in its path or query.
  • Errors from member calls — a tool call, prompt fetch, resource read or completion that failed — carry a stable error.type (listed below) plus the HTTP status and JSON-RPC code, never the upstream’s message, which can repeat what the member sent. The member who made the call always sees the full message in their client. For a failed tool call, the message is also kept in Conduit’s own database, and administrators see it among the recent tool calls on the Usage page. For a failed prompt fetch or resource read, the first 512 bytes of the message are also kept in Conduit’s database (a resource read’s URI too), though no page shows them yet. A failed completion’s message isn’t kept.
  • Errors from connection-level requests — listing a connector’s tools, the MCP handshake, token exchanges — keep the first 256 bytes of the upstream’s message in application logs and span status, because that text describes the integration (a revoked credential, a wrong URL) and is what an operator needs to fix it. Workspace exporters never receive it.
  • Bounded text: every string attribute is valid UTF-8 and capped — 1 KiB on events and application logs, 16 KiB for stack traces, and 16,384 characters for any span attribute — so a single malformed or oversized value can never cause a collector to reject a whole batch.
These rules are the same for every deployment, whether you run Conduit yourself or use Conduit Cloud; there is no setting that loosens them. To strip more before data reaches your backend (for example, hashing IP addresses), use the OpenTelemetry Collector’s redaction processor.

Where each kind of data lives

Error types on MCP events

The conduit.mcp.tool.called, conduit.mcp.prompt.fetched and conduit.mcp.resource.read events carry error.type when the call failed: Every audit entry carries actor_user_id, trace_id and span_id, so a span or event in your backend leads to the audit entry behind it without the telemetry itself holding an email address.

Instance exporters

An instance exporter is the operator’s view of the deployment. It receives every signal the process produces, so it is the right place for the backend your platform team watches. Add one in Settings → Instance → Telemetry with a name, a protocol, an endpoint, and optional headers (typically an API key for a hosted backend). Header values are write-only: once saved they are never shown again, and editing an exporter without re-entering a value keeps the stored one — unless the edit changes the exporter’s endpoint or protocol, which drops the stored headers, so re-enter them for the new collector. The service name field sets the service.name resource attribute on everything sent to instance exporters (default conduit); the rest of the deployment’s resource comes from the standard OTEL_RESOURCE_ATTRIBUTES variable. Exporters can also come from the environment. When the standard OTEL_EXPORTER_OTLP_* variables are set, Conduit configures an exporter from them at startup and shows it, read-only, alongside the ones configured in the UI. This is the recommended way to reach a node-local agent or sidecar, whose address belongs to the deployment rather than to the database: Conduit honors the standard variables directly: the generic and per-signal endpoint variables, OTEL_EXPORTER_OTLP_PROTOCOL (default http/protobuf), OTEL_EXPORTER_OTLP_HEADERS, and the TLS, timeout, and compression variables. See the OTLP exporter specification. The exporter’s display name comes from CONDUIT_OTEL_EXPORTER_NAME.

Workspace exporters

A workspace exporter is a tenant’s view of their own activity. In a multi-workspace deployment it lets each workspace’s team send their telemetry to their own backend without the operator forwarding and filtering it for them. A workspace’s exporters receive:
  • Traces of every request made within the workspace: its members’ MCP traffic and tool calls (including the upstream calls those make), its administrators’ settings changes, and SCIM provisioning pushed by its identity provider.
  • Events produced by those requests — the same records that appear in the workspace’s audit log, plus the tool-call and policy-denial events that don’t.
They never receive activity from another workspace, or instance administration — a change an instance administrator makes from the instance console (a rename, a member removed there) is the operator’s activity, not the workspace’s, and an instance administration tool invoked over the workspace’s MCP endpoint sends only the tool call itself, not what the tool did. Metrics are aggregates over the whole instance with no per-workspace dimension, and Conduit’s own application logs are the operator’s diagnostics; both go to instance exporters only. A span’s failure detail is redacted for a workspace: the error status and the stable error type stay, while the error message and stack trace — which can name internal hosts and paths — are dropped. In the other direction, events about the workspace’s own settings carry their names (policy.name, group.name, idp.name, scim_token.label, api_client.name, scim.idp_name) on the workspace’s copy only. Resource attributes. Everything sent to a workspace’s exporters carries the OpenTelemetry resource attributes the workspace sets in Settings → Telemetry — for example service.name or deployment.environment — and service.name defaults to conduit when the workspace sets none. The deployment’s own resource, including anything in OTEL_RESOURCE_ATTRIBUTES, describes the operator’s installation and goes to instance exporters only. Every span and log record a workspace exporter receives carries the attribute conduit.workspace.id naming the workspace. Instance exporters see the same attribute on workspace-scoped signals, which makes it the key to filter an instance backend by tenant. Workspace administrators add exporters in Settings → Telemetry (workspace settings), with the same name, protocol, endpoint, and write-only headers as instance exporters. Renaming keeps stored headers, while changing the protocol or endpoint clears them so credentials are never carried to a different collector. Workspace exporters have two restrictions that follow from the endpoint being configured by a tenant rather than the operator:
  • The endpoint must be an https URL (no plaintext, no private or internal address), using HTTP/Protobuf or HTTP/JSON. Traces are sent to /v1/traces and events to /v1/logs under the endpoint you give, so either the base URL or a signal path works. A workspace may have one exporter.
  • Export requests go through the same hardened outbound client as connectors: a hostname that resolves to a private or internal address is refused unless the operator has listed it in CONDUIT_SAFEHTTP_ALLOWED_PRIVATE_HOSTS. An operator who wants workspaces to share an in-cluster collector lists its hostname there; see Network Access.
A workspace exporter that cannot be reached backs up only its own queue: it never delays a tool call, and never affects the instance’s exporters or another workspace’s. Conduit creates a workspace’s export pipeline when that workspace first produces telemetry. Each replica keeps the 64 most recently used workspace pipelines active; activating another flushes and recycles the least recently used pipeline without removing its configuration. Sustained cache churn produces a warning in the instance log, while occasional eviction of a cold pipeline is silent. In a single-workspace deployment the one workspace is the instance, so this page is not shown; configure telemetry on the instance page, where the deployment’s resource attributes apply.

Where each signal lands

Traces go to <endpoint>/v1/traces, logs and events to <endpoint>/v1/logs, and metrics to <endpoint>/v1/metrics. Configure the endpoint as the base URL or with any of those paths; all work.

When an export fails

A failed export is reported in Conduit’s console log on a line starting with otel:, carrying what the collector said (a timeout, a refused connection, an unknown service). A failure that recurs on every batch — a collector that is down — is reported once, then once a minute with the number of repeats since the previous line, for as long as it lasts. A collector that does not serve one of the signals is handled separately. Some backends accept traces but have no receiver for logs or metrics; over gRPC such a collector answers Unimplemented, and the batch cannot be delivered by retrying. Conduit reports that once, naming the exporter and the signal, then stops sending that signal to that exporter and probes it with one batch every five minutes. When the collector starts serving the signal — after you add the receiver and restart it — Conduit reports that it is resuming and sends normally again. The exporter’s other signals are unaffected throughout. Over HTTP a collector reports a missing receiver as a plain error, which is logged like any other failure.