Skip to main content
Atomic Agents is a lightweight, modular Python framework for building agentic AI applications from small, single-purpose components. Every agent is a typed function: a Pydantic input schema in, a Pydantic output schema out, with the LLM call handled by Instructor. Atomic Agents ships its own OpenTelemetry instrumentor. From version 2.15.0 it emits OpenTelemetry GenAI semantic-convention spans (invoke_agent, execute_tool, chat) and adds the OpenInference span kinds and attributes automatically when the phoenix extra is installed, so Phoenix shows AGENT, TOOL and LLM spans with no provider instrumentor required.

Install

The phoenix extra pulls in openinference-instrumentation and openinference-semantic-conventions next to opentelemetry-api. Atomic Agents emits one LLM span per Instructor attempt with the model, token usage, retry count and validation errors. If you prefer the provider instrumentor’s LLM spans instead (they include the full message lists), install it and turn ours off:
Run only one of the two, or every model call shows up twice.

Setup

Set your API keys as environment variables:
Register Phoenix with auto-instrumentation. The Atomic Agents instrumentor is discovered through the 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, config=TracingConfig(...)) from atomic_agents.observability. TracingConfig controls input and output hiding, the attribute size cap and whether LLM spans are emitted; an OpenInference TraceConfig is accepted as well.

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 spans carry gen_ai.agent.name (the AgentConfig.name, or the class when unset), gen_ai.request.model, gen_ai.provider.name, the input and output as JSON, token usage totals, the number of LLM attempts and atomic_agents.* attributes for 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 gen_ai.tool.name, gen_ai.tool.description, the input JSON schema and the tool’s input and output. LLM spans carry the request and response model, per-attempt usage (including cached and reasoning tokens) and a validation_error event when Instructor retries. 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; using_session also sets gen_ai.conversation.id. To redact agent, tool and LLM payloads, set ATOMIC_AGENTS_TRACE_HIDE_INPUTS=true and ATOMIC_AGENTS_TRACE_HIDE_OUTPUTS=true (OPENINFERENCE_HIDE_INPUTS and OPENINFERENCE_HIDE_OUTPUTS still work).

Resources