Triage the last N production call logs for a Cekura agent against a set of KPIs / issues / goals, report the call IDs that hit each failure WITH the percentage of overall call logs affected, and distribute the remaining calls into a mutually-exclusive outcome taxonomy (e.g. not-answered / vetted / non-vetted caller-side / non-vetted agent-issue) with per-bucket percentages. Use when the user says "flag call log failures", "analyze the last N calls for issues", "what % of calls have <problem>", "which calls broke and how often", "find failing calls", "give me the breakdown of call outcomes", "what % of answered calls can be improved", or pastes an agent / project ID and lists the problems or KPIs to measure. Applies attribution rules so caller-side endings and recovered calls are NOT counted as agent failures. This is the upstream triage step that feeds `cekura-generate-scenarios` — it does NOT create scenarios.
76
96%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Go through an agent's recent production call logs and produce three things:
It is the triage front-end: hand the flagged set to cekura-generate-scenarios to build evaluators, or give the user the distribution for a customer-facing quality report.
This skill is strictly read-only — it never creates, updates, or deletes anything.
The single most important job is attribution: a call is an agent failure only when the agent under test caused it. Caller-side endings, simulated-caller disconnects, and recovered calls must NOT be counted as agent failures — they belong in their own buckets.
Reads through the Cekura MCP. Confirm these are present:
mcp__cekura__aiagents_retrieve — agent description + intended behavior (the yardstick for "failure")mcp__cekura__call_logs_list — paginated production call list (lightweight: usually has id, duration, call_ended_reason, success, rolled-up metric scores — but often no transcript)mcp__cekura__call_logs_retrieve — full transcript + metric evaluations for a single callmcp__cekura__metrics_list — to find metrics that already grade the KPIs/issues (reuse these as the classification basis when they exist)If the mcp__cekura__* tools aren't connected, stop and tell the user to connect the Cekura MCP (see /setup-mcp or https://docs.cekura.ai/mcp/overview).
Use AskUserQuestion for anything not supplied:
Agent ID (numeric). If unknown, mcp__cekura__aiagents_list helps find it.
(Optional) Project ID.
Window — how many recent calls (default 100) or a date range. Process in batches (see Step 2).
KPIs / issues / goals to measure — the heart of the request:
agent_description, classified against the failure-mode taxonomy in Step 3.Outcome taxonomy — the mutually-exclusive buckets to distribute ALL calls into. Derive these from the agent's job. For a candidate-vetting agent the natural set is:
not answered · vetted · non-vetted — caller-side · non-vetted — agent/system issueFor other agents, adapt (e.g. resolved / escalated / abandoned / agent-error). Confirm the bucket set with the user before reporting.
Echo the issue list and the bucket set back so the user confirms before you grind through the window.
Agent context — mcp__cekura__aiagents_retrieve(id=...): capture agent_description, agent_name, project_id, and any {{dynamic_variable}} names that define a KPI (e.g. requiredScreeningQuestions).
⚠️ If
agent_descriptionis empty/placeholder AND no explicit issue list was given, STOP — "failure" is ungrounded. Ask the user to name the issues or flesh out the description.
Call logs — loop in batches. mcp__cekura__call_logs_list with page_size=20, walking page=1..K until you've covered the window. The list view is lightweight, so collect the cheap signal for every call first:
| Field | Used for |
|---|---|
id, duration | identity, length-based heuristics |
call_ended_reason | who/what ended the call (the strongest first-pass signal) |
success / status | rolled-up pass/fail |
metrics[] scores | if your KPI metrics already ran (see below), read the score directly |
Cheap first pass (heuristic) → then verify only the candidates. Pulling every transcript is wasteful and can blow the token budget. Instead:
call_ended_reason + duration first. Strong proxies:
< 25s) → not answered / no engagementMain agent-ended-call) at normal length → agent completed its flow (provisionally vetted)testing-agent-ended-call, customer-ended-call, Client disconnected) → caller-side (provisionally)Ending conversation after N seconds of silence) → agent/system candidate (verify)call_logs_retrieve (they overflow to a file when large — parse with a script for loop/repeat detection rather than reading inline).long call ≠ loop. A long call is NOT automatically an agent failure — verify before counting it. Check for an actually-repeated question (same normalized agent line ≥4×) or a runaway invented-question pattern. Many long calls are just thorough vetting (≈1:1 agent/candidate turns, no repeat).Prefer the metrics we already built as the classification basis when they're attached to the agent/project — they encode the exact attribution rules:
Call not answered (no pickup / voicemail) → defines the not-answered bucket (TRUE = not answered).All vetting questions asked (perf) → vetting completion on eligible calls (PASS = vetted).Testing agent ended call before hard vetting started → caller-side early drop (TRUE).All vetting questions asked (failure-flag) → agent skipped questions.If those metrics haven't been evaluated on the window yet, you can either trigger them (call_logs_evaluate_metrics_create — costs eval credits, async) for an audited number, or classify by transcript/heuristic and report the result as an estimate (state which).
If call_logs_list returns 0, stop — pre-production agent, nothing to triage.
For each call, decide its outcome bucket (mutually exclusive) and, if it's an agent failure, which issue/mode. When flagged as a failure, record:
{ call_log_id, issue/mode, severity, evidence_quote, ended_reason, expected_behavior }evidence_quote — verbatim transcript slice (or failing metric justification). No paraphrasing; if you can't quote it, it isn't a flag.expected_behavior — one sentence on what the agent should have done (carries into a scenario's expected_outcome_prompt)."Any genuine failure" taxonomy (when no explicit issue list):
| Code | Mode | Detection signals |
|---|---|---|
🛑 drop | Ended early by the agent | agent ended/transferred mid-workflow; agent-side disconnect |
🌀 drift | Off-task / off-persona | content unrelated to agent_description |
👻 hallucination | Facts not in KB/description | numbers/policies/products absent from the description/KB |
🔧 tool_error | Tool selection/args/post-tool broke | tool error; re-asks something a tool already answered; wrong tool |
🎯 workflow_miss | Required step skipped/wrong | concluded before asking all required questions; skipped consent |
🤔 comprehension | Misunderstood caller | re-asks same clarifying question 3+ times; loops with no recovery |
🔁 loop | Stuck repeating, never converges | same question/confirmation many times; runaway invented questions |
🚪 refusal | Refused a legitimate, in-scope ask | "I can't help with that" inside its description |
⚡ latency | Long gaps / slow / unresponsive | long inter-turn gaps; no response after caller finished |
🧨 safety | PII leak / unsafe content | repeated back SSN/card unprompted; disallowed content |
📻 asr_capture | Candidate spoke but wasn't captured | candidate turns register as "…"; agent re-prompts "are you still there?" → silence-timeout (system/ASR class, improvable but not a prompt bug — call it out distinctly) |
A call can hit multiple issues — record each. But it lands in exactly one outcome bucket.
Count a call as an agent failure ONLY when the agent under test caused it. Otherwise it goes in a non-agent bucket.
call_ended_reason ∈ {testing-agent-ended-call, customer-ended-call, Client disconnected: 1005/1012} before the agent could finish → non-vetted caller-side, not agent.If the user's explicit issue list contradicts a default (e.g. they do want caller drops counted), follow the user.
Two computations over the full reviewed set (let N = total reviewed):
A. Failure rates. For each flagged issue: count / N = % of overall call logs with that failure. If the user framed it as "% of answered calls," compute against the answered denominator instead (answered = N − not_answered, where not-answered is the Call not answered bucket). State the denominator explicitly.
B. Outcome distribution. Assign every call to exactly one bucket and report counts + %:
not answered : a/N
vetted : b/N (= b/answered)
non-vetted caller-side : c/N (= c/answered)
non-vetted agent/system : d/N (= d/answered) ← the improvable sliceSub-split a bucket when it's useful (the agent/system slice often splits into e.g. ASR-capture vs true agent loop; the caller-side slice into dropped before vetting began vs dropped mid-vetting — the latter maps to the Testing agent ended before hard vetting started metric).
Headline the improvable number: "X% of answered calls are improvable on our side" (the agent/system bucket), and note how much of the non-vetted total is caller-side (not an agent defect).
# Call-log failure analysis — <agent_name> (`<agent_id>`)
**Window:** last <N> calls (<start> → <end>) · **Answered:** <A>
**Criteria:** <the confirmed KPI/issue list>
## Outcome distribution
| Bucket | Count | % of all | % of answered |
|---|---|---|---|
| Not answered | a | a/N | — |
| Vetted | b | b/N | b/A |
| Non-vetted — caller-side | c | c/N | c/A |
| Non-vetted — agent/system (improvable) | d | d/N | d/A |
→ **~d/A% of answered calls are improvable on our side.** (Caller-side = c/A%, not an agent defect.)
## Flagged failures (agent/system) — call IDs + rate
| Issue | Rate (of all) | Calls (evidence) |
|---|---|---|
| ASR capture → silence drop | 6/N | [<id>](…) "are you still there?" ×N → timeout; … |
| Loop | 1/N | [<id>](…) re-asked "which shift?" ×6 |
## Methodology & confidence
- Which calls were transcript-verified vs. heuristic-bucketed (ended_reason + duration).
- If the agent/system count is a lower bound (issues hidden inside agent-ended/caller-ended calls weren't all read), say so.
- Whether numbers are audited (metrics evaluated) or estimated (heuristic).Rules:
https://dashboard.cekura.ai/<project>/observe/<id>.Flagged agent/system calls (<d/A>% of answered). Want me to turn these into regression scenarios? I can hand the flagged set to
cekura-generate-scenarios, which clusters them and builds one evaluator per failure pattern.
If yes, invoke cekura-generate-scenarios and pass the flagged set — each entry already carries {call_log_id, issue/mode, severity, evidence_quote, expected_behavior}, exactly the per-call record it expects (it skips its own mining and goes straight to clustering). Don't re-triage there.
cekura-generate-scenarios (single-call fast path).caa6544
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.