Jido Composer integrates with OpenTelemetry for distributed tracing. All spans are optional — when OpenTelemetry is not configured, tracing is a no-op with zero overhead.

Setup

Add the optional dependencies:

def deps do
  [
    {:jido_composer, "~> 0.1.0"},
    {:opentelemetry, "~> 1.3"},
    {:opentelemetry_api, "~> 1.2"},
    {:opentelemetry_exporter, "~> 1.6"},
    # If using AgentObs for visualization:
    {:agent_obs, "~> 0.1"}
  ]
end

Configure the tracer in your application config:

config :jido, :observability,
  tracer: AgentObs.JidoTracer

The tracer module must implement the Jido.Observe.Tracer behaviour. AgentObs.JidoTracer maps Jido's telemetry events to OpenInference-compatible spans.

Span Hierarchy

Orchestrator Spans

AGENT span (full orchestrator lifecycle)
 ITERATION span (ReAct iteration 1)
    LLM span (model call)
    TOOL span (tool call A)
    TOOL span (tool call B)
 ITERATION span (iteration 2)
    LLM span
    TOOL span
SpanTelemetry PrefixOpenedClosed
Agent[:jido, :composer, :agent]orchestrator_startFinal answer or error
Iteration[:jido, :composer, :iteration]Before each LLM callWhen all tool results return or final answer
LLM[:jido, :composer, :llm]Before LLM instructionWhen LLM result arrives
Tool[:jido, :composer, :tool]When tool calls dispatchedWhen tool result arrives

Workflow Spans

AGENT span (full workflow lifecycle)
 TOOL span (node: extract)
 TOOL span (node: transform)
 TOOL span (node: load)

Workflow spans are simpler — one agent span containing one tool span per node execution.

Nested Agent Spans

When an orchestrator calls a workflow as a tool (or vice versa), the child's AGENT span is parented under the parent's TOOL span:

Parent AGENT span
 TOOL span (child agent)
    Child AGENT span         parented here
        TOOL span (step 1)
        TOOL span (step 2)

Context propagation works across process boundaries via OtelCtx.with_parent_context/2. The parent captures its OTel context when dispatching a tool call, threads it through the SpawnAgent directive, and the child attaches it before starting execution.

Span Measurements

Agent Span

FieldDescription
resultFinal output
status:completed, :error, :success, :failure
iterationsTotal ReAct iterations (orchestrator only)
tokens%{prompt, completion, total} (orchestrator only)
errorError description (when failed)

LLM Span

FieldDescription
tokens%{prompt, completion, total} from this call
finish_reason:stop, :length, :tool_calls, etc.
output_messagesNormalized assistant messages

Tool Span

FieldDescription
tool_nameName of the dispatched tool or node
resultTool output data
status:ok or :error
errorError detail (when failed)

Checkpoint Behavior

When a flow is checkpointed, the Obs struct is reset to Obs.new(). Spans are not resumed after thaw — a new agent span starts on resume. This ensures span state is always serialization-safe.

Tracer Mapping

AgentObs.JidoTracer maps Jido telemetry prefixes to OpenInference semantic types:

Jido PrefixAgentObs TypeOpenInference Semantic
[:jido, :composer, :agent]:agentAgent span
[:jido, :composer, :llm]:llmLLM span
[:jido, :composer, :tool]:toolTool span
[:jido, :composer, :iteration]:chainChain span

Interactive Demo

See livebooks/06_observability.livemd for a runnable example that traces orchestrator and workflow execution with visualization via AgentObs Phoenix at localhost:6006.