
Arize Instrumentation
- 2.2k installs
- 40 repo stars
- Updated July 27, 2026
- arize-ai/arize-skills
arize-instrumentation is an agent skill that Adds Arize AX tracing to an LLM application for the first time. Follows a two-phase agent-assisted flow to analyze the codebase then implement instrumentation a.
About
Adds Arize AX tracing to an LLM application for the first time. Follows a two-phase agent-assisted flow to analyze the codebase then implement instrumentation after user confirmation. Use when the user wants to instrument their app, add tracing from scratch, set up LLM observability, integrate OpenTelemetry or openinference, or get started with Arize tracing. --- name: arize-instrumentation description: Adds Arize AX tracing to an LLM application for the first time. Follows a two-phase agent-assisted flow to analyze the codebase then implement instrumentation after user confirmation. Use when the user wants to instrument their app, add tracing from scratch, set up LLM observability, integrate OpenTelemetry or openinference, or get started with Arize tracing. metadata: author: arize version: "1.0" compatibility: Python and TypeScript/JavaScript apps use openinference-instrumentation packages for auto-instrumentation. Go apps use arize-otel-go for setup plus per-provider instrumentors openinference-instrumentation-openai-go (official openai/openai-go SDK) and openinference-instrumentation-anthropic-sdk-go (anthropics/anthropic-sdk-go), or manual spans via openinference-semantic-conv.
- Arize Instrumentation Skill
- **Prefer inspection over mutation** - understand the codebase before changing it.
- **Do not change business logic** - tracing is purely additive.
- **Use auto-instrumentation where available** - add manual spans only for custom logic not covered by integrations.
- **Follow existing code style** and project conventions.
Arize Instrumentation by the numbers
- 2,215 all-time installs (skills.sh)
- +188 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #211 of 2,209 Security skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
arize-instrumentation capabilities & compatibility
- Capabilities
- arize instrumentation skill · **prefer inspection over mutation** — understand · **do not change business logic** — tracing is pu · **use auto instrumentation where available** — a · **follow existing code style** and project conve
- Use cases
- documentation
What arize-instrumentation says it does
--- name: arize-instrumentation description: Adds Arize AX tracing to an LLM application for the first time.
Follows a two-phase agent-assisted flow to analyze the codebase then implement instrumentation after user confirmation.
Use when the user wants to instrument their app, add tracing from scratch, set up LLM observability, integrate OpenTelemetry or openinference, or get started with Arize tracing.
metadata: author: arize version: "1.0" compatibility: Python and TypeScript/JavaScript apps use openinference-instrumentation packages for auto-instrumentation.
npx skills add https://github.com/arize-ai/arize-skills --skill arize-instrumentationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2.2k |
|---|---|
| repo stars | ★ 40 |
| Security audit | 2 / 3 scanners passed |
| Last updated | July 27, 2026 |
| Repository | arize-ai/arize-skills ↗ |
What problem does arize-instrumentation solve for developers using this skill?
Adds Arize AX tracing to an LLM application for the first time. Follows a two-phase agent-assisted flow to analyze the codebase then implement instrumentation after user confirmation. Use when the use
Who is it for?
Developers who need arize-instrumentation patterns described in the cached skill documentation.
Skip if: Skip when docs are empty or the task is outside the skill's documented scope.
When should I use this skill?
Adds Arize AX tracing to an LLM application for the first time. Follows a two-phase agent-assisted flow to analyze the codebase then implement instrumentation after user confirmation. Use when the use
What you get
Actionable workflows and conventions from SKILL.md for arize-instrumentation.
- configured ax profile
- restored trace pipeline
Files
Arize Instrumentation Skill
Use this skill when the user wants to add Arize AX tracing to their application. Follow the two-phase, agent-assisted flow from the Agent-Assisted Tracing Setup and the Arize AX Tracing — Agent Setup Prompt.
Quick start (for the user)
If the user asks you to "set up tracing" or "instrument my app with Arize", you can start with:
Follow the instructions from https://arize.com/docs/PROMPT.md and ask me questions as needed.
Then execute the two phases below.
Core principles
- Prefer inspection over mutation — understand the codebase before changing it.
- Do not change business logic — tracing is purely additive.
- Use auto-instrumentation where available — add manual spans only for custom logic not covered by integrations.
- Follow existing code style and project conventions.
- Keep output concise and production-focused — do not generate extra documentation or summary files.
- NEVER embed literal credential values in generated code — always reference environment variables (e.g.,
os.environ["ARIZE_API_KEY"],process.env.ARIZE_API_KEY). This includes API keys, space IDs, and any other secrets. The user sets these in their own environment; the agent must never output raw secret values.
Phase 0: Environment preflight
Before changing code:
1. Confirm the repo/service scope is clear. For monorepos, do not assume the whole repo should be instrumented. 2. Identify the local runtime surface you will need for verification:
- package manager and app start command
- whether the app is long-running, server-based, or a short-lived CLI/script
- whether
axwill be needed for post-change verification
3. Do NOT proactively check ax installation or version. If ax is needed for verification later, just run it when the time comes. If it fails, see references/ax-profiles.md. 4. Never silently replace a user-provided space ID, project name, or project ID. If the CLI, collector, and user input disagree, surface that mismatch as a concrete blocker.
When you must ask the user first
If monorepo scope, service entrypoint, or target app is still unclear after quick inspection — or you would otherwise open with a bare list of questions — use this opening pattern:
1. Acknowledge the skill, e.g.: I found the arize-instrumentation skill in this repo (you may add skills/arize-instrumentation/SKILL.md if helpful). 2. Then a clear pause line, e.g.: A few clarifying questions before I invoke it: 3. Ask minimal numbered or short bullet questions — only what blocks Phase 1 or Phase 2.
Phase 1: Analysis (read-only)
Do not write any code or create any files during this phase.
Steps
1. Check dependency manifests to detect stack:
- Python:
pyproject.toml,requirements.txt,setup.py,Pipfile - TypeScript/JavaScript:
package.json - Java:
pom.xml,build.gradle,build.gradle.kts - Go:
go.mod
2. Scan import statements in source files to confirm what is actually used.
3. Check for existing tracing/OTel — look for TracerProvider, register(), opentelemetry imports, ARIZE_*, OTEL_*, OTLP_* env vars, or other observability config (Datadog, Honeycomb, etc.).
4. Identify scope — for monorepos or multi-service projects, ask which service(s) to instrument.
What to identify
| Item | Examples |
|---|---|
| Language | Python, TypeScript/JavaScript, Java, Go |
| Package manager | pip/poetry/uv, npm/pnpm/yarn, maven/gradle, go modules |
| LLM providers | OpenAI, Anthropic, LiteLLM, Bedrock, etc. |
| Frameworks | LangChain, LangGraph, LlamaIndex, Vercel AI SDK, Mastra, etc. |
| Existing tracing | Any OTel or vendor setup |
| Tool/function use | LLM tool use, function calling, or custom tools the app executes (e.g. in an agent loop) |
Key rule: When a framework is detected alongside an LLM provider, inspect the framework-specific tracing docs first and prefer the framework-native integration path when it already captures the model and tool spans you need. Add separate provider instrumentation only when the framework docs require it or when the framework-native integration leaves obvious gaps. If the app runs tools and the framework integration does not emit tool spans, add manual TOOL spans so each invocation appears with input/output (see references/manual-spans.md).
Phase 1 output
Return a concise summary:
- Detected language, package manager, providers, frameworks
- Proposed integration list (from the routing table in the docs)
- Any existing OTel/tracing that needs consideration
- If monorepo: which service(s) you propose to instrument
- If the app uses LLM tool use / function calling: note that you will add manual CHAIN + TOOL spans so each tool call appears in the trace with input/output (avoids sparse traces).
If the user explicitly asked you to instrument the app now, and the target service is already clear, present the Phase 1 summary briefly and continue directly to Phase 2. If scope is ambiguous, or the user asked for analysis first, stop and wait for confirmation.
Integration routing and docs
Use the Agent Setup Prompt routing table to map detected signals to integration docs and fetch the matched pages for exact installation steps and code snippets. Use llms.txt as a fallback for doc discovery.
See references/integration-routing.md for the full list of supported integrations by language and platform.
Phase 2: Implementation
Proceed only after the user confirms the Phase 1 analysis.
Steps
1. Fetch integration docs — Read the matched doc URLs and follow their installation and instrumentation steps. 2. Install packages using the detected package manager before writing code:
- Python:
pip install arize-otelplusopeninference-instrumentation-{name}(hyphens in package name; underscores in import, e.g.openinference.instrumentation.llama_index). - TypeScript/JavaScript:
@opentelemetry/sdk-trace-nodeplus the relevant@arizeai/openinference-*package. - Java: OpenTelemetry SDK plus
openinference-instrumentation-*in pom.xml or build.gradle. - Go: Use `arize-otel-go` for tracer setup, plus a per-provider instrumentor when one exists. Install:
go get github.com/Arize-ai/arize-otel-go
go get github.com/Arize-ai/openinference/go/openinference-semantic-conventions
go get github.com/Arize-ai/openinference/go/openinference-instrumentation
# Plus exactly one of these, matched to the detected client:
go get github.com/Arize-ai/openinference/go/openinference-instrumentation-openai-go # official openai/openai-go SDK
go get github.com/Arize-ai/openinference/go/openinference-instrumentation-anthropic-sdk-go # anthropics/anthropic-sdk-go v1.43+Wire the exporter with one call: arizeotel.Register(ctx, arizeotel.Options{ProjectName: "my-app"}) — defaults to otlp.arize.com (US), use arizeotel.EndpointArizeEurope for EU. It reads ARIZE_SPACE_ID / ARIZE_API_KEY / ARIZE_PROJECT_NAME / ARIZE_COLLECTOR_ENDPOINT from env when the matching Options fields are unset. Wire the OpenAI instrumentor by passing option.WithMiddleware(openaiotel.Middleware(otel.Tracer("my-app"))) to openai.NewClient(...) (alongside option.WithAPIKey(...)). Wire the Anthropic instrumentor by passing option.WithMiddleware(anthropicotel.Middleware(otel.Tracer("my-app"))) to anthropic.NewClient(...). Both instrumentors expose WithTraceConfig(instrumentation.TraceConfig{...}) for in-code overrides of the OPENINFERENCE_HIDE_* env-driven masking config. Module floor is Go 1.25 (the openinference Go modules require it; arize-otel-go itself is Go 1.23+). 3. Credentials — User needs an Arize API Key and Space ID. Check existing ax profiles for ARIZE_API_KEY and ARIZE_SPACE — never read .env files:
- Run
ax profiles showto check for an existing profile. Runax profiles validateto verify an existing profile's credentials are still valid. - If no profile exists, guide the user to run
ax profiles createwhich provides an interactive wizard that walks through API key and space setup. See CLI profiles docs for details. - OAuth alternative (v0.18.0+): Users can authenticate via browser-based OAuth PKCE instead of API keys by running
ax auth login. Inform users of this option if they prefer not to manage API keys — do not runax auth loginyourself as it opens a browser. - If the user needs to find their API key manually, direct them to https://app.arize.com and to navigate to the settings page (do not use organization-specific URLs with placeholder IDs — they won't resolve for new users).
- If credentials are not set, instruct the user to set them as environment variables — never embed raw values in generated code. All generated instrumentation code must reference
os.environ["ARIZE_API_KEY"]/os.environ["ARIZE_SPACE"](Python),process.env.ARIZE_API_KEY/process.env.ARIZE_SPACE(TypeScript/JavaScript), oros.Getenv("ARIZE_API_KEY")/os.Getenv("ARIZE_SPACE_ID")(Go —arize-otel-goreadsARIZE_SPACE_ID, notARIZE_SPACE). With the recommendedarizeotel.Register(ctx, arizeotel.Options{...})flow, generated Go code does not need to callos.Getenvat all —Registerreads both env vars when the matchingOptionsfields are unset. - See references/ax-profiles.md for full profile setup and troubleshooting.
4. Centralized instrumentation — Create a single module (e.g. instrumentation.py, instrumentation.ts, instrumentation.go) and initialize tracing before any LLM client is created. 5. Existing OTel — If there is already a TracerProvider, add Arize as an additional exporter (e.g. BatchSpanProcessor with Arize OTLP). Do not replace existing setup unless the user asks.
Implementation rules
- Use auto-instrumentation first; manual spans only when needed.
- Prefer the repo's native integration surface before adding generic OpenTelemetry plumbing. If the framework ships an exporter or observability package, use that first unless there is a documented gap.
- Fail gracefully if env vars are missing (warn, do not crash).
- Import order: register tracer → attach instrumentors → then create LLM clients.
- Project name attribute (required): Arize rejects spans with HTTP 500 if the project name is missing —
service.namealone is not accepted. Set it as a resource attribute on the TracerProvider (recommended — one place, applies to all spans): - Python:
register(project_name="my-app")handles it automatically (sets"openinference.project.name"on the resource). For routing spans to different projects, useset_routing_context(space_id=..., project_name=...)fromarize.otel. - TypeScript: Arize accepts both
"model_id"(shown in the official TS quickstart) and"openinference.project.name"viaSEMRESATTRS_PROJECT_NAMEfrom@arizeai/openinference-semantic-conventions(shown in the manual instrumentation docs) — both work. - Go:
arizeotel.Register(ctx, arizeotel.Options{ProjectName: "my-app"})handles this automatically (setsopeninference.project.nameandservice.nameon the resource). If you're wiringsdktrace.NewTracerProviderdirectly (multi-exporter, on-prem collector), passattribute.String("openinference.project.name", "my-app")toresource.New(...)manually. - CLI/script apps — flush before exit:
provider.shutdown()(TS) /provider.force_flush()thenprovider.shutdown()(Python) /tp.Shutdown(ctx)(Go) must be called before the process exits, otherwise async OTLP exports are dropped and no traces appear. - When the app has tool/function execution: add manual CHAIN + TOOL spans (see references/manual-spans.md) so the trace tree shows each tool call and its result — otherwise traces will look sparse (only LLM API spans, no tool input/output).
Verification
Treat instrumentation as complete only when all of the following are true:
1. The app still builds or typechecks after the tracing change. 2. The app starts successfully with the new tracing configuration. 3. You trigger at least one real request or run that should produce spans. 4. You either verify the resulting trace in Arize, or you provide a precise blocker that distinguishes app-side success from Arize-side failure.
After implementation:
1. Run the application and trigger at least one LLM call. 2. Use the `arize-trace` skill to confirm traces arrived. If empty, retry shortly. Verify spans have expected openinference.span.kind, input.value/output.value, and parent-child relationships. 3. If no traces: verify ARIZE_SPACE and ARIZE_API_KEY, ensure tracer is initialized before instrumentors and clients, check connectivity to otlp.arize.com:443, and inspect app/runtime exporter logs so you can tell whether spans are being emitted locally but rejected remotely. For debug set GRPC_VERBOSITY=debug or pass log_to_console=True to register(). Common gotchas: (a) missing project name resource attribute causes HTTP 500 rejections — service.name alone is not enough; Python: pass project_name to register(); TypeScript: set "model_id" or SEMRESATTRS_PROJECT_NAME on the resource; Go: add attribute.String("openinference.project.name", "my-app") to resource.New(...); (b) CLI/script processes exit before OTLP exports flush — call provider.force_flush() then provider.shutdown() (Python/TS) or tp.Shutdown(ctx) (Go) before exit; (c) CLI-visible spaces/projects can disagree with a collector-targeted space ID — report the mismatch instead of silently rewriting credentials. 4. If the app uses tools: confirm CHAIN and TOOL spans appear with input.value / output.value so tool calls and results are visible.
When verification is blocked by CLI or account issues, end with a concrete status:
- app instrumentation status
- latest local trace ID or run ID
- whether exporter logs show local span emission
- whether the failure is credential, space/project resolution, network, or collector rejection
Reference links
| Resource | URL |
|---|---|
| Agent-Assisted Tracing Setup | https://arize.com/docs/ax/alyx/tracing-assistant |
| Agent Setup Prompt (full routing + phases) | https://arize.com/docs/PROMPT.md |
| Arize AX Docs | https://arize.com/docs/ax |
| Full integration list | https://arize.com/docs/ax/integrations |
| Doc index (llms.txt) | https://arize.com/docs/llms.txt |
IDE Integration (MCP)
If the user asks about IDE-based instrumentation guidance or MCP setup, see references/tracing-assistant-mcp.md.
Save Credentials for Future Use
See references/ax-profiles.md § Save Credentials for Future Use.
ax Profile Setup
Consult this when authentication fails (401, missing profile, missing API key). Do NOT run these checks proactively.
Use this when there is no profile, or a profile has incorrect settings (wrong API key, wrong region, etc.).
1. Inspect the current state
ax profiles showLook at the output to understand what's configured:
API Key: (not set)or missing → key needs to be created/updated- No profile output or "No profiles found" → no profile exists yet
- Connected but getting
401 Unauthorized→ key is wrong or expired - Connected but wrong endpoint/region → region needs to be updated
2. Fix a misconfigured profile
If a profile exists but one or more settings are wrong, patch only what's broken.
Never pass a raw API key value as a flag. Always reference it via the ARIZE_API_KEY environment variable. If the variable is not already set in the shell, instruct the user to set it first, then run the command:
# If ARIZE_API_KEY is already exported in the shell:
ax profiles update --api-key $ARIZE_API_KEY
# Fix the region (no secret involved — safe to run directly)
ax profiles update --region us-east-1b
# Fix both at once
ax profiles update --api-key $ARIZE_API_KEY --region us-east-1bupdate only changes the fields you specify — all other settings are preserved. If no profile name is given, the active profile is updated.
3. Create a new profile
If no profile exists, or if the existing profile needs to point to a completely different setup (different org, different region):
Always reference the key via `$ARIZE_API_KEY`, never inline a raw value.
# Requires ARIZE_API_KEY to be exported in the shell first
ax profiles create --api-key $ARIZE_API_KEY
# Create with a region
ax profiles create --api-key $ARIZE_API_KEY --region us-east-1b
# Create a named profile
ax profiles create work --api-key $ARIZE_API_KEY --region us-east-1bTo use a named profile with any ax command, add -p NAME:
ax spans export PROJECT -p work4. Getting the API key
Never ask the user to paste their API key into the chat. Never log, echo, or display an API key value.
If ARIZE_API_KEY is not already set, instruct the user to export it in their shell:
export ARIZE_API_KEY="..." # user pastes their key here in their own terminalThey can find their key at https://app.arize.com by navigating to the settings page. Recommend they create a scoped service key (not a personal user key) — service keys are not tied to an individual account and are safer for programmatic use. Keys are space-scoped — make sure they copy the key for the correct space.
Once the user confirms the variable is set, proceed with ax profiles create --api-key $ARIZE_API_KEY or ax profiles update --api-key $ARIZE_API_KEY as described above.
5. Verify
After any create or update:
ax profiles showConfirm the API key and region are correct, then retry the original command.
Space
There is no profile flag for space. Save it as an environment variable — accepts a space name (e.g., my-workspace) or a base64 space ID (e.g., U3BhY2U6...). Find yours with ax spaces list -o json.
macOS/Linux — add to ~/.zshrc or ~/.bashrc:
export ARIZE_SPACE="my-workspace" # name or base64 IDThen source ~/.zshrc (or restart terminal).
Windows (PowerShell):
[System.Environment]::SetEnvironmentVariable('ARIZE_SPACE', 'my-workspace', 'User')Restart terminal for it to take effect.
Save Credentials for Future Use
At the end of the session, if the user manually provided any credentials during this conversation and those values were NOT already loaded from a saved profile or environment variable, offer to save them.
Skip this entirely if:
- The API key was already loaded from an existing profile or
ARIZE_API_KEYenv var - The space was already set via
ARIZE_SPACEenv var - The user only used base64 project IDs (no space was needed)
How to offer: Use AskQuestion: "Would you like to save your Arize credentials so you don't have to enter them next time?" with options "Yes, save them" / "No thanks".
If the user says yes:
1. API key — Run ax profiles show to check the current state. Then run ax profiles create --api-key $ARIZE_API_KEY or ax profiles update --api-key $ARIZE_API_KEY (the key must already be exported as an env var — never pass a raw key value).
2. Space — See the Space section above to persist it as an environment variable.
Integration Routing
Consult this during Phase 1 to map detected signals (language, LLM provider, framework) to the correct integration docs. Always fetch the matched doc pages for exact installation steps and code snippets.
Supported integrations
- LLM providers: OpenAI, Anthropic, LiteLLM, Google Gen AI, Bedrock, Ollama, Groq, MistralAI, OpenRouter, VertexAI.
- Python frameworks: LangChain, LangGraph, LlamaIndex, CrewAI, DSPy, AutoGen, Semantic Kernel, Pydantic AI, Haystack, Guardrails AI, Hugging Face Smolagents, Instructor, Agno, Google ADK, MCP, Portkey, Together AI, BeeAI, AWS Bedrock Agents.
- TypeScript/JavaScript: LangChain JS, Mastra, Vercel AI SDK, BeeAI JS.
- Java: LangChain4j, Spring AI, Arconia.
- Go: Use `arize-otel-go`'s
Register(ctx, Options)for setup, then either (a) a per-provider auto-instrumentor — `openinference-instrumentation-openai-go` for the official `openai/openai-go` SDK, `openinference-instrumentation-anthropic-sdk-go` for `anthropics/anthropic-sdk-go` — or (b) manual spans built with `openinference-semantic-conventions` constants for clients that don't have an instrumentor yet. The `openinference-instrumentation` package also exportsWithSession/WithUser/WithMetadata/WithTags/WithSuppressioncontext helpers that the provider instrumentors honor automatically. - Platforms (UI-based): LangFlow, Flowise, Dify, Prompt flow.
- Fallback: Manual instrumentation, All integrations.
Fetch the matched doc pages from the full routing table in PROMPT.md for exact installation and code snippets. Use llms.txt as a fallback for doc discovery if needed.
Note:arize.com/docs/PROMPT.mdandarize.com/docs/llms.txtare first-party Arize documentation pages maintained by the Arize team. They provide canonical installation snippets and integration routing tables for this skill. These are trusted, same-organization URLs — not third-party content.
Manual Spans for Tool Use and Agent Loops
Consult this when the app uses LLM tool/function calling and you need to add CHAIN + TOOL spans so tool calls and results appear in the trace.
Why auto-instrumentors don't capture tool execution
*Provider instrumentors (Anthropic, OpenAI, etc.) only wrap the LLM client — the code that sends HTTP requests and receives responses.* They see:
- One span per API call: request (messages, system prompt, tools) and response (text, tool_use blocks, etc.).
They cannot see what happens inside your application after the response:
- Tool execution — Your code parses the response, calls
run_tool("check_loan_eligibility", {...}), and gets a result. That runs in your process; the instrumentor has no hook into yourrun_tool()or the actual tool output. The next API call (sending the tool result back) is just anothermessages.createspan — the instrumentor doesn't know that the message content is a tool result or what the tool returned. - Agent/chain boundary — The idea of "one user turn → multiple LLM calls + tool calls" is an application-level concept. The instrumentor only sees separate API calls; it doesn't know they belong to the same logical "run_agent" run.
So TOOL and CHAIN spans have to be added manually (or by a framework instrumentor like LangChain/LangGraph that knows about tools and chains). Once you add them, they appear in the same trace as the LLM spans because they use the same TracerProvider.
Adding manual spans
To avoid sparse traces where tool inputs/outputs are missing:
1. Detect agent/tool patterns: a loop that calls the LLM, then runs one or more tools (by name + arguments), then calls the LLM again with tool results. 2. Add manual spans using the same TracerProvider (e.g. opentelemetry.trace.get_tracer(...) after register()):
- CHAIN span — Wrap the full agent run (e.g.
run_agent): setopeninference.span.kind="CHAIN",input.value= user message,output.value= final reply. - TOOL span — Wrap each tool invocation: set
openinference.span.kind="TOOL",input.value= JSON of arguments,output.value= JSON of result. Use the tool name as the span name (e.g.check_loan_eligibility).
OpenInference attributes
Core attributes (all span kinds):
| Attribute | Use |
|---|---|
openinference.span.kind | Pick the right value: "LLM" for raw provider API calls (OpenAI, Anthropic, etc.); "CHAIN" for orchestration / agent-loop boundaries; "TOOL" for tool/function execution; "RETRIEVER" for vector-store / search lookups; "EMBEDDING" for embedding API calls; "AGENT" for an autonomous sub-agent run nested inside a larger chain; "RERANKER" for rerank API calls; "GUARDRAIL" for guardrail/policy checks; "EVALUATOR" for online eval calls. |
input.value | string (e.g. user message or JSON of tool args) |
output.value | string (e.g. final reply or JSON of tool result) |
LLM-span attributes (set in addition to the three above for actual LLM calls):
| Attribute | Use |
|---|---|
llm.model_name | model identifier (e.g. "gpt-4o-mini") |
llm.provider / llm.system | provider name (e.g. "openai", "anthropic") |
llm.input_messages.{i}.message.role | "system" / "user" / "assistant" / "tool" for the i-th input message |
llm.input_messages.{i}.message.content | text content of the i-th input message |
llm.output_messages.{i}.message.role | role of the i-th output message |
llm.output_messages.{i}.message.content | text content of the i-th output message |
llm.token_count.prompt | int — prompt/input tokens |
llm.token_count.completion | int — completion/output tokens |
llm.token_count.total | int — total tokens |
All three languages expose these names as constants via their respective openinference-semantic-conventions packages — from openinference.semconv.trace import SpanAttributes in Python, @arizeai/openinference-semantic-conventions in TypeScript, and semconv "github.com/Arize-ai/openinference/go/openinference-semantic-conventions" in Go (e.g. semconv.LLMModelName, semconv.LLMProvider, semconv.LLMTokenCountPrompt).
Python pattern
Get the global tracer (same provider as Arize), then use context managers so tool spans are children of the CHAIN span:
from opentelemetry.trace import get_tracer
tracer = get_tracer("my-app", "1.0.0")
# In your agent entrypoint:
with tracer.start_as_current_span("run_agent") as chain_span:
chain_span.set_attribute("openinference.span.kind", "CHAIN")
chain_span.set_attribute("input.value", user_message)
# ... LLM call ...
for tool_use in tool_uses:
with tracer.start_as_current_span(tool_use["name"]) as tool_span:
tool_span.set_attribute("openinference.span.kind", "TOOL")
tool_span.set_attribute("input.value", json.dumps(tool_use["input"]))
result = run_tool(tool_use["name"], tool_use["input"])
tool_span.set_attribute("output.value", result)
# ... append tool result to messages, call LLM again ...
chain_span.set_attribute("output.value", final_reply)Go pattern
Get a tracer from the global TracerProvider (registered via otel.SetTracerProvider), then nest spans with tracer.Start so tool spans become children of the CHAIN span.
Critical for short-lived processes: never calllog.Fatalf/os.Exitafter a span has started — they skip the deferredtp.Shutdown(ctx)and the in-flight CHAIN/LLM spans never flush. Uselog.Printf+returnfrommaininstead, and keeptp.Shutdown(ctx)deferred at the top ofmain.
import (
"context"
"encoding/json"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
semconv "github.com/Arize-ai/openinference/go/openinference-semantic-conventions"
)
var tracer = otel.Tracer("my-app")
func runAgent(ctx context.Context, userMessage string) string {
ctx, chainSpan := tracer.Start(ctx, "run_agent")
defer chainSpan.End()
chainSpan.SetAttributes(
attribute.String(semconv.OpenInferenceSpanKind, semconv.SpanKindChain),
attribute.String(semconv.InputValue, userMessage),
)
// ... LLM call (auto-instrumented by openaiotel/anthropicotel if used) ...
for _, toolUse := range toolUses {
_, toolSpan := tracer.Start(ctx, toolUse.Name)
argsJSON, err := json.Marshal(toolUse.Input)
if err != nil {
toolSpan.RecordError(err)
toolSpan.SetStatus(codes.Error, err.Error())
}
toolSpan.SetAttributes(
attribute.String(semconv.OpenInferenceSpanKind, semconv.SpanKindTool),
attribute.String(semconv.InputValue, string(argsJSON)),
)
result := runTool(toolUse.Name, toolUse.Input)
toolSpan.SetAttributes(attribute.String(semconv.OutputValue, result))
toolSpan.End()
// ... append tool result to messages, call LLM again ...
}
chainSpan.SetAttributes(attribute.String(semconv.OutputValue, finalReply))
return finalReply
}Session, user, metadata, tags, suppression (Go)
When the customer asks for session-aware tracing or wants evaluator calls excluded, use the openinference-instrumentation package's context helpers — the per-provider instrumentors (openai, anthropic) apply them automatically to every LLM span:
import instrumentation "github.com/Arize-ai/openinference/go/openinference-instrumentation"
ctx = instrumentation.WithSession(ctx, sessionID)
ctx = instrumentation.WithUser(ctx, userID)
ctx = instrumentation.WithMetadata(ctx, metadataJSON) // caller JSON-encodes the map
ctx = instrumentation.WithTags(ctx, "prod", "canary")
// openai/openai-go:
resp, _ := client.Chat.Completions.New(ctx, params) // span carries all four
// anthropics/anthropic-sdk-go:
// resp, _ := client.Messages.New(ctx, params)
// Off-trace evaluator calls:
suppressedCtx := instrumentation.WithSuppression(ctx)
_, _ = evalClient.Chat.Completions.New(suppressedCtx, params) // no span emittedFor manual spans you author yourself, call instrumentation.ApplyContextAttributes(ctx, span) right after tracer.Start to copy the same context attributes onto the span. (These values ride context.Context via unexported keys — not OTel baggage — so they do not leak out as baggage HTTP headers on downstream calls.)
See Manual instrumentation for more span kinds and attributes.
Tracing Assistant MCP
Consult this when the user asks about IDE-based instrumentation guidance or wants to set up MCP integrations for Arize.
For deeper instrumentation guidance inside the IDE, the user can enable:
- Arize AX Tracing Assistant MCP — instrumentation guides, framework examples, and support. In Cursor: Settings → MCP → Add and use:
"arize-tracing-assistant": {
"command": "uvx",
"args": ["arize-tracing-assistant@latest"]
}- Arize AX Docs MCP — searchable docs. In Cursor:
"arize-ax-docs": {
"url": "https://arize.com/docs/mcp"
}Then the user can ask things like: "Instrument this app using Arize AX", "Can you use manual instrumentation so I have more control over my traces?", "How can I redact sensitive information from my spans?"
See the full setup at Agent-Assisted Tracing Setup.
Related skills
How it compares
Pick arize-instrumentation over general OpenTelemetry skills when the failure is specific to Arize ax CLI profiles and 401 tracing auth.
FAQ
What does arize-instrumentation do?
Adds Arize AX tracing to an LLM application for the first time. Follows a two-phase agent-assisted flow to analyze the codebase then implement instrumentation after user confirmation. Use when the user wants to instrumen
When should I use arize-instrumentation?
Adds Arize AX tracing to an LLM application for the first time. Follows a two-phase agent-assisted flow to analyze the codebase then implement instrumentation after user confirmation. Use when the user wants to instrumen
Is arize-instrumentation safe to install?
Review the Security Audits panel on this page before installing in production.