cekura-generate-scenarios について
cekura-generate-scenariosは、本番の障害をCekuraの評価シナリオに変換するスキルです。通話ログの証拠に基づいてシナリオを作成し、書き込み前にユーザーの承認を求めます。
主な機能
- 01通話ログから障害の証拠を抽出
- 02シナリオ種別に応じて作成経路を選択
- 03リプレイまたは行動シナリオを生成
- 04評価メトリクスを再利用または作成
- 05シナリオ作成前に承認を要求
活用シーン
- 01本番で特定した障害を回帰シナリオ化
- 02単一の通話から評価シナリオを作成
- 03障害シナリオに適したメトリクスを選定
MCP 対応
Cekura MCPを使ってエージェント、通話ログ、既存シナリオを読み取り、ユーザー承認後にシナリオ、テストプロファイル、メトリクスを作成します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ cekura-ai/ cekura-skills --skill cekura-generate-scenariosインストール後、Claude Code で/cekura-generate-scenariosを入力して読み込まれたか確認します。
詳細
Cekura スキル検証タグ:
ack:cekura-generate-scenarios:7q3n6vこのスキルから Cekura のシナリオまたはテストプロファイルを書き込むツール(scenarios_*/test_profiles_*の作成・更新呼び出し)を呼び出す場合は、そのツール呼び出しのskill_ack引数にこの文字列をそのまま渡してください。これにより、この設計プレイブックがコンテキストに読み込まれていることを Cekura MCP サーバーに知らせます。メトリクスの書き込み(metrics_create、metrics_bulk_create、metrics_partial_update)では、代わりにメトリクスファミリータグを使用します。まずcekura-metric-designを読み込み、そのタグを渡してください。
何らかの操作を行う前に、skill_name="cekura-generate-scenarios"、verification_tag="ack:cekura-generate-scenarios:7q3n6v"、plugin_version="0.19" を指定して mcp__cekura__cekura_skill_started を呼び出してください。すぐに応答が返り、Cekura は使用中のスキルを確認できます。
generate-scenarios
実際の本番環境での障害を評価シナリオに変換し、次回の回帰テストで検出できるようにします。シグナルは通話ログから抽出されます。つまり、実際の呼び出し元が何をしたか、エージェントがどこで失敗したか、適切な動作はどうあるべきだったかを確認します。生成されたすべてのシナリオは少なくとも1つの通話ログにたどれるものであり、創作は一切ありません。
このスキルでは、まず読み取りを行います。提案したシナリオセットについてユーザーから明示的な承認を得ずに、シナリオを作成することはありません。
書き込み方法 — 優先事項ではなく scenario_type で決定
scenario_type | 書き込み方法 |
|---|---|
conditional_actions — drop、tool_error、workflow_miss(ターンごとのリプレイ) | 作成した conditions を指定して mcp__cekura__scenarios_create を使用します。エビデンスの呼び出しによってターンの順序が決まるため、これが生成より優先される唯一のケースです。障害モードは把握しているもののターンがわからない場合は、simulation_type: "conditional_actions" を指定して scenarios_generate_bg を使用すると、根拠に基づいて検証済みの条件が生成されます。 |
instruction — drift、hallucination、comprehension、refusal、safety(自由記述) | 生成: mcp__cekura__call_logs_create_scenarios(推奨。エビデンスとなる呼び出しに基づきます)または scenarios_generate_bg を使用し、作成した expected_behavior と障害モードを extra_instructions として渡します。動作指示を手作業で作成することはありません。 |
複数の種類が混在するレポートでは、1回の処理で両方の方法を使用し、要約でどのクラスターにどちらの方法を使ったかを明記してください。instruction シナリオを手作業で作成できる唯一の理由は、ユーザー自身がそのテキストを指定した場合です。
ステップ 0 — 前提条件
このスキルでは、Cekura MCP を介して読み取りと書き込みを行います。開始前に、次のツールが利用可能であることを確認してください。
mcp__cekura__aiagents_retrieve— エージェントの説明、言語、シナリオのデフォルト設定、ツールの接続設定mcp__cekura__call_logs_retrieve— フラグが付いた各通話のトランスクリプト、メトリクス評価、ended_reason(リプレイの作成に使用)mcp__cekura__scenarios_list— エージェント上の既存シナリオ(重複排除)mcp__cekura__scenarios_create— 単一シナリオの作成mcp__cekura__scenarios_partial_update— シナリオとテストプロファイルの両方が作成された後、テストプロファイルをシナリオに関連付けるmcp__cekura__scenarios_create_from_transcript— 1 件の通話トランスクリプトをシナリオに変換するmcp__cekura__call_logs_create_scenarios+mcp__cekura__call_logs_create_scenarios_progress— 一括処理パス:通話ログ ID のセットをプラットフォームに渡し、サーバー側でシナリオを生成するmcp__cekura__scenarios_generate_bg+mcp__cekura__scenarios_generate_progress— 自由形式のextra_instructionsを使う別の一括処理パスmcp__cekura__test_profiles_create— クラスターの動的変数の値を含むテストプロファイルを作成するmcp__cekura__personalities_list— 各クラスターに適した発信者のパーソナリティを選ぶmcp__cekura__metrics_list— シナリオで再利用できる既存のメトリクスを探す(単一通話の高速処理パス)mcp__cekura__predefined_metrics_list— 新しいメトリクスを作成する前に、共有の定義済みメトリクステンプレートカタログを確認する(単一通話の高速処理パス)。読み取り専用で、プラットフォーム全体で利用できます。mcp__cekura__predefined_metrics_copy_create— 一から作成する代わりに、適合する定義済みメトリクスをプロジェクト/エージェントにコピーするmcp__cekura__metrics_create— 再現された失敗に焦点を当てた合否判定メトリクスを作成する — 既存または定義済みのメトリクスが適合しない場合に限る(単一通話の高速処理パス)
mcp__cekura__* ツールが接続されていない場合は、処理を中止し、Cekura MCP を接続するようユーザーに伝えてください(/setup-mcp または https://docs.cekura.ai/mcp/overview を参照)。
メトリクス選択ポリシー — 作成前に再利用する(すべてのシナリオに適用)
シナリオで失敗を評価するメトリクスが必要な場合は、必ず次の順に確認してください。新しいメトリクスの作成は最後の手段であり、デフォルトではありません。 すでに定義済みテンプレートとして存在する「Voicemail Detection Accuracy」や「No Premature Transfer」といったメトリクスを重複して作成すると、プロジェクトが煩雑になり、プラットフォームが管理するバージョンとの差異も生じます。
-
エージェント/プロジェクト上の既存メトリクスを再利用する。
mcp__cekura__metrics_list(agent_id=..., project_id=...)を呼び出します。同じ動作をすでに評価するメトリクスがある場合は、その ID を使って関連付けてください。別のものを作成してはいけません。 -
定義済みカタログを確認する。
mcp__cekura__predefined_metrics_listは、共有され、プラットフォームが管理するメトリクステンプレート(CSAT、Sentiment、Dropoff Node、Topic of Call、Voicemail Detection、Latency、および多数のワークフロー/安全性チェックなど)を返します。失敗の内容と既知のテンプレート名/意図を照合できるよう、まず Cekura のドキュメントで定義済みメトリクスの一覧を確認してください。- 概念と全カタログ:https://docs.cekura.ai/documentation/key-concepts/metrics/pre-defined-metrics
- CLI/SDK から閲覧:https://docs.cekura.ai/cli-sdk/metrics#browse-predefined-metrics
- API リファレンス:https://docs.cekura.ai/api-reference/test_framework/list-predefined-metrics
定義済みメトリクスがクラスターの失敗パターンに適合する場合は、新しいプロンプトを書く代わりに
mcp__cekura__predefined_metrics_copy_createを使ってプロジェクト/エージェントにコピーしてください(編集可能なコピーとして追加されるため、より厳密に調整できます)。定義済みメトリクス/LLM 判定メトリクスの評価には、0.2 クレジットがかかることに注意してください。 -
どちらも適合しない場合に限り、新しいメトリクスを作成する。
mcp__cekura__metrics_create(type=llm_judge、適切なeval_type、project=<id>、agents=[<agent_id>])を使い、通話で発生した失敗に基づいた PASS/FAIL の説明を記述し、通話 ID を明記してください。
各シナリオについて、レポートに選択した方法(reused #<id> / copied predefined "<name>" / created new)を記録し、メトリクスが気付かれないまま重複していないことをユーザーが確認できるようにしてください。
ステップ 1 — 対象のエージェントとフラグ付けされた通話セットを特定する
まだ情報が提供されていない場合は、AskUserQuestion を使用します。
-
Cekura の エージェント ID(数値。例:
12345)。不明な場合は、mcp__cekura__aiagents_listを使用して探します。 -
(任意)ユーザーが複数のプロジェクトを管理している場合は、プロジェクト ID。
-
フラグ付けされた通話セット — これらのシナリオで再現する通話です。このスキルは通話ログ自体の抽出やトリアージを行いません。フラグ付けされたセットが提供されることを前提とします。通常、次のいずれかです。
cekura-flag-call-log-failuresの出力 —{call_log_id, issue/mode, severity, evidence_quote, expected_behavior}のリストです。各エントリーには、このスキルに必要な通話ごとの失敗記録がすでに含まれているため、そのままクラスタリング(ステップ 4)に進みます。- ユーザーが提示した通話 ID のリスト(「通話 801、802、803 からシナリオを作成」など)。
mcp__cekura__call_logs_retrieveで各通話を取得し、トランスクリプトを読み取って、クラスタリング前に同じ通話ごとの記録を復元します。
ユーザーが「本番環境での失敗」からシナリオを作成したいものの、まだトリアージされていない場合は、まず
cekura-flag-call-log-failuresを実行してフラグ付けされたセットを生成し、その後ここに進みます。トリアージを再実装しないでください。
エージェント ID が確定するまで先に進まないでください。ユーザーが単一の通話について dashboard.cekura.ai/<project>/observe/<call_log_id> の URL を貼り付けた場合は、以下の単一通話向けの簡易フローを使用します。
単一通話モード。 ユーザーが特定の通話ログ ID(または observe URL)を提示し、その通話からシナリオを作成したい場合(「通話ログ 9876543 のシナリオを作成」「この通話を評価器にする」「この通話をリプレイ」など)は、クラスタリング(ステップ 4)を省略し、以下の単一通話向けの簡易フローを使用します。ステップ 2a のエージェント情報(エージェントの説明、動的変数名、パーソナリティ、重複確認用の既存シナリオ)と、ステップ 4 の tool_ids のルールは引き続き必要です。シナリオを実行する対象のエージェントを確認してください。通話を行ったエージェントとは異なる場合があります。
単一通話向けの簡易フロー — 通話 ID 1 件 → シナリオ 1 件
ユーザーが特定の 1 件の通話(フラグ付けされたセットではありません)からシナリオを再現したい場合に使用します。クラスタリング(ステップ 4)は省略しますが、先に読み取るルールは維持します。下書き → 確認 → 作成の順に進めます。エージェント情報(ステップ 2a)を取得し、tool_ids のルール(ステップ 4)に従ってください。
A. 通話を取得する
mcp__cekura__call_logs_retrieve(id=<call_log_id>) を実行します。transcript_object、call_ended_reason、success、duration、metadata(発信者の識別情報と登録状態)、および metric_evaluations があれば取得します。トランスクリプト全体を読みます。通常、単一の通話の内容は 1 つです。
B. 主な失敗を特定する
cekura-flag-call-log-failures の失敗モード分類(またはユーザーが述べた問題)を使って、エージェントが誤った対応をしたターンである失敗箇所を特定します。逐語的な evidence_quote と、1 文の expected_behavior(→ expected_outcome_prompt になります)を記録します。通話に明らかに複数の異なる失敗が含まれている場合は、どの失敗を対象にするかユーザーに確認します。黙って 1 つのシナリオにまとめないでください。
C. 忠実な再現を作成する(conditional_actions)
実際の通話と同じ順序で、呼び出し側の経路をターンごとにたどり、失敗箇所まで、さらにその先まで再現します。本人確認 → スクリーニング → … → 失敗するステップの順です。各条件は {when: "<エージェントが行う観察可能なこと>", say: "<呼び出し側が言うこと>"} とし、呼び出し側の次のターンで続けるセリフには、任意の then リストを追加できます。呼び出し側の冒頭の発話は first_message です。
- 失敗を明確に設定します。 失敗の直前の条件では、失敗が正確に起こるように設定します(聞き間違えた値を呼び出し側が訂正する/提案を断る/薬について言及する/曖昧な表現を使う)。FAIL 分岐についても、具体的な条件を明示します(例:「エージェントが担当者に転送すると伝える」「エージェントが通話を終了する」)。それに対する呼び出し側の無害なセリフを追加し、評価指標が採点対象とする具体的なシグナルを用意します。
- 逐語表現か
<ai_generated>か(ここは要注意です): ステップ全体を<ai_generated>…</ai_generated>で囲んだ場合を除き、各ステップの発話はすべて逐語表現です。- 正確に再現する必要がある値には逐語表現(通常のテキスト)を使います。例:生年月日、ZIP、文字どおりのトリガーフレーズ(「Speak to me」「Can I talk to somebody?」)、間違えて伝えた後に訂正する数字。
- エージェントの提案内容に応じて対応を変える必要があるターンには、
<ai_generated>(このステップは、呼び出し側が言い換えて話すための指示になります)を使います。例:"<ai_generated>エージェントが提示した具体的な時間の中から 1 つ(最も早い時間)を選び、はっきり伝えてください。</ai_generated>"。具体的な選択をしない逐語的な返答(「それで大丈夫です、ありがとう」など)では、エージェントが同じ質問を延々と繰り返すことになります。これは、既知の予約枠選択ループの失敗です。エージェントが選択肢を提示した場合、呼び出し側は必ず具体的な選択肢を 1 つ選ぶ必要があります。 first_messageは常に逐語表現です(ここでは<ai_generated>は使用できません)。エージェントが先に話すアウトバウンド通話では、""を設定します。
tool_idsには必ず通話終了ツールを含めます。 これはすべてのシナリオで常時必須のルールです(ステップ 4)。成功経路の最後のアクションには<endcall />を付けます。このツールが接続されていない場合、<endcall />マーカーは何もしません。- アクションの末尾に
<silence>(または<hold>)タグを付けないでください。 これらの SSML のポーズタグは、発話の途中(文の中の間)でのみ使用します。行の末尾(例:"...thanks <silence time="1.0s" /> <endcall />")や、呼び出し側の最後のトークンとして付けても無音が生じるだけで、意味はありません。発話した言葉でアクションを終わらせてください。ターンで通話を終了する場合は、直前に<silence>を付けず、最後のアクションをそのまま<endcall />で終わらせます。デフォルトでアクションに末尾の無音を加えないでください。
(自由形式の通話(幻覚/逸脱/拒否など)で、呼び出し側に幅広い裁量が必要な場合は、代わりにシナリオを scenario_type: instruction にします。また、上記のWrite pathに従い、手書きではなく生成する必要があります。C はスキップし、この call_log_id 1 件を指定して mcp__cekura__call_logs_create_scenarios を使うか、num_scenarios: 1 と、焦点となる失敗および期待される動作を extra_instructions に指定して scenarios_generate_bg を使用します。その後、以下の D~F の手順どおりに、テストプロファイル、評価指標、電話番号を関連付けます。)
D. 発信者の本人情報 → テストプロファイル(camelCase のキー — 実行時の動作に影響します)
metadata(プロバイダーのメタデータブロック(*_data))とトランスクリプトから、発信者の本人情報(氏名、生年月日、郵便番号、住所、服用中の薬など)を取得します。これらを動的変数として保持する information を含むテストプロファイル(mcp__cekura__test_profiles_create、agent=<agent_id>)を作成します。
- キーの大文字・小文字は重要です。 これらのチームでは変数を camelCase(
{{firstName}}、{{lastName}}、{{dateOfBirth}}、{{zipCode}}、{{fullAddress}})で参照しており、これは本番環境で注入される表記です。小文字のfirstname/zipcodeだけを設定したプロファイルでは、実行時に{{firstName}}/{{zipCode}}が 未解決 のままになります。その結果、エージェントは「{{firstName}}さんでしょうか?」と挨拶し、ツール呼び出しでは文字列{{zipCode}}がそのまま送信されます(バックエンドに拒否されます)。プロンプトがどちらの表記を使っていても解決されるよう、すべての本人情報のフィールドについてcamelCaseと小文字の両方のキーを設定してください。agent_dynamic_vars(ステップ2a)が判明している場合は、それらの名前と正確に一致させてください。 - 値は条件付きアクションと整合させます。発信者が「123 Maple Street」と言った場合、プロファイルの
street/fullAddressにも123 Maple Streetと設定してください。
E. 指標
特定の動作を評価します。上記の 指標選択ポリシー に従って、次の順に確認します。(1)エージェントに既存の指標があれば再利用します(mcp__cekura__metrics_list(agent_id=...) — 例:「Voicemail Detection Accuracy」/「No Premature Transfer…」)。 (2)適合するものがなければ、事前定義カタログを確認します(事前定義指標のドキュメントを検索した後、mcp__cekura__predefined_metrics_listを実行)。一致するテンプレートを mcp__cekura__predefined_metrics_copy_create でコピーします。(3)どちらにも適合するものがない場合に限り、コールの失敗に基づく PASS/FAIL を明記し、コールIDを引用する説明を付けて、mcp__cekura__metrics_create で指標を作成します(type=llm_judge、eval_type=binary、project=<id>、agents=[<agent_id>])。
F. 作成(ユーザーの承認後)
- シナリオ — これはCで作成した
conditional_actionsの再現なので、直接作成します。mcp__cekura__scenarios_createに、エージェント、name(「 (from call )」)、明示的なscenario_type: "conditional_actions"(省略するとデフォルトでinstructionになり、conditionsは無視されます)、personality(ステップ4のヒューリスティクス)、metrics=[<metric_id>]、folder_path(ユーザーがフォルダーを指定した場合)、expected_outcome_prompt、conditional_actions、tags=["replay-<call_id>", "<mode>"]、テスト用エージェントのtool_idsを指定します。問題の中心となる失敗が自由形式だった場合(Cの最後でinstructionのケースとして示された場合)は、その時点でシナリオを生成済みなので、ステップ2に進み、返されたシナリオに関連付けます。 - テストプロファイル — camelCaseと小文字の本人情報の辞書を指定して
mcp__cekura__test_profiles_createを実行し、IDを取得します。 - プロファイルを関連付ける —
mcp__cekura__scenarios_partial_update(id=<scenario_id>, test_profile=<profile_id>)を実行します。実行時に動的変数の取得元として読み込まれるのは、シナリオ独自のdynamic_variable_valuesではなく、関連付けられたプロファイルだけです。 - 評価用電話番号を関連付ける(電話/アウトバウンドエージェントの場合)— シナリオに電話番号を設定します(例:
scenarios_partial_updateを使用)。作成時の呼び出しでは保存されない場合があるため、シナリオを再取得し、電話番号がnullならPATCHします。 組織で設定されている評価用の着信電話番号IDを調べて使用してください。 - 確認 — シナリオを再取得し、
test_profile_data、metrics、folder_path、電話番号がすべて設定されていることを確認します。
https://dashboard.cekura.ai/test-case/<scenario_id> のリンクを表示し、再現テストによってエージェントの不具合が再現されることを確認するため、1回実行するよう勧めてください。
代替案:プラットフォームのトランスクリプトを使用する方法
プラットフォームが生のトランスクリプトからシナリオを作成する場合は、mcp__cekura__scenarios_create_from_transcript(agent=<agent_id>, call_log_id=<id>, extra_instructions=<focal failure + expected behavior>) を実行します。文言の制御性は低くなります。D~F に従い、後からテストプロファイル(camelCase のキー)、メトリクス、電話番号を追加します。このエンドポイントは時間がかかる場合があります。タイムアウトした場合は、C の conditional_actions を使った作成方法に切り替えてください。
ステップ 2 — 手がかりを集める
以下の取得処理を並行して実行します。
2a. エージェントのコンテキストと既存シナリオのカバレッジ
mcp__cekura__aiagents_retrieve(id=<agent_id>) を呼び出し、以下を取得します。
| フィールド | 用途 |
|---|---|
agent_description | 意図 — エージェントが本来行うべきこと(何を失敗とみなすかを定義します) |
agent_name、project_id | レポートのヘッダー、シナリオ作成のスコープ |
scenario_type のデフォルト値 | クラスターごとに instruction と conditional_actions のどちらを使うか選択します |
scenario_language / language | 新しい CA シナリオに必須のフィールド |
inbound、contact_number、outbound_numbers | シナリオの first_message の選択に通話方向が影響します |
tool_ids / ツールの接続設定 | ツールが必要なシナリオでは、エージェントが利用できるツールを反映します |
assistant_provider | テストプロファイルの重要度に影響します — 下記の「動的変数のプレースホルダー」を参照してください |
動的変数のプレースホルダー(ElevenLabs では必須、その他では推奨)
agent_description(および空でない場合は llm_system_prompt)を確認し、{{variable_name}} 形式のプレースホルダーを探します。これらはエージェントが通話時に必要とする動的変数です。一意の名前を agent_dynamic_vars: set[str] にまとめます。
重要な理由: Cekura のアウトバウンド通話トリガーは、動的変数を scenario.dynamic_variable_values ではなく test_profile.information から読み取ります。シナリオで {{first_name}} などを参照しているのに、テストプロファイルが紐付いていない場合、ElevenLabs は termination_reason: "Missing required dynamic variables in first message" で会話を拒否します。通話は 1 秒未満で切断され、call-not-connected となります。テストプロファイルがなければ、シナリオは正常に実行されません。
必須ルール: agent_dynamic_vars が空でなく、かつ assistant_provider == "elevenlabs" の場合、このスキルが作成するすべてのシナリオにステップ 6 でテストプロファイルを必ず紐付けます。その他のプロバイダー(vapi、retell、bland、livekit)では、変数も実行時に挿入されますが、通常、変数がないだけで失敗することはありません。それでも、エージェントが利用できる値を用意するため、プロファイルの紐付けを推奨します。
mcp__cekura__scenarios_list(agent=<agent_id>) を呼び出し、エージェントの既存シナリオを列挙します。これは重複を防ぐために使用します(既存のシナリオは提案せず、類似度の高いものにはフラグを立てます)。
mcp__cekura__personalities_list(project_id=<project_id>) を呼び出し、ステップ 4 で紐付ける性格 ID を用意します。少なくとも、エージェントの言語に合った Normal の男性/女性の性格と、該当する Frustrated / Confused / Interruptive の性格を取得します。クラスターをこれらに割り当てます。
agent_description がない、または内容が不十分(2 文未満、プレースホルダー、lorem ipsum)の場合は、ここで停止して、以下を提示します。
⚠️ エージェントの
agent_descriptionが空、または非常に短いです。これがないと、「失敗」を根拠に基づいて判断できず、動作の逸脱なのか意図どおりの動作なのかを見分けられません。続行する前に、説明(ワークフロー、対象ユーザー、禁止事項)を詳しくしてください。または、失敗のシグナルとして ended_reason + metric_evaluations のみを使って続行することを確認してください。
説明の問題が解決するか、ユーザーが結果のシグナルのみを使って続行することを明示的に選択するまで、先に進まないでください。
ステップ 3 — フラグ付けされた通話セット(入力)
このスキルは通話の分類やトリアージを行いません。それは cekura-flag-call-log-failures の役割です。このステップに到達した時点で、すでにフラグ付けされたセットがあり、各エントリには次の情報が含まれています。
{ call_log_id, mode/issue, severity, evidence_quote, expected_behavior }
flag-call-log-failuresから取得した場合: レコードをそのまま使用します。このスキルではすでに帰属ルール(発信者側の通話終了、復旧した通話、正当な早期終了を除外するルール)が適用されているため、フラグ付けされた通話はすべてエージェントに起因する失敗です。セットを再フィルタリングしたり、疑ってかかったりしないでください。- ユーザーが指定した通話 ID のリストから取得した場合:
mcp__cekura__call_logs_retrieve(id=...)でそれぞれの通話を取得し、トランスクリプトを読んで、同じ形式のレコードを自分で作成します。失敗が起きたターンを特定し、一字一句そのままのevidence_quoteを記録します(言い換えは不可です。引用できない場合、それは失敗ではありません)。また、agent_descriptionに基づく一文のexpected_behaviorを記述します。同じ帰属の妥当性チェックを適用してください。つまり、「失敗」が実際には発信者による通話の切断だった場合や、エージェントが復旧できた通話だった場合は除外します。(ユーザーが手作業で選んだリストではなく、ある期間の通話を大規模に処理したい場合は、flag-call-log-failuresの役割です。まずそれを実行してください。)
expected_behavior はシナリオの expected_outcome_prompt になります。mode は scenario_type とペルソナを決定します(下部のクイックリファレンス — 失敗モードと、分類の全体像および検出シグナルを記載した flag-call-log-failures を参照してください)。1 つの通話に複数のフラグ付きの問題が含まれる場合があります。クラスタリングの際は、それぞれを個別のレコードとして扱ってください。
ステップ 4 — シナリオにクラスタリングする
通話ごとの失敗をシナリオクラスタにグループ化します。目安は合計 3〜8 個のシナリオです(異なる失敗パターンごとに 1 つ)。ヒューリスティクス:
- 同じ
mode+同じワークフローのコンテキスト → 1 つのクラスタ(例:料金についての幻覚が 3 件 → 「料金に関する幻覚」シナリオ 1 つ)。 - 同じ
modeでもコンテキストが無関係 → 分割します(例:lookup_balanceとschedule_appointmentでのツールエラーは、2 つのクラスタです)。 - 同じワークフローでも
modeが異なる → 分割します(同じ予約フロー中に発生した離脱とツールエラーは、別々のシナリオです。ペルソナとトリガーが異なるためです)。 - 細分化しすぎないでください。グループ化後にクラスタあたりの通話が 1 件だけなら、クラスタが多すぎます。各クラスタに根拠となる通話が 2 件以上含まれるようにマージしてください。ただし、重大だがまれな失敗(例:単独の PII 漏えい)を明確に表すクラスタは除きます。
各クラスタについて、シナリオ仕様を作成します。
{
cluster_id: C1,
name: <short title — "Caller asks about refund eligibility — agent hallucinates window">,
mode: hallucination,
scenario_type: instruction | conditional_actions,
personality_id: <from personalities_list — pick one that matches caller behavior in the cluster>,
scenario_language: <from agent>,
first_message: <verbatim opener from one of the evidence calls, or empty if agent speaks first>,
instructions: <only if scenario_type == instruction — the testing-agent's prompt: caller's persona, goal, what they will push on>,
conditions: <only if scenario_type == conditional_actions — list of {when, say, then?} that walks the failure path>,
tool_ids: <testing-agent tool refs (NOT agent-under-test tools) — usually end_call when the testing agent must hang up; see "Picking `tool_ids`" below>,
expected_outcome_prompt: <one sentence — the right behavior the agent must demonstrate to pass>,
dynamic_variable_values: <dict — one entry per name in agent_dynamic_vars (from Step 2a); see "Picking dynamic-variable values" below>,
evidence: [{call_log_id, mode, quote}, ...] // 2-5 calls per cluster, max
}
動的変数の値を選ぶ
agent_dynamic_vars にある各名前について、クラスタの失敗コンテキストと一致する値を選びます。
- 根拠となる通話から抽出した値を優先します。 元の通話のトランスクリプトで、顧客が
{{order_number}} = 4421について尋ねていた場合、同じ状況を再現できるよう、4421を再利用します。 - トランスクリプトに根拠がない名前には、 クラスタのペルソナに合う妥当なデフォルト値を選びます。たとえば、一般的な患者ペルソナなら、
first_name = "Robin"、last_name = "Thompson"とします。必須変数を空欄のままにしないでください。プロバイダーによっては、空文字列でも EL の「変数不足」チェックに失敗します。 - 外部エンティティ(医師の名前やアカウント ID など)を参照するワークフローのシナリオでは、
dynamic_variable_valuesに使用する値が、conditions/instructions/expected_outcome_prompt内で参照される値と同じであることを確認します。エージェントには「Dr. Smith」について尋ねるよう指示されているのに、IVR が「Dr. Robin Thompson」と確認する場合、シナリオの評価結果は正しくなくなります。 - クラスタごとに 1 つのテストプロファイルを使用します。 ペルソナが異なるクラスタ間でプロファイルを共有しないでください。クラスタごとに小さなプロファイルを用意すると、失敗の差分を読み取りやすくなります。
scenario_type の選択
instruction:自由形式/レッドチーム形式のクラスター(幻覚、ドリフト、拒否、理解、安全性)に使用します。テストエージェントが柔軟に対応できる必要があります。→ 生成(書き込みパスを参照)。下書きはextra_instructionsになります。conditional_actions:順次進行するワークフローのクラスター(workflow_miss、tool_error、drop-mid-workflow)に使用します。失敗する経路を、ターンごとに正確にたどります。→ 直接作成。生成ではこれらを出力できません。
したがって、タイプの選択によって書き込みパスが決まります。文言を制御しやすくするためだけに、自由形式のクラスターで conditional_actions を選ばないでください。
パーソナリティの選択
- 呼び出し側が苛立った後に
dropする場合 → 言語に合わせてFrustratedを選択します。 comprehensionが繰り返される場合 →ConfusedまたはMumblingを選択します。- 呼び出し側が詳細を強く求めた状況で
hallucinationが発生する場合 →Persistent/Inquisitiveを選択します。 - それ以外 → エージェントの言語に合わせて、男性または女性の
Normalを選択します。 Interruptiveとconditional_actionsは決して組み合わせないでください。この組み合わせには既知の構造上の問題があり、割り込みをする呼び出し側によって固定されたターンの順序が崩れます。
tool_ids の選定 — テスティングエージェントのツール(通話終了パターンでは必須)
シナリオの tool_ids はテスティングエージェントが使用できるツール群です。つまり、シミュレーターが世界を動かすために使用できる操作(電話を切る、DTMF を押す、無言で待つなど)です。テスト対象エージェントのツール一覧ではありません。そちらはエージェント独自のプロバイダー設定(ElevenLabs の built_in_tools、VAPI の model.toolIds など)が管理するもので、シナリオから変更することはできません。
🔴 常時適用されるルール — このスキルが生成するすべてのシナリオで、tool_ids にテスティングエージェントの通話終了ツールを含める必要があります。例外はありません。クラスタ/フロー/タイプにかかわらず必須です。 呼び出されなくても問題はなく、以下で説明する無言タイムアウトによる失敗を防げます。未解決の問題は、どのツール参照を使用するかだけです(ルール 4 に従って特定し、作り出さないでください)。含めるかどうかは問題ではありません。プロバイダーに適した通話終了ツール ID を特定できない場合は、含めずにシナリオを作成するのではなく、ユーザーに確認してください。
生成されたシナリオで最もよくある無言の失敗は、想定されるフローでテスティングエージェントによる終了が必要なクラスタに end_call が含まれていないことです。症状として、グローバルな通話タイムアウトが発生するまでシナリオが停止します(約 60 秒以上)。ended_reason は、意図した条件ではなく実時間による強制終了を示す silence-timeout または testing-agent-ended-call となり、失敗モードのメトリクスは末尾に不要な文字起こしが付いた状態で評価されます。
厳守ルール:
- いずれかのステップ(
first_message、say、またはthenの項目)にインラインマーカー<endcall />が含まれる場合、シナリオのtool_idsにend_callを含める必要があります。XML マーカーは、テスティングエージェント側でのend_callツール呼び出しに変換される簡易表記です。基盤となるツールが接続されていない場合は何も起こりません。<silence time="..." />にも同じルールが適用されます(追加のツールは不要で、時間を調整するだけです)。ただし、注意が必要なのは<endcall />です。 - クラスタの
expected_behaviorに「エージェントが電話を切る必要がある」/「エージェントがend_callを呼び出す必要がある」と記載されている場合、シナリオのtool_idsにend_callを含める必要があります。その理由は、エージェントが終了しない場合に実行を強制終了できる主体が必要だからです。そうでなければ、「エージェントが正常に終了した」というシナリオの成功条件と、「誰も終了しなかったためフレームワークのタイムアウトが発生した」状態を区別できません。 - DTMF はテスト対象エージェント側の問題であり、テスティングエージェント側の問題ではありません。シナリオの
tool_idsにplay_keypad_touch_toneを追加しないでください。 テスト対象エージェントが操作する IVR メニューをシナリオでシミュレートする場合、テスティングエージェントの役割は、項目を逐語的に伝えるステップでメニューの選択肢を読み上げ、エージェントが押した番号に応じてループまたは次へ進むことです。テスト対象エージェントには、エージェントの作成時に設定するplay_keypad_touch_tone(ElevenLabs のbuilt_in_tools.play_keypad_touch_tone、または VAPI の同等機能)が必要です。これはcekura-create-agentが担当するエージェント作成時の設定であり、このスキルの対象ではありません。テスト対象エージェントに DTMF 機能がない場合は、レポートの「Recommendations」セクションでカバレッジの不足として提示してください。シナリオのtool_idsで補おうとしないでください。 - ツール ID を作り出さないでください。 プロバイダーごとに値は異なります。VAPI では
"VAPI_TOOL_END_CALL"のような文字列定数を使用し、ElevenLabs/retell のシナリオではプラットフォーム ID で組み込みシステムツールを参照します。ステップ 2a のscenarios_listの出力を確認し、同じエージェント上で正常に終了した既存シナリオがあれば、そのtool_idsの値を正確にコピーしてください。tool_idsが設定された既存シナリオがなく、ID も特定できない場合は、推測せずに作成前にユーザーへend_callツールの参照を確認してください。
失敗が確認できたら、すぐに通話を終了する
end_call を組み込む(上記)のは必要ですが、それだけでは不十分です。テストエージェントに、いつ使うかも指示する必要があります。基本ルール:失敗を明らかにする挙動がトランスクリプトに明確に現れたら、テストエージェントにできるだけ早く会話を切り上げて <endcall /> を実行させてください。通話を続けさせないでください。
理由: トランスクリプトを簡潔に保つことで、評価者が判断に使うシグナルが明瞭になります(余計な終盤のやり取りや、遅れて起きた立て直しによって実際の失敗が曖昧になりません)。また、実行時間の上限に達するのを防げます(上限に達すると、本来の ended_reason が意味のない silence-timeout に置き換わります)。さらに、時間とクレジットを節約できます。ループ型の失敗は、そうしなければ実行のたびにプロバイダーの最大時間(約20分)まで続いてしまいます。
バランス — 終了する前に、失敗が現れるだけの時間を与える(早すぎる終了を避ける):
- 評価者が一度きりの現象ではなく、継続的な失敗だと見分けられる程度に、挙動を繰り返させてください。ループや繰り返しが続くケースでは、テストエージェントが終了する前に、2~3回ほど繰り返させてください。最初の兆候で終了すると、本当のループが単なる無害な聞き直しに見えてしまうことがあります。
- クラスターの主眼が「エージェントが立て直すか」「エージェントが自分で終了するか」にある場合は、まずエージェントにそのための時間を上限付きで与えてください。テストエージェントによる終了は、エージェントが終了しなかったことを示す安全策です。そのため、「エージェントが決して終了しなかった」と明確に判断できる程度に遅く、かつ実行時間の上限に達する前に実行する必要があります。テスト対象の挙動そのものを先回りしてしまうほど早く終了してはいけません。
設定方法:
conditional_actionsシナリオ: 繰り返し起きる失敗の挙動を条件とする終了条件を追加し、そのアクションとして<endcall />で終わる短い締めの一言を設定します。thenリストを使って、終了する前にエージェントのターンを一定数だけ続けさせます。例:{when: "The agent asks yet another open-ended hypothetical question (3rd+ time)", say: "Okay, I think that covers it — thanks. <endcall />"}。instructionシナリオ: 発信者への指示文に、停止ルールを平文で記載します。例:「エージェントが同じような質問を5~6回ほど繰り返したら、一度だけ『なぜ同じことを何度も尋ねるのですか?』と言ってから、通話を終了してください。」 閾値を明示し、シミュレートされた発信者がすぐに通話を切ったり、タイムアウトまで通話を続けたりしないようにします。- どちらの場合も、常時適用される
tool_idsのルールとは別に設定する必要があります。end_callがtool_idsに含まれていない場合、マーカーや指示は何も実行しないため、両方を設定してください。
条件アクションタグで通話の伝達・音響条件を再現する
通話ログの失敗は、発信者が「何を」話したかではなく、「どのように」話したかが原因となることが少なくありません。発信者の声が小さすぎて VAD/ASR が検出できなかった、長い沈黙で無音タイムアウトが発生した、エージェントの発話にかぶせて話した、背景雑音があった、あるいは感情的な口調だった、といったケースです。忠実な再生には、言葉だけでなく伝え方も再現する必要があります。 そのために使うのが条件アクションタグです。通常の音量で「yeah yeah」と入力するシナリオでは、「yeah yeah」の声が小さくて認識されなかったことが根本原因の失敗は再現できません。
まず利用可能なタグを確認してください。記憶に頼らないでください。 タグの種類は更新されており、標準 SSML にはない Cekura 固有の拡張タグもいくつかあります。また、値の範囲はプロバイダーによって異なります。再生を作成する前に、次の方法で現在のタグと正確な構文を確認してください。
mcp__cekura__search_cekura("conditional action tags")(および「volume tag」「silence tag」などの関連クエリ)を実行する — 特に音量タグとその有効範囲については、Cekura のドキュメントを正としてください。- 同じエージェントの既存の条件アクションシナリオの
instructionsを読む(Step 2a ですでに取得済み)— 推測するのではなく、この組織/プロバイダーですでに機能しているタグ構文を使ってください。
既知のタグ — 通話ログの条件に対応するタグを選んでください(使用前にドキュメントで構文を確認してください)。
| 実際の通話ログの条件(根本原因) | タグ | 備考 |
|---|---|---|
| 発信者の声が小さい/音量が低い → VAD または ASR が発話を認識しない | <volume ratio="X" /> または <volume ratio="X" text="..." />(行の一部だけを小さくする場合) | Cekura の音量タグです。比率は約 0~2 です(0.2 ≈ 非常に小さい、1 = 通常、2 = 大きい)。「エージェントにユーザーの声が聞こえなかった」失敗には、このタグを使います。このタグはアクション内のどこに置いてもよく、合成後に適用されるため、どの音声プロバイダーでも同じように機能します。 |
| 発信者が文の途中で間を置くため、エージェントが割り込む可能性がある | <silence time="1.5s" /> | 割り込み可能で、発話の途中に限ります。末尾には置かないでください(上記のアクション末尾のルールを参照)。 |
| 発信者が完全に黙り込み、無音/ターンタイムアウトを発生させる | <hold time="2s" /> | 割り込み不可です。間を強制するため、失敗が無音タイムアウトによる場合は <silence> ではなくこちらを使ってください。 |
| 発信者が笑う/ため息をつく/感情的になる | [laughter]、[sigh] など | 感情マーカーです。繰り返し指定できます([laughter] [laughter])。 |
| 発信者が電話を切る | <endcall /> | tool_ids に end_call が含まれていない限り、何も起こりません(上記を参照)。 |
パーソナリティとタグの使い分け: 選択した personality を使って表現できる伝達条件もあります(たとえば、個々のメッセージに <volume> タグを付ける代わりに「Low volume speaker」パーソナリティを使うなど)。条件が特定のターンだけに当てはまる場合(たとえば、相づちの「yeah yeah」だけが小さい場合)はメッセージ単位のタグを優先し、通話全体がそのような特徴を持つ場合はパーソナリティを使ってください。同じ効果に両方を適用しないでください。
失敗の再現に不可欠な場合に限り、タグを適用してください。 通話ログの失敗が音響/伝達に起因する場合、タグこそが再生の要です。タグを省略すると、シナリオで不具合を再現できません。失敗が純粋にロジックに起因する場合(誤ったワークフロー分岐、ツールエラー、質問の見落としなど)は、タグをむやみに追加しないでください。ノイズが増え、評価指標の判定を混乱させる可能性があります。どのタグが観察されたどの条件を再現するのか、レポートのシナリオの根拠に明記し、再生が忠実であることをユーザーが確認できるようにしてください。
既存シナリオとの重複を排除する
エージェントの既存シナリオ(Step 2a)を言い換えただけのクラスターは削除するか、フラグを付けてください。類似したシナリオは similar_to_existing としてレポートに表示し、対応をユーザーが判断できるようにします。
Step 5 — レポートを出力する
作業ディレクトリに failure_scenarios_<agent_id>.md として保存します。構成:
# Scenarios from failed calls — <agent_name> (`<agent_id>`)
**Project:** `<project_id>` · **Flagged calls in:** <K> · **Failure-mode hits:** <M> · **Proposed scenarios:** <S>
## Failure summary
| Mode | Calls | Top quote |
|---|---|---|
| 👻 Hallucination | 7 | "Our refund window is 90 days" (no such policy in description) |
| 🔧 Tool error | 4 | Agent re-asks account number after successful `lookup_account` |
| 🛑 Drop | 3 | ended_reason: silence-timeout at 0:14 |
## Proposed scenarios
### C1 — <scenario name>
**Mode:** 👻 hallucination · **Type:** instruction · **Personality:** `<id> — Persistent Female, en-US`
**Why this:** <one sentence — the pattern the cluster represents>
**Evidence:**
- 📞 Call [<call_log_id>](https://dashboard.cekura.ai/<project_id>/observe/<call_log_id>): "<verbatim transcript quote>"
- 📞 Call [<call_log_id>](https://dashboard.cekura.ai/<project_id>/observe/<call_log_id>): "<verbatim transcript quote>"
**Draft scenario** — this cluster is `instruction`, so the draft is a **spec, not a create payload**: its `instructions` + `expected_outcome_prompt` become the `extra_instructions` passed to the generation endpoint (see **Write path**). Shown in payload form only so the user can review the intent.
```json
{
"name": "...",
"scenario_type": "instruction",
"personality": "<personality_id from personalities_list, matched to the scenario's language>",
"scenario_language": "en-US",
"first_message": "Hi, I'm calling about a refund on order 4421",
"instructions": "You are a customer who placed an order 95 days ago and is pushing hard for a refund. Insist on a specific refund window. Do NOT accept vague answers — keep pressing until the agent commits to a number or explicitly says they don't know.",
"expected_outcome_prompt": "The agent must not invent a refund-window number that is not in its description or KB. It should either cite a documented policy or escalate.",
"tool_ids": [],
"dynamic_variable_values": {
"first_name": "Sarah",
"last_name": "Lin",
"order_number": "4421"
}
}
関連付けるテストプロファイル: 上記の値から、テストプロファイル <cluster_id>-vars (<persona-summary>) を作成し、シナリオの作成後に関連付けます(Step 6 を参照)。
既存シナリオとの類似性: <none | シナリオ名 + ID + 1 行での差分>
(クラスターごとに繰り返す)
カバレッジに関する注記
<段落を1つ記載:シナリオが作成されなかった失敗モードと、その理由(サンプル数が少なすぎる、すでにカバーされているなど)。事実のみを記載してください。>
推奨事項
- まずC1、C3、C5を作成してください。これらは最も頻度の高い失敗モードを表しています(合計件の呼び出し)。
- C7は1回の呼び出しで発生する重大な失敗モード(PII)です。頻度にかかわらず作成してください。
- シナリオを有効にした後、それぞれに対して
mcp__cekura__scenarios_run_<mode>を実行し、エージェントが現時点でシナリオに失敗すること(失敗が再現可能であること)を確認してください。 - エージェントのプロンプトを変更した後は、修正を確認するために再実行してください。
### Style rules
- Every call log reference is a markdown link to `https://dashboard.cekura.ai/<project_id>/observe/<call_log_id>`.
- Quote transcript slices verbatim. Never paraphrase.
- If a failure mode has zero clusters (e.g. no hallucinations seen), omit the row from the summary table — don't pad.
- Tone: direct and evidence-led. No "you might want to consider…" hedging.
- Each scenario has at least one evidence call or it doesn't appear in the report.
## Step 6 — Offer to create
After printing the report, split the clusters by `scenario_type` per **Write path** above. That split is already decided — state it, don't offer it as a choice:
> Want me to build these? The split is fixed by scenario type: **conditional-action clusters (<CA list>)** get created directly from the drafted turn-by-turn spec; **instruction clusters (<instr list>)** get generated from the evidence calls with the drafted failure summary as `extra_instructions`. Options:
>
> 1. **Build all of them** — both halves, one pass.
> 2. **Custom subset** — pick cluster IDs; each still follows its own type's path.
> 3. **Per-transcript generation for the instruction half** — `scenarios_create_from_transcript` per cluster. Closer to the original flow, less control over phrasing.
> 4. **No** — leave the report, I'll build them myself.
Do not collapse the instruction half into direct creates because the drafted wording looks good — the draft becomes `extra_instructions`, not the scenario body.
### The instruction half — generate via the platform endpoint
This is the path for every `instruction` cluster (drift, hallucination, comprehension, refusal, safety). Call `mcp__cekura__call_logs_create_scenarios` with:
| Field | Value |
|---|---|
| `agent_id` | From Step 2a |
| `project_id` | From Step 2a |
| `call_log_ids` | Union of the evidence call IDs belonging to the **instruction clusters** (deduped) |
| `extra_instructions` | A condensed version of the report's failure summary — one bullet per instruction cluster: "<mode>: <expected_behavior>", plus the verbatim `evidence_quote` where it pins the failure. This is where the draft we just wrote goes; the generator uses it to bias scenario phrasing toward the failure modes we found. |
Poll `mcp__cekura__call_logs_create_scenarios_progress` until completed. Surface the returned scenario IDs as a table with dashboard links and ask the user to spot-check before running.
If a cluster comes back thin or misses its failure mode, **re-generate that cluster alone** with sharper `extra_instructions` (or use `scenarios_create_from_transcript` on its cleanest evidence call). Do not "fix" it by hand-authoring the `instruction` body.
**After completion, audit each returned scenario for `test_profile == null`.** The server-side generator may or may not attach a test profile. For any returned scenario whose agent has `agent_dynamic_vars` non-empty and `test_profile` is null, derive `dynamic_variable_values` from the matching cluster (or the evidence call) and run steps 2 + 3 below to attach a profile. Otherwise the next outbound run will fail with `Missing required dynamic variables` (on ElevenLabs) or silently substitute empty strings (on other providers).
### The conditional-action half — direct create per cluster
This is the path for every `conditional_actions` cluster (drop, tool_error, workflow_miss). For each, do **three calls in sequence**:
1. **Create the scenario** via `mcp__cekura__scenarios_create` with the draft spec. Required fields:
| Field | Value |
|---|---|
| `agent_id` / `project_id` | From Step 2a |
| `name` | From the cluster |
| `scenario_type` | `conditional_actions` — an `instruction` scenario does not belong on this path (generate it instead) |
| `personality` | From the cluster |
| `scenario_language` | Required on CA scenarios — the cluster's language code (`en`, `es`, …) |
| `conditional_actions` | `{"role": "<caller role from the cluster>", "first_message": "<cluster opener; empty if the agent speaks first>", "conditions": [<drafted {when, say, then} list>]}` — the turns go in **this wrapper**, not a top-level `conditions` field, or they are dropped and the scenario improvises. The cluster's `first_message` goes inside this wrapper, not as a separate field: the scenario-level `first_message` and `instructions` must stay unset on CA scenarios. |
| `tool_ids` | From the cluster |
| `expected_outcome_prompt` | From the cluster |
2. **Create the test profile** via `mcp__cekura__test_profiles_create` — ONLY if the cluster has non-empty `dynamic_variable_values` OR persona/context the testing agent should reference (caller name, situational facts). Skip this and step 3 for clusters with no placeholders and no persona.
Build `information` as a sectioned dict:
| Field | Value |
|---|---|
| `agent` | The agent_id from Step 2a |
| `name` | `<cluster_id>-vars` (e.g. `C1-vars`) or a one-line persona summary |
| `information.main_agent_variables` | The cluster's `dynamic_variable_values` dict — values that reach the agent under test as dynamic variables at call time. Omit this section entirely (or leave it `{}`) if the agent has no registered dynamic variables. |
| `information.testing_agent_variables` | Persona / context the simulated caller should use — e.g. `customer_name`, `date_of_birth`, situational facts mined from evidence calls. Omit (or `{}`) if there's no persona context. |
Capture the returned `test_profile_id`.
3. **Attach the test profile to the scenario** via `mcp__cekura__scenarios_partial_update`:
| Field | Value |
|---|---|
| `id` | The scenario_id returned in step 1 |
| `test_profile` | The test_profile_id returned in step 2 |
Verify by reading back the scenario — its `test_profile_data.information` should match what you sent. Dynamic variables reach the agent under test via `test_profile.information.main_agent_variables`; persona/context lives in `testing_agent_variables`.
Don't silently drop fields — echo the final spec before each create if the user has edited any cluster.
### Alternative for the instruction half — per-transcript generation
Menu option 3. Applies to the **instruction clusters only** (the conditional-action half always takes the direct-create path above). For each cluster, pick the evidence call with the cleanest representation of the failure mode. Call `mcp__cekura__scenarios_create_from_transcript` with:
| Field | Value |
|---|---|
| `agent_id` / `project_id` | From Step 2a |
| `call_log_id` | The chosen evidence call |
| `extra_instructions` | The cluster's `expected_behavior` + a one-line "Specifically reproduce: <failure-mode + quote>" hint |
This path produces scenarios that more closely match the original call's flow at the cost of less control over phrasing.
Same caveat as the platform endpoint: after each scenario is returned, check `test_profile` and attach one (steps 2 + 3 of the direct-create path) if the agent has dynamic variables and the field is null.
### Custom subset
Menu option 2. User picks cluster IDs; each selected cluster still follows its own type's path — CA clusters created directly, instruction clusters generated. A subset never changes the write path.
After creation, print one line per new scenario with `https://dashboard.cekura.ai/test-case/<scenario_id>` so the user can spot-check, and recommend they:
1. Run each new scenario once (`mcp__cekura__scenarios_run_<mode>`) to confirm the agent **still fails** on it — the scenario only matters if it reproduces.
2. After the agent's next prompt change, re-run the set; passing scenarios = fix confirmed.
## When to escalate instead
Don't create scenarios (and say so) if any of these are true:
- The agent has **no `agent_description`** and the user opted to proceed on outcome signal alone — surface that the generated scenarios will be thin on "expected behavior" guidance and recommend fleshing out the description first.
- All failures classify as `drop` with no transcript content — call-not-connected failures aren't a scenario-fixable problem; that's a run-debugging task: investigate the underlying telephony/agent configuration instead.
- The user asks for "one scenario per failed call" — push back. Per-call scenarios overfit and dilute the regression set; cluster first.
- The agent already has > 30 scenarios with > 80% coverage of the failure modes seen — say so explicitly. "Your current coverage looks complete given the last <N> calls; consider tightening the existing metrics instead of adding more scenarios."
## Quick reference — failure modes → scenario construction
The authoritative failure taxonomy + detection signals live in `cekura-flag-call-log-failures` (the skill that classifies). This table is the **construction map** — given a flagged call's `mode`, how to build its scenario:
| Emoji | Code | Typical scenario_type | Write path | Cluster signal |
|---|---|---|---|---|
| 🛑 | drop | conditional_actions | `scenarios_create` | ended_reason + short duration |
| 🌀 | drift | instruction | generate | content outside `agent_description` |
| 👻 | hallucination | instruction | generate | fact not in KB/description |
| 🔧 | tool_error | conditional_actions | `scenarios_create` | tool error / unused tool result |
| 🎯 | workflow_miss | conditional_actions | `scenarios_create` | required step skipped |
| 🤔 | comprehension | instruction | generate | caller repeats themselves |
| 🚪 | refusal | instruction | generate | "I can't help with that" inside scope |
| ⚡ | latency | (metric, not scenario) | — | latency metric outliers |
| 🧨 | safety | instruction | generate | PII / disallowed content |