investigate-telemetry
Diagnoses agent run errors by analyzing execution logs, failure states, and LLM call metrics.
Install
mkdir -p .claude/skills/investigate-telemetry && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/12084" && unzip -o skill.zip -d .claude/skills/investigate-telemetry && rm skill.zipInstalls to .claude/skills/investigate-telemetry
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Investigate a failed or suspicious agent run (implementer/coder, bootstrap, reviewer, etc.) using the production telemetry in D1. Use when asked to look into a run failure, "no progress" abort, a stuck/looping agent, model output quality, token/truncation issues, or "what went wrong with the latest run". Pulls the run lifecycle from `agent_runs` and the per-LLM-call prompt/response/usage from `llm_call_metrics`, then reads the tool-call loop to find the root cause.Key capabilities
- →Find specific agent runs using D1 database queries.
- →Read the failure verdict and step list from `agent_runs` to understand how a run died.
- →Analyze per-call LLM telemetry from `llm_call_metrics` to identify issues like truncation or infra failures.
- →Examine `prompt_text` and `response_text` to find root causes like malformed tool arguments or looping calls.
- →Classify the failure as model quality, truncation, infra, or working as designed, and report with evidence.
How it works
The skill queries D1 database tables `agent_runs` and `llm_call_metrics` to analyze the lifecycle and LLM interactions of a failed agent run, identifying the root cause.
Inputs & outputs
When to use investigate-telemetry
- →Debugging agent run failures
- →Investigating infinite loops
- →Analyzing LLM response quality
About this skill
Investigate run telemetry (from D1)
Telemetry lives in the production D1 database cat_factory, NOT (primarily) in
Cloudflare Workers Observability. Two tables carry everything you need:
-
agent_runs— one row per container-backed run (kind='execution'for the task pipeline / implementer,kind='bootstrap'for repo bootstrap). Holdsstatus, the structuredfailureJSON (kind/message/hint/lastSubtasks), and adetailJSON with every pipeline step (agentKind, state, model, approvals, per-stepmetrics). This is the lifecycle + the failure verdict. -
llm_call_metrics— one row per LLM call (migration 0026). Holdsagent_kind,provider,model,ok,http_status,finish_reason, token counts,request_max_tokens, the latency split (upstream_ms/overhead_ms),error_message, and the fullprompt_text+response_text. Linked to a run byexecution_id. This is what the model actually saw and produced.Three producers write here and their rows read differently, so check which one you have before drawing a conclusion from a null: a proxied container call (Pi) carries the full latency split and an
http_status; a subscription harness call (Claude Code / Codex) carries aturn_indexand aphasebut zero timing (the CLIs expose none); an inline call (a judge, consensus, the requirements writer, an inline agent kind such asdoc-researcher/doc-outliner/ the document interviewer) hasstreaming=0,turn_indexNULL,http_statusNULL,phase='', andupstream_ms = total_ms— a genuine 0 overhead, because there is no proxy hop. None of those nulls means data was lost.
Retention: llm_call_metrics is pruned to LLM_CALL_METRICS_RETENTION_DAYS (default 14
days) because the full bodies are heavy; agent_runs lives longer. A deployment may have
lowered it, so an empty result for an older run can mean pruned rather than never recorded.
How to query
Run wrangler from deploy/backend (its wrangler.toml defines the cat_factory
binding). Always pass --remote (production) and --json (parseable). Do NOT
pre-check Cloudflare auth — assume the login is correct (see CLAUDE.md).
cd deploy/backend
npx wrangler d1 execute cat_factory --remote --json --command "SELECT ..."
Parse the JSON with node -e (Python is not on PATH here). The result shape is
[{ results: [...rows], success, meta }].
Step 1 — find the run
Latest implementer/pipeline runs (drop the WHERE kind to see bootstrap too):
SELECT id, kind, status, block_id,
datetime(created_at/1000,'unixepoch') AS created,
datetime(updated_at/1000,'unixepoch') AS updated
FROM agent_runs
WHERE kind='execution'
ORDER BY created_at DESC LIMIT 10;
Take the id (e.g. exec_44c8387cac02) of the run in question.
Step 2 — read the failure verdict and step list
SELECT failure, detail FROM agent_runs WHERE id='<run id>';
failure(JSON):kind(job_failed,evicted,timeout,agent, …),message(the abort reason — e.g. theProgressGuardtext),hint, andlastSubtasks. This tells you HOW the run died.detail.steps[](JSON): which step was running at failure (state:'working'), themodeleach step used, and each step's rolled-upmetrics(calls,truncatedCalls,errors,warnings,peakCompletionTokens,maxOutputTokens). The step withjobId === <run id>is the container step.
Step 3 — read the per-call LLM telemetry
Overview of every call for the failing step's kind (usually coder):
SELECT agent_kind, provider, model, ok, http_status, finish_reason,
prompt_tokens, completion_tokens, request_max_tokens, upstream_ms,
datetime(created_at/1000,'unixepoch') AS t, substr(error_message,1,300) AS err
FROM llm_call_metrics
WHERE execution_id='<run id>' AND agent_kind='coder'
ORDER BY created_at ASC;
Read the columns as signals:
ok=0/ non-2xxhttp_status/ non-nullerror_message→ transport, proxy, or spend-gate failure (an infra problem, not a model problem).finish_reason='length'orcompletion_tokensnearrequest_max_tokens→ output truncation; the model was cut off mid-answer (raise the output limit or shrink the task).truncatedCallsin the step metrics counts these.ok=1+finish_reason='tool_calls'everywhere → the LLM side is healthy; the failure is in tool EXECUTION inside the container (see step 4). Not in this table, but each failing tool call is its own row inagent_tool_calls(ok=0), which is where step 4 starts. TheProgressGuard(harnesspi.ts) counts the same failures live off Pi's event stream, which is what aborts the run.
Step 4 — read the actual tool-call loop (the root cause)
Read the trajectory first. agent_tool_calls (same telemetry DB) holds one row per tool
invocation, so a stuck loop or a failing edit is visible without reconstructing it from
prompt deltas:
SELECT seq, tool, ok, datetime(started_at/1000,'unixepoch') AS t,
substr(args,1,200) AS args, substr(result,1,300) AS result
FROM agent_tool_calls
WHERE execution_id='<run id>'
ORDER BY started_at ASC, seq ASC;
Order by (started_at, seq), never by job_id (a string that sorts a run's dispatches by
agent-kind spelling) and never by seq alone (it restarts at zero on each dispatch). Add
AND job_id='<job id>' to read one dispatch. bodies='withheld' means the workspace or
deployment opted out of body capture, so an empty args says nothing about the call; a run
whose image predates the sink has no rows at all, and the deltas below are then the only
account.
prompt_text is stored as a DELTA vs the previous call (migration 0027), so each
call's prompt_text contains the new assistant message(s) plus the tool RESULT
messages returned to the model — including tool validation errors. response_text
is the model's text content (tool-call arguments are echoed inside the assistant
message in the next call's prompt delta).
Dump responses to see what the model was trying to do:
SELECT completion_tokens, response_text
FROM llm_call_metrics
WHERE execution_id='<run id>' AND agent_kind='coder'
ORDER BY created_at ASC;
Dump the tail of the final prompt to see the last tool result/error the model got:
SELECT prompt_text FROM llm_call_metrics
WHERE execution_id='<run id>' AND agent_kind='coder'
ORDER BY created_at DESC LIMIT 1;
Look for, in prompt_text: Validation failed for tool "<tool>" /
must have required properties <field> (the model is emitting malformed tool
args), repeated identical tool calls (a stuck loop), or <tool_call>…</tool_call>
appearing as literal TEXT in response_text (the model emitted a tool call as
prose instead of through the structured channel — fragile parsing, a model-quality
smell). In response_text: garbled token-soup completions point at a Workers AI
decode bug for that model (cf. the streaming token-doubling fix, commit 23b9fb6).
Step 5 — classify and report
Decide whether the failure is:
- Model quality — malformed/looping tool calls, garbled output, ignored validation errors. Fix: don't default that role to that model; pin a stronger tool-calling model or denylist it for code steps.
- Truncation —
finish_reason='length'. Fix: raise output limit / split task. - Infra —
ok=0, HTTP errors, spend-gate refusals, eviction/timeout (failure.kind). Fix: the proxy/runner/budget, not the prompt. - Working as designed — the
ProgressGuardaborting a genuinely stuck run is the safety net doing its job; the bug (if any) is upstream of it.
Report: the run id, the failing step + model, the abort reason, the root-cause
class with the evidence (quote the specific tool error or response), and a concrete
fix. Then the run can be retried (POST /workspaces/:ws/agent-runs/:id/retry,
or the board "retry" button) to spin a fresh container.
Notes
- Helper one-liner to scan all deltas for tool validation failures:
pipe the
prompt_textrows throughnodeandmatch(/must have required properties (\w+)/g). - The app also exposes this without SQL:
GET /executions/:id/llm-metrics(per-call list) andGET /executions/:id/llm-metrics/export(LLM-friendly JSON bundle). With aread-scoped public API key, the remote debugging surface (/api/v1/debug/*, seebackend/docs/debug-api.md) covers steps 1–4 end to end: the run overview'ssignalsreplace step 2's manual reading, and?contains=+matchOffset+?bodyOffset=replace step 4's grep. Use D1 directly when you need cross-run queries or the app is unreachable.
When not to use it
- →When the telemetry data is older than the retention period (e.g., 3 days for `llm_call_metrics`).
- →When the issue is not related to agent run failures, loops, or quality.
- →When the D1 database `cat_factory` is not accessible.
Limitations
- →Telemetry data for `llm_call_metrics` is pruned aggressively.
- →Requires `wrangler` CLI from `deploy/backend` to query D1.
- →Does not automatically fix the identified issues; it provides a diagnosis.
How it compares
This skill provides a structured, data-driven approach to debugging agent run failures using production telemetry, unlike relying on general logs or assumptions.
Compared to similar skills
investigate-telemetry side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| investigate-telemetry (this skill) | 0 | 1mo | Review | Advanced |
| langsmith-observability | 4 | 7mo | Review | Intermediate |
| debugging-toolkit-smart-debug | 4 | 4mo | No flags | Intermediate |
| jaeger-analysis | 6 | 5mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
langsmith-observability
davila7
LLM observability platform for tracing, evaluation, and monitoring. Use when debugging LLM applications, evaluating model outputs against datasets, monitoring production systems, or building systematic testing pipelines for AI applications.
debugging-toolkit-smart-debug
sickn33
Use when working with debugging toolkit smart debug
jaeger-analysis
incidentfox
Jaeger distributed tracing analysis. Use when investigating request latency, tracing errors across services, finding slow spans, or understanding service dependencies.
log-analyzer
mikopbx
Анализ логов Docker контейнера для диагностики проблем и мониторинга здоровья системы. Использовать при отладке ошибок, отслеживании процессов воркеров, исследовании проблем API или мониторинге поведения системы после тестов.
gcloud-usage
fcakyon
This skill should be used when user asks about "GCloud logs", "Cloud Logging queries", "Google Cloud metrics", "GCP observability", "trace analysis", or "debugging production issues on GCP".
error-debugging-error-analysis
sickn33
You are an expert error analysis specialist with deep expertise in debugging distributed systems, analyzing production incidents, and implementing comprehensive observability solutions.