grafi package. It composes assistants from workflows, nodes, tools, and topics, and instruments each of those layers with OpenTelemetry.
Graphite reads its tracer from the ExecutionServices bundle you hand to GrafiRuntime, so pointing it at Arize AX is a matter of giving it a tracer from an Arize AX tracer provider. The framework’s own spans then nest assistant → workflow → node → tool, and the OpenInference OpenAI instrumentor adds the LLM span underneath with prompts, token counts, and cost.
Do not use Graphite’s own
setup_tracing() helper for Arize AX. It builds a plaintext gRPC exporter (insecure=True) with no request headers, so exports to Arize AX fail with StatusCode.UNAVAILABLE ... Connection reset by peer, and the resource it builds carries service.name instead of the openinference.project.name that Arize AX reads to assign a project. Build the provider with arize.otel.register instead, as below.Prerequisites
- Python 3.11+ (required by
grafi) - An Arize AX account (sign up)
- Your Arize AX Space ID and API Key
- An
OPENAI_API_KEYfrom the OpenAI Platform
Launch Arize AX
- Sign in to your Arize AX account.
- From Space Settings, copy your Space ID and API Key. You will set them as
ARIZE_SPACE_IDandARIZE_API_KEYbelow.
Install
grafi already depends on openinference-instrumentation-openai and the OpenTelemetry SDK, so only the Arize AX exporter is extra:
Configure credentials
Setup tracing
register returns the tracer provider. Instrument OpenAI with it for the LLM spans, then hand Graphite a tracer taken from it.
Graphite names its span attributes after its own metadata model, so the span kind arrives as oi_span_type, the payloads as input and output, and the conversation as conversation_id. Arize AX reads the OpenInference names, so without a rename Graphite’s spans show with no span kind and no session. Graphite calls set_attribute on whatever tracer you give it, so wrapping the tracer is enough — the wrapper hands back a span proxy that renames keys on the way in, and changes nothing else:
The rename passes Graphite’s own values through rather than second-guessing them, so each layer is labeled the way Graphite labels it — the workflow as an agent span, the node as a chain span, its OpenAI tool as an LLM span. Drop the wrapper and hand
tracer_provider.get_tracer("grafi") straight to Graphite if you would rather see its raw attribute names.endpoint=Endpoint.ARIZE_EUROPE to register (import Endpoint from arize.otel).
Run Graphite
Pass the tracer inExecutionServices. GrafiRuntime.invoke binds those services for the duration of the invocation, so every assistant, workflow, node, and tool span lands in the same trace:
Expected output
Verify in Arize AX
- Open your Arize AX space and select project
graphite-tracing-example. - Open the newest trace. Graphite’s layers nest, with the OpenInference LLM span at the leaf:
Check from the skill, CLI, or SDK
Confirm spans are actually reaching your Arize AX project. Use whichever fits your workflow — the skill and CLI work for any framework; the SDK check is shown for each language.- Arize skill (agent)
- AX CLI
- SDK
Install the Arize Skills plugin and let your coding agent check for you:Then prompt your agent:
Use the arize-trace skill to export and analyze recent traces from my project. Confirm spans are arriving, and summarize any errors or latency issues.
What Arize AX captures
- One span per Graphite layer — assistant, workflow, node, and tool — carrying its
name,type,latency_ms, and the invocation’sconversation_id,invoke_id, andassistant_request_id - A fully attributed LLM span from the OpenInference OpenAI instrumentor: prompts and completions,
llm.model_name, token counts, and cost - The assistant’s input and output payloads, size-bounded by Graphite
- The invocation’s
conversation_idas the session, so a multi-turn conversation groups in the Sessions view
The span kinds,
input.value / output.value, and the session come from the rename in Setup tracing. Without it Graphite’s own spans arrive under its own attribute names, so they show with no span kind and no session grouping. A rename in Graphite itself would make the wrapper unnecessary.Troubleshooting
Invalid type dict for attribute 'kwargs' valueon startup. Graphite copies its metadata model onto the span and one field is a dictionary, which OpenTelemetry rejects. The wrapper in Setup tracing drops that field, so the warning means the wrapper is not in the path — check thatExecutionServicesis given the wrappedtracer.StatusCode.UNAVAILABLEorConnection reset by peerwhen exporting. Something is exporting plaintext gRPC to Arize AX — usually Graphite’ssetup_tracing(). Build the provider witharize.otel.registeras shown in Setup tracing.- Traces land in a project you did not name. Only
registersetsopeninference.project.name. If a Graphite helper created the provider instead, the resource carriesservice.nameand Arize AX cannot map it to your project. RuntimeError: No ExecutionServices bound for the current invocation.The assistant was invoked directly instead of throughruntime.invoke(...). Either invoke through the runtime, or wrap the call ingrafi.runtime.bind_services(...).- Graphite’s spans show with no span kind.
ExecutionServiceswas given the raw tracer rather than theOpenInferenceTracerwrapper from Setup tracing. - Spans stop at the assistant with no LLM child.
instrumentationmust be imported before the assistant is constructed, soOpenAIInstrumentoris in place when the OpenAI client is created.