Observability with OpenTelemetry¶
kompend instruments its pydantic-ai agents with OpenTelemetry (OTel) out of the box. When enabled, every agent run, model request, tool call, and validation retry emits structured spans you can inspect in any OTel-compatible backend.
Naming: this is the OpenTelemetry tracing feature (agent runs). For the page-to-source provenance command, see Provenance.
This guide shows the fastest path to local visibility using Arize Phoenix — a pure-Python OTel collector + UI that runs as a single process (no Docker, no external services).
1. Install the OTel extra¶
# In the kompend repo (editable install)
uv sync --extra otel
# Or in a downstream project
uv add "kompend[otel]"
This pulls in opentelemetry-sdk with the OTLP HTTP exporter.
2. Start Arize Phoenix (local process, no venv pollution)¶
Phoenix starts two endpoints:
- OTLP receiver:
http://localhost:6006(receives traces from kompend) - Web UI:
http://localhost:6006(same port — open in your browser)
No Docker, no external services, no auth setup, no venv pollution. The process
stays running in your terminal (or background it with &). To stop, press Ctrl+C.
3. Enable kompend OTel export¶
export KOMP_OTEL_ENABLED=true
export KOMP_OTEL_ENDPOINT="http://localhost:6006"
export KOMP_OTEL_SERVICE_NAME="kompend"
# optional, if you later put Phoenix behind a proxy:
# export KOMP_OTEL_HEADERS="Authorization=Bearer <token>"
Then run any kompend command that invokes agents:
kompend -w wiki compile --tier wicer
# or
kompend -w wiki lint all
# or
kompend -w wiki query "your question"
4. Inspect traces in the Phoenix UI¶
Open http://localhost:6006 in your browser. You'll see:
| View | What it shows |
|---|---|
| Traces | One trace per agent invocation (extraction, generation, wicer-evaluate, wicer-probe, lint-rule, etc.) |
| Spans | Hierarchical: Agent Run → Model Request → Tool Call → Retry Loop |
| Attributes | Each span carries model, prompt, response, tool_name, tool_args, tool_result, validation_error, retry_count |
| Filter/Query | Filter by service.name = "kompend", span.name = "model.request", retry_count > 0, etc. |
What to look for¶
When you see unusual agent behavior — retries that shouldn't fire, long latencies, validation failures, or budget blow-up — the trace view is the cheapest place to start:
- Retry chains: A failing model run shows up as
model.request→validation.error→model.retry→ … → success/fail. Counting the retry spans answers “how often is this happening?” without parsing logs. - Tool call details:
tool_callspans record the exact arguments sent to the model and the tool's return value — useful when a tool call is what triggers a validation failure downstream. - Token usage:
usageattributes on model spans carry prompt and completion tokens; correlate withretry_countto see whether a budget cap is the actual failure cause.
5. Environment variables reference¶
| Variable | Default | Description |
|---|---|---|
KOMP_OTEL_ENABLED |
(unset/off) | true/1/yes to enable OTel export |
KOMP_OTEL_ENDPOINT |
http://localhost:4318 |
OTLP HTTP endpoint (Phoenix: http://localhost:6006) |
KOMP_OTEL_SERVICE_NAME |
kompend |
Service label in the OTel UI |
KOMP_OTEL_HEADERS |
(unset) | Optional key=value HTTP headers for auth |
6. Other OTel-compatible backends¶
The instrumentation is backend-agnostic — spans conform to standard OTel
semantic conventions, so you can point KOMP_OTEL_ENDPOINT at any OTLP HTTP
receiver (typically :4318):
- Jaeger —
http://localhost:4318 - SigNoz —
http://localhost:4318 - OpenObserve —
http://localhost:5081/api/default - Grafana Tempo —
http://localhost:4318 - collector + downstream — any OTLP HTTP endpoint
High-volume runs: enable sampling¶
A long compile (--tier wicer) can emit thousands of spans. BatchSpanProcessor
exports everything by default. For high-volume runs, enable ratio-based sampling:
export OTEL_TRACES_SAMPLER=traceidratio
# keep 10% of traces
# (this is an OpenTelemetry env var, read by the SDK — no kompend prefix)
export OTEL_TRACES_SAMPLER_ARG=0.1
To validate later, set OTEL_TRACES_SAMPLER=always_on to capture everything.
7. Managed SaaS: Logfire¶
The instrumentation is powered by the pydantic-ai framework, which has built-in support for Logfire (the observability platform from the pydantic team). Logfire is the recommended observability backend for kompend — it captures agent runs, tool calls, and LLM request/response spans out of the box with no extra configuration.
Enable it by setting KOMP_LOGFIRE_ENABLED=true (or installing the logfire
package and running logfire auth). kompend auto-configures Logfire at startup:
To disable Logfire for a specific invocation, set KOMP_LOGFIRE_DISABLED=true
or pass --no-logfire to the CLI.
For existing OTel users, Logfire also accepts OTLP endpoints:
export KOMP_OTEL_ENABLED=true
export KOMP_OTEL_ENDPOINT="https://logfire-us.pydantic.dev"
export KOMP_OTEL_HEADERS="Authorization=Bearer <your-write-token>"
8. What gets traced¶
| Agent type | Span prefix | Notes |
|---|---|---|
ExtractionAgent |
extraction.* |
Concept/entity extraction from source chunks |
AgenticGenerationAgent |
generation.* |
Wiki page generation, multi-turn tool loop |
WiCER |
wicer.evaluate / wicer.probe |
Two-phase refinement; retries visible as child spans |
LintRuleAgent |
lint.rule.* |
Rule evaluation + remediation spans |
QueryAgent |
query.* |
Search + synthesis pipeline |
Each agent run produces one root trace. The trace carries kompend.agent_type
and kompend.source_id attributes for filtering.
9. Disabling¶
Unset KOMP_OTEL_ENABLED or set it to anything other than true/1/yes.
Zero overhead when disabled — the tracer provider is never constructed.