OpenTelemetry
Already instrumented? Point your exporter at AgentPing and you are done. AgentPing accepts standard OTLP/HTTP trace exports, protobuf or JSON, and maps them onto runs and steps. No new SDK, no code changes.
The endpoint
POST https://eu.ingest.agentping.io/v1/traces
Use the host matching your data residency (eu or us). Authenticate
with your team API key (apk_...) as a Bearer token; exporters that
cannot set Authorization can send X-AgentPing-Key instead. Per-agent
ping_ tokens do not work here; OTel traffic can create agents, so it
needs the team key.
Generic exporter setup
Any OpenTelemetry SDK works with two environment variables:
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="https://eu.ingest.agentping.io/v1/traces"
export OTEL_EXPORTER_OTLP_TRACES_HEADERS="authorization=Bearer apk_eu_..."
How traces map to runs
| OpenTelemetry | AgentPing |
|---|---|
| Trace | Run (one run per trace; re-exports are deduplicated) |
| Root span | The run record; its name becomes the run's goal |
| Span with model/provider attributes | LLM call step, with tokens and server-side cost |
| Span with a tool name | Tool call step |
| Any other span | Step |
service.name |
The agent (created automatically on first sight) |
LLM calls are recognised across emitter conventions, not just the
canonical gen_ai.* set. AgentPing reads the model from gen_ai.request.model,
gen_ai.response.model, OpenInference's llm.model_name, or the Vercel AI
SDK's ai.model.id; the provider from gen_ai.system, llm.provider, or
ai.model.provider; and token counts from any of gen_ai.usage.input_tokens
/ output_tokens, the older prompt_tokens / completion_tokens,
OpenInference's llm.token_count.*, or Vercel's ai.usage.*. An
OpenInference span tagged openinference.span.kind = LLM or TOOL is mapped
even without gen_ai.* attributes.
Two attributes are worth setting explicitly:
agentping.agenton the resource overrides the agent identity whenservice.nameis not what you want on the dashboard.agentping.goalon the root span tells evaluations what the run was supposed to achieve. Setting it materially improves evaluation quality; without it the root span's name is used.
Run completion
OTel delivers spans in batches with no end-of-run signal, so a run ingested this way completes once its root span has arrived and no new span has landed for two minutes. Costs, health checks, and evaluations then run exactly as they do for SDK-reported runs.
Limits
Span attributes AgentPing does not map are kept with the step, up to 8KB per step; beyond that the largest attributes are dropped and the step is flagged, never rejected. Prompt and completion attributes count as step content with the usual 64KB allowance.
Verified emitters
Anything that speaks OTLP/HTTP works; each needs only the endpoint and header configuration above. These are the ones we test against recorded fixtures, so an upstream attribute rename is caught by us, not by you:
| Emitter | What to set | Mapped from |
|---|---|---|
| OpenLLMetry / Traceloop | TRACELOOP_BASE_URL to the endpoint, plus the auth header |
gen_ai.* |
| Pydantic AI | Enable instrumentation, point the OTLP exporter at the endpoint | gen_ai.* |
| Vercel AI SDK | experimental_telemetry: { isEnabled: true } plus an OTLP exporter |
ai.* |
| OpenInference (Arize Phoenix, OpenAI Agents SDK) | OTLP exporter to the endpoint | openinference.span.kind, llm.* |
| LangGraph (via OpenLLMetry's LangChain instrumentation) | OTLP exporter to the endpoint | gen_ai.*, node spans as steps |
CrewAI and LlamaIndex are supported through their OpenLLMetry / OpenInference instrumentation by the same path.