AGENT span for every AtomicAgent run and a TOOL span for every BaseTool run, including tools generated from MCP servers. LLM spans come from the provider instrumentor you already use and nest under the agent span.
Install
openinference-instrumentation-openai, openinference-instrumentation-anthropic, openinference-instrumentation-litellm, …). Installing both a provider instrumentor and openinference-instrumentation-instructor produces two layers of LLM spans.
Setup
Set your API keys as environment variables:openinference_instrumentor entry point, so no extra code is needed:
To activate the instrumentor by hand (for example with your own
TracerProvider), use AtomicAgentsInstrumentor().instrument(tracer_provider=tracer_provider) from atomic_agents.observability. It accepts an OpenInference TraceConfig for masking inputs and outputs.Run Atomic Agents
Atomic Agents has no built-in tool-calling loop: your code calls an agent, then a tool, then another agent. Each call is a root span on its own, so wrap a unit of work in a parent span to see one trace per turn:Observe
The trace in Phoenix looks like this:agent.name (Class[InputSchema, OutputSchema]), the input and output schemas as JSON, and atomic_agents.* attributes for the model, the Instructor mode, the schema names, the history size entering the turn, the registered context providers and a hash of the static system prompt sections. Tool spans carry tool.name, tool.description, tool.parameters (the input JSON schema) and the tool’s input and output. Streaming runs (run_stream, run_async_stream) record the final response, or the last partial plus atomic_agents.stream.closed_early when the consumer stops early.
Wrap calls in using_session, using_user or using_metadata from openinference.instrumentation to group spans by conversation or user. To redact agent and tool payloads, set OPENINFERENCE_HIDE_INPUTS=true and OPENINFERENCE_HIDE_OUTPUTS=true.

