Skip to main content

Overview

Swarms ships with optional OpenTelemetry tracing. When enabled, every agent and swarm run emits a span recording what was asked, what came back, how long it took, and whether it failed — and those spans nest, so a swarm run and every agent run underneath it form a single connected trace. Telemetry is fail-safe by design: if the exporter is unreachable, the configuration is wrong, or the dependency is missing, the instance goes inert and your agents keep running. It never raises into your code.

Turning it on and off

Telemetry is controlled by a single environment variable, SWARMS_TELEMETRY_ON.
Accepted “on” values are exactly "True", "true", and "1". Anything else — including "yes", "TRUE", or an empty string — is off.
The gate is read once per process, at first use. Changing SWARMS_TELEMETRY_ON at runtime has no effect until you restart. This is deliberate: it keeps the hot path to a single cached lookup.
A .env file in your working directory is loaded automatically on import. If telemetry appears to be on when you expected it off, check .env before checking your shell — the file populates the variable before the gate is read.

Verifying the current state

ready can be False even when telemetry_on() is True — that means setup failed and telemetry silently disabled itself. Run with loguru at DEBUG level to see why.

Performance cost

Measured overhead per decorated call: Every one of those numbers is dwarfed by a single LLM round trip (200 ms – several seconds). Even the worst case is roughly 0.05% of a 200 ms call. Span export happens on a background thread via BatchSpanProcessor, so the network is never on your hot path. The dominant cost when enabled is stringifying inputs and outputs for the span. Payloads are truncated to 16,000 characters (SWARMS_OTEL_MAX_CHARS), and captured constructor configs to 65,536 (SWARMS_OTEL_MAX_CONFIG_CHARS).

What gets captured

Spans

Every span carries identity attributes: And run spans add:

Trace structure

Spans nest, including across the thread pools that concurrent swarms use:
One trace, one root, every agent attributable to the run that spawned it.
SequentialWorkflow delegates internally to AgentRearrange, so a sequential run shows an extra AgentRearrange.run span between the workflow and its agents. That is the real call path, not a duplicate.

Instrumented components

Every multi-agent harness and the Agent class itself:

Agents

Agent

Workflows

SequentialWorkflow, ConcurrentWorkflow, AgentRearrange, GraphWorkflow, BatchedGridWorkflow, RoundRobinSwarm

Orchestrators

SwarmRouter, HierarchicalSwarm, MultiAgentRouter, PlannerWorkerSwarm, MixtureOfAgents

Deliberation

MajorityVoting, CouncilAsAJudge, DebateWithJudge, GroupChat, LLMCouncil, HeavySwarm

Configuration reference

Instrumenting your own components

The same primitives are available for custom structures.

The decorator

trace_run opens the span, captures the named parameters, records the return value on success, and records any exception that propagates before re-raising it unchanged. You never need to touch the span yourself.

Inline spans

When you need to attach extra attributes mid-run:

Errors you swallow

trace_run and capture_run only see exceptions that propagate. For errors you catch and handle, record them explicitly:

Threads

OpenTelemetry’s active-span context does not cross thread boundaries. If you dispatch agents to a pool, use the drop-in executor so their spans nest under the run that spawned them:
A plain ThreadPoolExecutor still works — the agents just show up as disconnected root traces instead of children.

Capturing spans in tests

Point the tracer at an in-memory exporter instead of the network:
swarm_telemetry.cache_clear() is the important line — without it you get the singleton built under the previous gate value.

Privacy

Telemetry captures task text, agent outputs, and constructor configuration — including system prompts, which may contain proprietary instructions. If that matters for your deployment, leave SWARMS_TELEMETRY_ON unset. There is no partial mode: it is entirely on or entirely off.