Investigate and root-cause production issues from live OpenTelemetry telemetry (traces, logs, metrics) with the Kopai SDK in TypeScript code mode. Use this skill to debug errors and error-rate spikes, investigate latency/slowness and timeouts, trace requests across services, find failing or cascading services, and correlate logs to a trace — including vague symptom reports like 'why is my API slow', 'getting 500 errors', 'service is down', 'requests are timing out', or 'something is failing in prod', even when the user never says 'traces' or 'observability'. This analyzes existing telemetry to find a cause. Do NOT use it to add instrumentation (use otel-instrumentation), to build dashboards or visualizations (use create-dashboard), or to fix non-telemetry problems like failing CI, lint errors, unit tests, or SQL query tuning.
77
97%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
| title | impact | tags |
|---|---|---|
| Step 2: Get Full Trace Context | CRITICAL | workflow, trace, context, step2 |
Impact: CRITICAL
Pull every span of a trace, then inspect fields per row. getTrace returns
OtelTracesRow[] — no time window or query builder needed.
// get-context.mts — run: npx tsx get-context.mts
import { clientFromConfig } from "@kopai/sdk/node";
const client = clientFromConfig();
const traceId = "<traceId>";
const spans = await client.getTrace(traceId); // OtelTracesRow[] — all spans
// Slowest span = likely bottleneck (Duration is NANOSECONDS: 1ms=1e6, 1s=1e9).
const slowest = [...spans].sort(
(a, b) => Number(b.Duration) - Number(a.Duration)
)[0];
// Earliest Error in the chain = usually closest to root cause.
const firstError = [...spans]
.filter((s) => s.StatusCode === "Error") // "Unset" | "Ok" | "Error"
.sort((a, b) => Number(a.Timestamp) - Number(b.Timestamp))[0];
console.log(JSON.stringify({ slowest, firstError }, null, 2));"Select specific fields" is just reading row props — no --fields flag. Project
what you need:
const view = spans.map((s) => ({
SpanName: s.SpanName,
Duration: s.Duration, // nanoseconds
StatusCode: s.StatusCode, // "Unset" | "Ok" | "Error"
ParentSpanId: s.ParentSpanId,
}));
console.log(JSON.stringify(view, null, 2));| Field | What to Look For |
|---|---|
| ParentSpanId | Span hierarchy / call chain (empty on root span) |
| Duration | Slow spans (bottlenecks) — nanoseconds, find the max |
| SpanAttributes | Request context, parameters |
| StatusMessage | Error details, exception info |
| StatusCode | "Ok" / "Error" (successful spans are usually "Unset") |
Two questions drive the read: which span is slowest (max Duration) and
where the chain first broke (earliest span with StatusCode === "Error",
ordered by Timestamp). Reconstruct hierarchy from ParentSpanId to see which
call dragged the latency or threw first.
npx @kopai/cli traces get <traceId> --json
npx @kopai/cli traces get <traceId> --fields SpanName,Duration,StatusCode --jsonSee references/trace-filters.md for trace columns and field details.