exploring-scouts について
PostHog プロジェクトの Signals scout の設定、実行状況、出力を読み取り専用の MCP ツールで調べるためのスキルです。レポート、構造化レコード、実行メタデータ、出力のない実行の読み解き方を説明します。
主な機能
- 01scout の設定とスケジュールの一覧
- 02実行状態・要約・レポートの確認
- 03実行間メモリーとチームのメモの検索
- 04構造化出力と実行メタデータの解釈
- 05成果のない実行と出力経路の特定
活用シーン
- 01プロジェクトで有効な scout の把握
- 02scout の実行とレポートの追跡
- 03プロンプト変更前後の実行比較
- 04scout が記録を残さなかった理由の調査
MCP 対応
読み取り専用の PostHog MCP ツールで、プロジェクト情報、scout の設定と実行、メモリー、ノート、受信トレイのレポートを調べます。書き込み操作は扱いません。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ posthog/ ai-plugin --skill exploring-scoutsインストール後、Claude Code で/exploring-scoutsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/assessing-performance.mdscout-data-model.mdscripts/assess_health.pyfleet_survey.pyrender_run_report.py詳細
翻訳後に原文が更新されています。最新の内容は原文をご確認ください。
Signals スカウトの探索
スカウトは、設定された間隔で自動的に起動し、1 つの PostHog プロジェクトを調べ、実際に提示する価値があるものを判断して、Signals の受信トレイにレポートとして書き込むか、何もない状態で終了するスケジュール実行エージェントです(これも正当な結果です)。
PostHog には、標準スカウト群が用意されています。複数のプロダクトを横断する汎用スカウト(signals-scout-general)に加え、各領域に特化したスカウト(エラートラッキング、ログ、AI オブザーバビリティ、実験、フィーチャーフラグ、セッションリプレイ、ウェブ分析、アンケートなど)があります。
プロジェクトには標準スカウト群に加えてカスタムスカウトがある場合もあります。チームが作成した signals-scout-* スキル(例:-brand-mentions、-mcp-feedback)もここに表示されるため、スカウトの一覧が固定だとは考えないでください。プロジェクトの正式な一覧は scout-config-list で確認できます。
(注意点として、作成したばかりのスカウトは、コーディネーターの次回の実行で自動登録されるか、書き込み側の scout-config-create を使って誰かが登録するまで、設定行がありません。そのため、新しいスカウトが一覧に一時的に表示されないことがあります。)
このスキルでは、すべて読み取り専用の MCP ツールを通じて、プロジェクトのスカウトが何をしているか、どのような成果を上げているかを把握し、調べることができます。
これは、スカウトの作成と調整方法を説明する authoring-scouts スキル、およびスカウトがレポートを届ける受信トレイを扱う inbox-exploration スキルに対応する、オブザーバビリティ向けのスキルです。
(スカウトツールは最近 signals-scout-* から scout-* に名称変更されました。scout-* が不明なツールとして返された場合、サーバーでは旧名称の signals-scout-* で引き続き公開されている可能性があります。ツールカタログを検索し、返された名称を呼び出してください。)
スカウトの出力は、1 対 1 で作成される受信箱レポートです。 スカウトは allowed_tools に emit_report / edit_report を指定し、受信箱レポートを直接作成または編集します。実行の出力は emitted_report_ids(作成したレポート)と edited_report_ids(更新したレポート)に表示されます。
実行の行には、emitted_count / emitted_finding_ids も含まれています。これらは、非推奨のシグナル出力チャネル(パイプラインが統合した、弱い emit_signal の調査結果)から引き継がれたレガシーフィールドです。レポートチャネルのスカウトでは、実りのある実行であっても値は 0 / 空のままです。ゼロ以外の集計値は、その実行がまだレガシーチャネルを使用しているスカウト(古いカスタムスカウト、またはまだ移行されていない標準スカウト)によるものだという意味で、その実行の実際の出力であり、ノイズではありません。スカウトのチャネルが不明な場合は、skill-get で allowed_tools を確認してください。
emitted_count: 0 を「何もしなかった」と解釈しないでください。まずレポート関連の列と実行サマリーを確認してください。
設定に structured_output_schema があるスカウトには、レポートに加えて 3 つ目の出力チャネルがあります。プロジェクト内で $scout_structured_output イベントとして記録される、スキーマ検証済みの測定レコードです(トップレベルのペイロードキーのうち スカラー のものだけが output_<key> プロパティにフラット化されます。オブジェクトと配列のフィールドは完全な output プロパティ内にのみ保持されるため、output_<key> がないからといって値がないわけではありません。subject は評価対象のエンティティを示します)。実行行の列として記録されるわけではありません。
イベントが正確な実態を示します。metadata.derived.has_structured_output は、実行で少なくとも 1 つのバッチが受理されたことを示します。実行ごとの簡易確認には使えますが、配信の確認にはなりません(まれに、受理後のキャプチャに失敗すると、イベントが少数しか残らない、またはまったく残らない状態でも true になります)。レコード数が重要な場合は、イベントを数えてください。イベントの形式については、references/scout-data-model.md を参照してください。
PostHog が提供するスカウトのうち、系列を記録するのは signals-scout-mcp-tool-calls です。MCP トラフィックを検出した実行はすべて、レポートを作成するかどうかにかかわらず、MCP ツールの健全性に関するカテゴリ別の集計と、ツールごとのセッション共有率の行を記録します。そのため、健全なカテゴリと未測定のカテゴリを区別できます。
レコードがないことだけでは、チャネルが壊れているとは限りません。
最近の $mcp_tool_call イベントがないプロジェクトでの実行は早期に停止して何も記録せず、ドライランのスカウト(emit がオフ)には記録先がありません。
チャネルが壊れていると判断する前に、実行サマリー、not-in-use:mcp_analytics のスクラッチパッド項目、設定の emit を確認してください。
event = '$scout_structured_output' と properties.skill_name = 'signals-scout-mcp-tool-calls' を指定して見つけてください。グラフとアラートのレシピは、スカウト自身の references/metrics-dashboard.md にあります。
各実行には metadata マップも含まれます。トップレベルには、実行に与えられた指示を示す来歴情報として harness_prompt_version / report_channel(none、emit、edit、または both)/ skill_origin / github_guidance があります。また、ゲートやピンによってデフォルトが上書きされた場合に限り、ルーティングキー(model / runtime_adapter / reasoning_effort / service_tier)が含まれます。metadata.derived の下には、実行の終了時にハーネスが計算するブール値(has_emit_report、has_edit_report、has_self_improvement、has_chart、has_self_validation、has_structured_output、has_not_in_use_closeout)があります。
実行を比較する場合(プロンプト変更の前後、あるモデルと別のモデルなど)は、まず 4 つすべての来歴値でセグメント分けしてください。harness_prompt_version、report_channel、skill_origin、github_guidance のいずれかが異なる実行には異なる指示が与えられているため、同条件の母集団ではありません。このフィールドが導入される前の実行には、これらの値がありません。来歴情報が欠落している場合は不明として扱い、比較対象にまとめず除外してください。
「この実行はどのようなものだったか」という質問(自己改善レポートを作成したか、後続キューを検証したかなど)には、散文のサマリーを解析するのではなく derived を確認してください。実行が実際に行ったことからサーバー側で計算されるため、実行自体の出力と食い違うことはありません。ただし例外が 1 つあります。has_structured_output は実行が受理したバッチを追跡するもので、配信されたイベントを追跡するものではありません。そのため、これだけは後続のレコードが少数しかない、またはまったくない状態でも true になることがあります。前述のとおり、イベントを数えてください。derived マップ自体がない場合は「すべて false」ではなく不明です。実行がこのフィールドの導入前だった、終了前に失敗した、または記録に失敗した可能性があります。導入前の実行の多くにはマップがないため、マップがないことを調査結果として解釈しないでください。
無駄な実行を見つけるには、has_not_in_use_closeout を確認します。実行が not-in-use: のスクラッチパッド項目を書き込み(簡易クローズアウトで対象の製品がオフだと判明し)、レポート、編集、検出事項、または構造化出力の記録を生成しなかった場合、この値は true になります。ハーネスは、サンドボックストークンを使って書き込みを行った実行に対してカウントするため、同じチームの別のスカウトによるクローズアウトは、この実行の実績にはなりません。確認した結果、何も見つからなかった静かな実行では false になります。スカウトの無駄な実行率は、このフラグが true である、確定済みの実行(derived マップを持つ実行)の割合です。これを使って、次に事前チェックで実行を制限するスカウトの優先順位を決め、導入した事前チェックによって率がゼロに近づくことを確認します。このフラグの導入前に行われた実行には has_not_in_use_closeout キーがないため、false として数えるのではなく除外してください。
フリートについて確認できる項目は6つあり、それぞれに専用のツールがあります。
| 確認したいこと | ツール | 確認できる内容 |
|---|---|---|
| どのスカウトが、どのくらいの頻度で、どのような設定で実行されるか | scout-config-list | スカウトごとに1行:スケジュール(run_interval_minutes または run_cron_schedule)、enabled、status / pause_reason、emit、output_destinations、write_scopes、mcp_gateway_server_ids、last_run_at、consecutive_failure_count、description、scout_origin、owners、tags |
| スカウトが実際に行ったこと(実行ごと) | scout-runs-list / -retrieve | 実行ごとのステータス、タイミング、実行終了時の要約、emitted_report_ids / edited_report_ids、失敗した実行の error / failure_reason、ディープリンク。skill_name で絞り込み可能 |
| 実行を通じてフリートが学習したこと | scout-scratchpad-search | チームごとに保持される永続メモリ(ベースライン、ノイズ、許可リスト) |
| チームがフリートに伝えたこと | scout-notes-list | 人間やエージェントがスカウトに残した指示メモ(スカウトごと、またはフリート全体。新しい順) |
| 実行が作成または編集したレポート | 実行行そのもの | emitted_report_ids / edited_report_ids。各 ID は inbox-reports-retrieve で取得 |
| スカウトがユーザーに提示した内容 | inbox-reports-list | スカウトが作成したレポート(ユーザーに表示される内容)。1つのスカウトの場合は scout: "<skill_name>"、フリート全体の場合は source_product: "signals_scout" |
scout-config-list は tags パラメーター(カンマ区切り)を受け取り、指定したラベルのいずれかを持つスカウトに対象を絞り込めます。たとえば、対象領域を限定した質問に答える場合、大規模なフリートでは tags=revenue のように指定すると便利です。 | ||
scout-runs-list は skill_name(および任意で skill_version)を受け取り、取得結果を1つのスカウトに絞り込めます。フリート全体をページ送りして探すことなく、単一のスカウトに関する質問に答える際の通常の方法です。 |
状況を把握するためのツールは scout-project-profile-get です。すべてのスカウトがコールドスタート時に参照する、「このプロジェクトについて何が事実か」を示す決定的なスナップショットです。
スカウトが何も見つけられなかった場合、通常はこれが原因です。
出力の処理:ファイルへの退避を想定する
これらのツールのうち2つ、scout-runs-list と、特に tasks-runs-session-logs-retrieve は、MCP クライアントのトークン予算を超過し、ペイロードがファイルに退避されることがよくあります。
これは通常の動作であり、エラーではありません。
呼び出しに失敗してから気づくのではなく、事前に備えてください。
scout-runs-listではlimitを小さく(約10~15) 保ちます。 各行には長い文章のsummaryが含まれ、実行結果はフリート全体を対象に新しい順で返されるため、控えめな件数でも大きな結果になります。- セッションログはもともと大容量です。 1回の実行のログは、数百KBから数MBになります。
call --jsonで取得します(保存されるファイルが整形済みテキスト形式ではなく、jqで処理可能な実際の JSON になります)。インラインで読むのではなく、保存したファイルをjqやスクリプトで読み取ってください。 - セッションログを手作業で解析しないでください。 同梱の
scripts/が復元処理を行います。詳しくは以下を参照してください。
まず確認:フリートはセットアップされていますか?
プロジェクトにスカウトがいるとは限りません。
フリートが稼働するのは、signals-scout フィーチャーフラグが有効なチームのみです。また、プロジェクトには設定がない場合、スカウトがすべて無効になっている場合、またはドライランのまま停止しているスカウトがある場合があります。
ユーザーからセッション中に初めてスカウトについて尋ねられたときは、まずこれを実行してください。
scout-config-list
結果を次の3つのケースに照らして確認します。
設定リストはページネーションされず、{ results: [...] }(配列のみ)として返されます。count フィールドはありません。
結果を次の3つのケースに照らして確認します。
-
空(
results: []) — スカウトは登録されていません。 このプロジェクトはスカウトフリートに登録されていない(または、まだ一度も実行されていない)状態です。 そのまま明確に伝え、実行履歴を探し回らないでください。 活動状況を作り上げるのではなく、Signals のスカウト設定または PostHog Desktop のオンボーディングを案内してください。 -
設定はあるが、すべて
enabled: false— フリートは登録されていますが、一時停止中です。 何も実行されていません。 どのスカウトが存在し、すべてオフになっていることを伝え、誰がそれぞれをオフにしたのかも説明してください。この情報はstatusに含まれます。paused_by_userは人(または起動時の初期設定)によってオフにされたことを意味し、paused_by_systemはpause_reasonに原因(no_output/ignored/repeated_failures)が記録された自動一時停止を意味します。 どちらの場合も、scout-config-updateを使ってenabled: trueにすると再開します。repeated_failuresによる一時停止は、失敗ブレーカーによるものです。スケジュール実行の連続失敗(consecutive_failure_count。手動実行とワークフロー起動の実行は含みません)が、スケジュールを12時間に収めるための回数を1回超えています。この回数は5~25に制限されます(日次:5、ローリング方式の毎時間隔:13、毎時のcron:15。cronの枠は、夏時間の変化に備えて余裕を持たせた時間枠で数えます)。これはハーフオープン状態のため、コーディネーターは1日1回スカウトを試験実行し、問題なく実行できれば再開します(ただし、プロジェクトが有効なスカウトの上限に達している場合は、試験実行が成功しても行は一時停止のままです)。何が失敗し続けていたのかを伝えるには、最新の実行のfailure_reasonを確認してください。 -
enabled: trueが1つ以上ある — フリートは登録されており、そのスカウトは実行を許可されています。 有効なスカウトごとに、実行頻度(設定されていればrun_cron_schedule、そうでなければrun_interval_minutes。cron が優先されます)、emit(false は ドライランで、実行はされますがインボックスには何も書き込みません)、last_run_atを記載してください。statusがpending_pauseの場合、スカウトは引き続き実行されますが、システムによって間もなく一時停止するようフラグが設定されています(原因はpause_reasonにあります)。設定を編集すると警告は解除されます。 「稼働中」と報告する前に、1つ注意点があります。実行はenabledではなく、signals-scoutフィーチャーフラグによって制御されます。 登録後にフラグの対象から外されたプロジェクトには、enabled: trueの行が残りますが、コーディネーターはそのプロジェクトの実行を計画しなくなります。そのため、有効なスカウトのlast_run_atが古いまま、またはnullの場合、通常はスカウトがアイドル状態なのではなく、プロジェクトが対象外になったことを意味します。last_run_atは ディスパッチ 時刻であり、実行された証拠ではありません。 コーディネーターは、実行時刻になったスカウトの子ワークフローを キューに登録 した時点でlast_run_atを更新します。ワーカーが実行を開始するより前です。 子ワークフローのディスパッチは非同期で行われるため、ワーカーが過負荷または停止中の場合、子ワークフローはキューに入ったまま実際の実行に至らないことがあります。それでもlast_run_atはティックごとに更新され続けます。 したがって、last_run_atが最近の時刻であることが意味するのは「このティックでディスパッチされた」であり、「実際に実行中である」ではありません。 稼働状況を判断するための信頼できる情報は、設定のタイムスタンプではなく、scout-runs-listにある最新の実際の 実行行 です。 両者を照合してください。last_run_atが新しい(数分前)にもかかわらず、そのスカウトのrun_interval_minutesを大幅に超えても実行行が現れない場合、フリートは ディスパッチしているものの、実行していません。ワーカーが滞留または停止しているか、実行が取り残されている状態であり、実際に稼働しているスカウトではなく、信頼性に関わる問題です。last_run_atだけを根拠に「実行中」と報告しないでください。 事前チェックでスキップされた場合も、実行レコードがないままlast_run_atは新しくなります。 スカウトに事前チェックが設定されていて、クエリで新しいものが見つからない場合、スケジュール実行は実行レコード、サンドボックス、モデル呼び出しを作成する前にスキップされます。 そのため、実行が見当たらないことを失敗と判断する前に、設定行のeffective_precheck_queryとprecheck_query_sourceを確認してください。ソースがoffの場合、事前チェックではこの空白期間を説明できません。 それ以外の場合は、設定のidだけを指定してscout-config-precheck-testを実行してください。would_run: falseなら、次回のスケジュール実行もスキップされるため、この空白期間は想定どおりです。 ドライランはユーザー自身として実行されますが、スケジュールチェックはスカウトの実行ユーザーとして実行されるため、クエリがアクセス範囲の制限されたテーブルを読み取る場合、結果が異なることがあります。 スキップによってわかるのは、クエリで新しいものが見つからなかったことだけです。スカウトが正常に動作していることを示すものではありません。 事前チェックのレシピとルールはauthoring-scouts(スケジュール事前チェックのリファレンス)に記載されています。
enabled: true でも emit: false のスカウトは、「スカウトが何もしていない」という誤解の最も一般的な原因です。スカウトは各実行時に動作して推論していますが、まだレポートの投稿が許可されていないだけです。
スカウトについて報告する際は、必ず emit の状態を明示してください。
設定、実行、スクラッチパッドの各エントリーに含まれるすべてのフィールド、実行ステータスの値、各要素の関連付けについては、references/scout-data-model.md を参照してください。
ワークフロー:スカウト群を調査する
「どんなスカウトがあるか/何をしているか?」という質問には、まず scout-config-list を実行し、続いて各スカウトの最新の実行を追加で確認して、設定だけでなく稼働状況もわかるようにします。
scout-config-list— スカウト一覧を取得します。scout-runs-listを少なめのlimitで一度実行し、skill_nameごとに最新の実行を選びます(実行結果はスカウト群全体で新しい順に返されるため、通常は一度の呼び出しで全員分を確認できます)。そのページに表示されないスカウトについては、skill_nameを指定してもう一度呼び出します。statusと、実行からどれくらい経過したかを報告します。
ユーザーが一覧しやすい表にまとめ、スカウト、実行間隔、状態、最終実行、最終結果を示します。また、異常な点(未実行、直近の実行でエラー、長期間ドライランのままなど)があれば指摘します。
ワークフロー:1つのスカウトを最初から最後まで理解する
「エラートラッキングスカウトはどのように動作していますか/調子はどうですか?」
- 設定を読む —
scout-config-listでsignals-scout-error-trackingの行を見つけ、スケジュール、動作方針、最終実行を確認します。 - 本文を読む —
posthog:skill-get {"skill_name": "signals-scout-error-tracking"}を実行すると、チームが実際に使用している指示一式が返されます(標準の既定値の場合もあれば、編集されて標準から変わった行の場合もあります)。 これは毎回の実行でエージェントに指示される内容、つまりシグナルとノイズを見分ける基準、探索するパターン、除外条件です。 スカウトがそのように動作する「理由」を理解するには、本文を読んでください。 - 最近の実行を読む:
scout-runs-listのskill_nameにスカウトを指定します(トピックについて概要を検索するにはtextを追加します)。 各実行の最後にあるsummaryは、スカウトが調査した内容と判断した内容についての説明です。失敗した実行には、代わりにfailure_reasonが記録されます。 - 記憶した内容を読む —
scout-scratchpad-searchを使用します(下記参照)。 スカウトが書き込んだメモリ項目から、このプロジェクトについて内部に取り込んだベースラインとノイズがわかります。 - 与えられた指示を読む —
scout-notes-list {"skill_name": "signals-scout-error-tracking"}を実行すると、人間がこのスカウトに残した誘導メモと、全体に適用される一般的なメモが返されます。これらは実行時に前提コンテキストとして読み込まれるメモそのものです。 各メモにはoriginがあり、直接残されたメモはhuman、受信箱によって自動的に転送された派生メモは、その種類に応じてreport_dismissal(却下/スヌーズのメモ)、report_discussion(レポートの「Discuss」ボックスに入力された質問)、report_feedback(星評価とともに残されたメモ)、report_reviewer_correction(誰かが推奨レビュアーを追加または削除したもの)です。派生メモは約30日後に期限切れになります。また、レポートの読み取り権限(task:read)がない呼び出し元には、レポートの内容が引用されているため表示されません。そのため、signal_scout:readだけを持つ認証情報では、人間が残したメモのみが表示されます。pipeline:report-research宛てのメモは、このスカウトではなくレポートパイプラインの調査段階を誘導するため、ここには表示されません。 スキルの編集やスクラッチパッドの項目に原因をたどれない動作の変化は、多くの場合、メモに原因があります。 観察ではなく、メモを使ってスカウトを「誘導」するよう依頼された場合は、メモ機能の書き込み側を扱うauthoring-scoutsスキルに引き継いでください。
ワークフロー:最近の実行履歴を読む
scout-runs-list は、フリート全体の最新の実行履歴を新しい順に返します(最大100件)。
「最近何があった?」に答えるときに使います。
- 1つのスカウトに絞り込むには
skill_nameを使います(1つのボディバージョンの実行履歴に絞る場合はskill_versionも指定します)。質問が単一のスカウトについての場合は、まずこの方法で絞り込みます。 - 期間を指定するには
date_from/date_toを使います(ISO-8601形式。created_atに対して開始日時は含み、終了日時は含みません)。 さらに前の履歴を見るには、より早いdate_toを指定して遡ります。 - サマリーを検索するには
textを使います。各実行の終了時のsummaryに対する、大文字と小文字を区別しない部分一致検索です。 ヘッドレススカウトが重複を排除する際に使うほか、「チェックアウトエラーの急増をすでに調査した実行はあるか?」といった履歴の検索にも使えます。 - 出力で絞り込むには
emittedを使います。emitted=trueは、少なくとも1件のレポートを作成した実行(またはレガシー実行の場合は、調査結果を出力した実行)のみを返し、emitted=falseは何も作成しなかった実行のみを返します。 文章を解析せずに「実際に何かを書き込んだ実行はどれか?」に答えるための直接的な方法です。 注意点として、既存のレポートを編集しただけの実行はemitted=trueには該当しません。そのような実行を何もしていないと判断する前に、edited_report_idsを確認してください。
各サマリー行には、run_id、skill_name、skill_version、status、started_at、completed_at、emitted_report_ids/edited_report_ids(実行が作成または編集したレポート、つまり出力)、emitted_count/emitted_finding_ids(レガシーのシグナルチャネルの件数。現行のスカウトでは 0/空)、task_url(Tasks UI の完全なトランスクリプトへのディープリンク)、summary の文章、そして正常に完了しなかった実行の場合は error(TaskRun の完全なエラー)と failure_reason(そこから導出した簡潔な一文)が含まれます。
ユーザーに説明するときは、まず summary を伝えてください。これはスカウト自身による平易な言葉での締めくくりです。また、詳細な推論を確認できるよう、必ず task_url も案内してください。
ワークフロー:単一の実行履歴を詳しく調べる
ユーザーが1つの実行履歴の全容を知りたい場合(または run id/Tasks URL を貼り付けた場合):
scout-runs-retrieve
{ "id": "<uuid>" }
フィールド名が異なる点に注意してください。scout-runs-list は各実行の ID を run_id として返しますが、scout-runs-retrieve では id として受け取ります。
run_id の値を id に渡してください。
実行履歴の全容が返されます。内容は、status、started_at/completed_at(これらから所要時間を算出)、skill_name/skill_version(実行されたものとそのボディバージョン)、実行終了時の summary、emitted_report_ids/edited_report_ids、metadata、および task_url です。
トランスクリプト、つまり実際のツール呼び出しと推論は、このペイロードではなく task_url の先にある Tasks UI にあります。すべての手順を確認したい場合は、そのリンクをユーザーに案内してください。
失敗した実行では summary は空です。まず failure_reason(1行の診断。実行時間の上限によるタイムアウト、エラーを繰り返したツール、起動しなかったサンドボックスなど)を確認し、次に TaskRun の完全なエラーテキストである error を確認してください。
この2つのフィールドだけで「なぜ失敗したのか」という質問の大半に答えられます。失敗に至る呼び出しの順序を調べる必要がある場合は、トランスクリプトを確認してください。
UI を開く必要はありません。tasks-runs-session-logs-retrieve は、その実行のセッションログ(すべてのツール呼び出し、メッセージ、推論の手順)をデータとして返します。失敗の診断や、会話から離れずに実行内容を正確にたどりたいときに便利です。
実行の task_run_id を id として渡し、task_id も渡してください(どちらも実行行にあります)。
生のストリームは数百 KB から数 MB と大きく、インライン表示ではあふれてしまうため、call --json で取得してファイルに出力し、手作業で解析するのではなく、scripts/render_run_report.py に渡してください。
ツールはデフォルトで 100 件、1 回の呼び出しで最大 5000 件を返します。また、ページネーション状態は本文に含まれないため、limit: 5000 を指定し、前のページで実際に返された件数分(limit ではありません)だけ offset を進めながら、ページが空になるまで繰り返してください。その後、レンダリングの前にページを連結します。ページが短くても終わりではありません。バイト数の上限に達するとページが早く閉じることもあり、その後に limit 分進めると残りの項目を飛ばしてしまいます。そのため、デフォルトの 1 ページだけでは失敗の末尾が欠落することがあります。
⚠️ 絞り込むために exclude_types: "tool_call_update,…" を使わないでください。 ストリームの大部分を tool_call_update の増分チャンクが占めるため、そうしたくなるかもしれません。しかし、各ツールの実際の入力はそれらのチャンクにしかありません。ベースとなる tool_call イベントの rawInput は空で、ストリーミングされる更新が入力(および最終的な rawOutput)をトークンごとに組み立てます。
これらを除外すると、ツールの_名前_は分かっても、調査エージェントが実際に何を照会したのかは分かりません。
ログをすべて取得し、スクリプトに各呼び出しを再構成させてください(toolCallId でグループ化し、最も情報量の多い rawInput を保持して、完了時の rawOutput/status を付与します)。
実行によって何かが書き込まれたかどうかは、第一級のフィールドである emitted_report_ids/edited_report_ids で確認できます。 emitted_report_ids が空でなければ、実行が emit_report を使って作成したレポートが順番に列挙されます。edited_report_ids には、edit_report で変更したレポートが列挙されます(変更対象は調査エージェントが作成したものに限らず、どのインボックスレポートでもかまいません)。
生産的な実行では通常、ここに ID が 1 つあり、Report authored: <id> のような要約が含まれます。レポート自体を読むには、inbox-reports-retrieve で ID を解決してください。
出力を判定するために、文章の summary を解析しないでください。「P1 はすでに報告済み……再提出しなかった」のような文言は_以前の_実行について述べているため、要約内の部分一致では信頼できません。ID 列が正確な集計値です。
「レポート ID がない」ことと「何も書かなかった」ことが一致しない調査エージェントの種類が 1 つあります。測定調査エージェントは、通常の実行ではレポートを作成しません。出力が記録ストリームであるためです。そのため、このような実行を空と判定する前に、metadata.derived.has_structured_output とイベント自体を確認してください。
レガシー実行:emitted_count/emitted_finding_ids。 非推奨のシグナル出力チャネルからの実行(allowed_tools のオプトインがない調査エージェント。古いカスタム調査エージェント、またはまだ移行されていない正規の調査エージェント)では、出力は代わりに emitted_count 件の弱いファインディングとして集計されます。各 finding_id は、source_id = run:<run_id>:finding:<finding_id> を持つ Signal に対応します。
そのような実行に限り、scout-runs-emission-reports に run_id を渡すと、出力された各ファインディングを、そのシグナルがグループ化されたインボックスレポートに対応付けます(表面化しなかった場合は null)。
レポートチャネルの調査エージェントでは、これらのフィールドは常に 0/空です。これらを基に診断しないでください。
フィールドの詳細については、references/scout-data-model.md を参照してください。
status が complete で、要約が「ベースラインの状態で、報告事項なし」のように何も見つからなかった実行は、失敗ではなく健全な結果です。ほとんどの実行は何も報告せずに終了するはずです。
何も見つからないまま終了する実行が続いても、フリートが壊れているのではなく、きちんと機能していると考えてください。
ワークフロー:フリートが学習した内容を確認する
スクラッチパッドは、フリートがチームごとに保持する永続的なメモリです。調査エージェントが記述する文章形式のエントリによって、後続の実行はより賢く、不要な動作を抑えられるようになります。 これを読むと、フリートがこのプロジェクトについてどう認識しているかが分かります。
scout-scratchpad-search
{ "text": "error_tracking" }
エントリーを新しい順に返します。デフォルトは20件で、limit は最大1000件です。text は content と key を大文字・小文字を区別せずに照合します。
すべてを閲覧するには text を省略します。存在するメモリを手軽に確認するには keys_only=true を指定し、長い本文をプレビューするには content_max_chars を指定します。また、上限を超えて遡るには、最も古いエントリーの updated_at を date_to に設定します。
有効期限が過ぎたエントリー(過去の expires_at を持つエントリー)は、include_expired=true を指定しない限り除外されます。各エントリーには、元の作成者(スカウトのスキル名、またはパイプラインのステージに応じて pipeline:report-research / pipeline:implementation)を示す created_by_skill も含まれます。これは来歴を示すものであり、現在のテキストの作成者を示すものではありません。同じチーム共通キーを別の書き手が upsert しても、元の作成者と created_by_run_id はそのまま保持されるため、どちらのフィールドも共有キーの現在の書き手を示すものではありません。内容をそのスキルに帰属させず、不明として扱ってください。
各エントリーの key にはカテゴリのプレフィックスが付き、学びの種類を示します。
| Prefix | 意味 |
|---|---|
pattern: | ベースライン:このチームのデータに通常見られる傾向 |
watch: | 追跡中のライブ課題。ただし、まだレポート基準には達していません |
followup: | スカウトの検証キュー:後続の実行で再実行し、修正または再発を確認するプローブ |
noise: | フリートが無視すると決めたパターン(開発環境のみ、単一ユーザーなど) |
addressed: | チームが修正した、または対応を終えたもの |
dedupe: | 特定の課題/フィンガープリントの再登録を防ぐゲート |
allowlist: | 精査済みで、再び表面化させないエンティティ |
not-in-use: | このチームが使用していない製品/サーフェス(対応終了のメモ) |
mcp-gap: | スカウトが気づいた、後で提起する価値のあるツールの不足点 |
improve: | カスタムスカウトが提案した、自身のスキル本文への変更。オーナーのレビュー待ち |
reported: | スキルの不足点をすでに PostHog にフィードバックした、標準スカウトの記録 |
report: | スカウトが作成したレポート。後続の実行で編集/重複排除するための report_id を保存します |
reviewer: | 領域の解決済みオーナー(GitHub ログイン名)。suggested_reviewers の割り当て用にキャッシュされます |
これは共通の語彙であり、固定された一覧ではありません。スカウトは必要に応じて独自のプレフィックスや <domain> ラベルを作成します(たとえば、稼働中のフリートでは watch: が多く使われています)。見慣れないプレフィックスも、単なる別のカテゴリとして扱ってください。
エントリー同士は [[key]] の Wiki リンクで相互参照します。
キーは <prefix>:<domain>:<entity> の形式です(例:dedupe:error_tracking:019e8375-…)。
ユーザーから「なぜスカウトが X を検出しなくなったのですか?」と尋ねられたら、スクラッチパッドで noise:、addressed:、dedupe:、allowlist: のエントリーを検索してください。フリートが意図的に抑制するよう学習した可能性があります。
標準プレフィックスの語彙と、フリートが判断に用いる4状態の重複排除分類は、authoring-scouts スキルの references/dedupe-and-memory.md に記載されています。
カスタムスカウトは、スキルの改善点を自ら報告します。 カスタム(チーム作成)のスカウトは、実行によって自身のスキル本文が誤った方向に導いたことを示す具体的な証拠が得られた場合、ハーネスから improve:<skill-name>:<topic> エントリーを書くよう促されます。このエントリーには、提案された変更、その証拠、日付入りの観測内容を記録し、後続の実行でも同じ箇所で再確認します。
レポートチャネルを使うカスタムスカウトは、繰り返し現れる提案や重要な提案をさらにエスカレーションします。自身に関する受信トレイレポートを作成し(タイトルは Scout self-improvement: <skill-name> – <topic>)、その report_id を improve: エントリーに保存します。これにより、最も有力な提案はスクラッチパッド経由だけでなく、ほかのレポートと同様に受信トレイを通じてオーナーに届きます。
カスタムスカウトを評価するときは、{"text": "improve:"} を検索し、該当するエントリーをユーザーに提示してください。複数の実行にわたって再確認されたエントリーは、オーナーが行える編集の中で最も有力なものです。
それらを確認して適用するのは書き込み操作です。authoring-scouts スキルに引き継いでください。
標準スカウトは improve: エントリーを書きません(スキル本文はPostHogのフリートから同期されます)。そのため、標準スカウトの領域に improve: エントリーがあれば、それ自体を指摘する価値があります。
代わりに標準スカウトは、スキル内容の不足を agent-feedback MCP ツール(feedback_type: "scout")経由でPostHogチームに上流報告します。その際、プロジェクトデータが外部に送信されないよう一般化し、すでに提出した内容をローカルに記録するため reported:<skill-name>:<topic> エントリーを残します。そのため、reported: エントリーがあれば、不足がこのチームではなくPostHogに報告されたことがわかります。
ワークフロー:スカウトが作成した内容を確認する
スカウトの出力は受信トレイレポートとしてユーザーに届きます。 スキル名で受信トレイをフィルタリングすると、特定のスカウトのレポートを絞り込めます(複数の場合はカンマで区切ります)。
inbox-reports-list
{ "scout": "signals-scout-error-tracking", "limit": 20 }
各行には scout_name も含まれるため、フリート全体のページで、どのスカウトが何を作成したかを確認できます。
フリート全体のレポートをまとめて確認するには、代わりにソースでフィルタリングします:{ "source_product": "signals_scout", "limit": 20 }。
スカウトが作成したすべてのレポートには、source_product="signals_scout" のタグが付いた根拠シグナルが含まれます。このフィルターは、寄与したシグナルにそのタグが含まれるレポートをすべて抽出するため、結果はフリートが作成したレポートの集合になります。
どちらのフィルターも、編集だけの作業は対象になりません。たとえば、スカウトが既存の非スカウトレポートを編集(パイプラインレポートに注記を追記するなど)しても、signals_scout シグナルは追加されないため、そのレポートは一致しません。編集内容は、実行行の edited_report_ids から追跡してください。
抑制されたレポートはデフォルトでは非表示です。スカウトの出力がどの程度フィルタリングされたかを判断するときは、include_all_statuses: true(または status: "suppressed")を追加してください。それでも、安全性判定器によって抑制されたレポートは、scout と source_product のどちらのフィルターでも見つかりません。どちらもシグナルを介してレポートを解決しますが、安全でないレポートのシグナルはインデックス化されないためです。シグナル対ノイズの監査では、実行行の emitted_report_ids が完全な一覧です。
結果が空でも、フリートがレポートをまだ一件も作成していないという意味であり、フィルターが壊れているわけではありません。
スカウトの判定基準は厳しく、ほとんどの実行ではレポートを書かずに終了します。そのため、動きの少ないプロジェクトや登録したばかりのプロジェクトでスカウトレポートがゼロなのは、通常どおりで予想される状態です。
受信トレイに表示されるのは表示対象になったレポートだけです。安全性判定器によって抑制されたレポート(または not_actionable として作成されたレポート)は、ステータスが SUPPRESSED のまま保持されますが、デフォルトの受信トレイ表示には現れません。
実行ごとのビューを確認するには、実行を起点にしてください。scout-runs-list?emitted=true には、レポートを作成したすべての実行が一覧表示されます。各実行の emitted_report_ids / edited_report_ids には、作成または更新したレポートが正確に記録されているため、inbox-reports-retrieve で取得してください。
ギャップを説明する際は、逆のケースも重要です。実行の summary に「レポートを作成した」と記載されていても、事前チェックによって書き込みが通知なく破棄される場合があります(その時点でドライランだった、組織が AI 処理を承認していない、または signals_scout ソースが無効になっている場合など)。この場合、emitted_report_ids は空のままです。そのため、作成したという記載があるのにレポートが存在しないこと自体が、診断の手がかりになります。
受信トレイをさらに広く確認するには、inbox-exploration スキルを使用してください(ステータス、推奨レビュアー、レポートの基盤となるシグナルの詳細確認)。
各レポートの基盤となるレポート契約(レポートの基準、エビデンス、実行可能性、レビュアーへの振り分け)については、authoring-scouts スキル(references/report-contract.md)に記載されています。
レポートのステータスだけでは全体像はわかりません。チェックも確認してください。 チェックとは、スカウトまたはレポートパイプラインがレポートに付与する追跡測定です。期待値と、それを測定する時刻が設定されているため、レポートが解決済みでも測定が続いていることがあります。
inbox-report-checks-list は、1 件のレポートに対するすべてのチェックを新しい順に返します。各チェックの status(pending、active、passed、failed、errored、expired、cancelled)、last_outcome、スケジュール(next_run_at、run_interval_minutes、runs_remaining、expires_at)が含まれます。inbox-report-checks-retrieve は、1 件のチェックの完全な設定を返します。
各行は次のように読み取ってください。
pending— チェックはレポートが解決されるのを待っており、その後に計測が始まります。- 将来の
next_run_atが設定されたactive— 判定結果がまもなく出ます。手作業で結果を再導出せず、結果が出る時期を伝えてください。 - それ以外はすべて終了状態です。引き続き確認する価値のある主張には、新しいチェックが必要です。これは書き込みを伴うため、
authoring-scoutsに引き継いでください。
判定結果そのものはチェックの行にはありません。各判定結果はレポート上の check_result アーティファクトであるため、レポートのアーティファクト一覧から確認してください。
query と baseline_value は、それらが示すデータを読み取れない認証情報では null として返されます。
解決済みレポートのチェックが failed の場合、通常はその背後に新しいレポートもあります(違反が解決済みレポートにリンクされた新しいレポートとして再浮上しています)。未対応の再発として報告する前に、そのレポートがないか確認してください。
チェックの仕組み全般(2 種類のチェック、観測期間、各判定結果の後に起こること)については、authoring-scouts スキル(references/report-checks.md)に記載されています。
ワークフロー:健全性とパフォーマンスの評価
「この scout は本当に動いているのか/コストに見合っているのか?」
単一の指標で判断することはできません。一定期間の実行履歴を見て scout を評価してください。
実行履歴を取得し(date_from を指定して scout-runs-list を実行)、以下の各項目に照らして判断します。
各シグナルの読み取り方や一般的な失敗パターンを含む完全な手引きは、references/assessing-performance.md にあります。
- 実行頻度の遵守:実行はおおむね
run_interval_minutesごとに行われていますか。それともrun_cron_scheduleの各枠で行われていますか? cron scout はインターバルではなく、スケジュールの枠に照らして判断してください。平日のみ動く scout が週末に実行されないのはスケジュールどおりであり、停止しているわけではありません。また、assess_health.pyはインターバルに基づく採点をスキップするため、その実行頻度の列にはcronと表示されます。 大きな空白期間がある場合、コーディネーターが scout の実行をスキップしています(無効化されている、フラグによって実行対象から外れている、または負荷の高いタイミングで上限に達している)か、ディスパッチはしているものの実行が開始されていない可能性があります。last_run_atを見れば、この2つを区別できます。設定のlast_run_atも古い場合は、コーディネーターが実行計画の作成を停止しています。一方、last_run_atが新しいのに最新の実行履歴が何時間も前の場合は、前述のディスパッチと実行の乖離(ワーカーの処理が滞っている/停止している、または実行が取り残されている)です。この問題はscout-runs-listだけでは見えません。 - 成功率 — エラーにならず、正常な
statusまで到達した実行の割合はどれくらいですか? エラーが続いているなら、静かなのではなく scout が壊れています。失敗した実行をfailure_reasonごとにまとめ、同じ原因が繰り返されているか確認してください。 - レポート率 — レポートを新規作成または編集した実行と、何も出力せずに終了した実行の割合はどれくらいですか?
各実行の
emitted_report_ids/edited_report_idsを直接確認するか、runs-list?emitted=true/?emitted=falseで期間を分けて確認してください。編集のみの実行は未出力として扱われる点に注意してください。 稼働中のサーフェスで長期間にわたりほぼゼロの場合、判別条件が厳しすぎる(またはサーフェスが本当に静かである)可能性があります。ほぼ100%の場合は、通常ノイズが多すぎます。 measurement scout はこの指標で評価しないでください。レポート率がほぼゼロなのは意図された動作なので、代わりにそのレコードストリームを確認してください。 健全な scout の大半は、レポートを頻繁には作成しません。 - シグナル対ノイズ比 — 作成されたもののうち、アクションにつながる受信トレイのレポートとして表示されたものと、抑制または非表示にされたものの割合はどれくらいですか?
各実行の
emitted_report_idsをinbox-reports-retrieveで解決し、レポートのステータスを確認してください。一定期間に作成されたレポートのうち、有効で抑制されていないものの割合が scout の的中率です。 - メモリの増加 — 健全な scout は、時間の経過とともに
pattern:/noise:/dedupe:のエントリーを蓄積します。 多数の実行を経てもスクラッチパッドが空の scout は、学習できていません。
ヘルパースクリプト
このスキルには、よくある依頼に対応する純粋なフォーマッターが scripts/ 以下に3つ含まれています。
ネットワーク I/O は一切行いません。「エージェントが取得し、スクリプトが整形する」という分担の後半を担います。
手順は常に同じです。
- MCP を使って各ペイロードを
call --json(整形済みテキストではなく、生の JSON)で取得し、ファイルに保存します。 大きなデータ(scout-runs-list、tasks-runs-session-logs-retrieve)では、インライン表示の上限を超えてファイルに出力されるため、この手順は必須です。そのファイルをスクリプトに渡してください。 - それらのファイルを使ってスクリプトを実行します。
3つのスクリプトはいずれも標準ライブラリのみを使う Python 3.11 以降のスクリプトで、標準出力(または --out)にプレーンテキストを出力します。ターミナルで読みやすいよう設計されているため、.txt として保存してください。
scripts/render_run_report.py — 1 回の実行を詳しく調べる
1 回の実行を調べるときに役立つ、詳細なレポートを生成します。ヘッダー(ステータス、所要時間、姿勢)、エージェントの説明と各ツール呼び出しおよびその実際の入力を交互に示すナレーション付きタイムライン、実行終了時の概要、スクラッチパッドメモリーが含まれます。
# fetch (note --json), saving each to a file:
# call --json scout-runs-retrieve { "id": "<run_id>" } -> run.json
# call --json tasks-runs-session-logs-retrieve { "id": "<task_run_id>", "task_id": "<task_id>", "limit": 5000, "offset": 0 } -> log.json (FULL, no exclude_types; page with offset until an empty page, then concatenate)
# (optional) call --json scout-scratchpad-search { ... } -> mem.json
# (optional) call --json scout-config-list {} -> cfg.json
python scripts/render_run_report.py --run run.json --log log.json \
--scratchpad mem.json --config cfg.json --out report.txt
モード(--mode、デフォルトは detailed):
| モード | 内容 | --log が必要か |
|---|---|---|
summary | ヘッダー + 姿勢 + 終了時の説明 | いいえ |
detailed | + ナレーション付きタイムライン(ツールの入力を含む)+ ツール集計 + スクラッチパッド | はい |
full | + 各ツール呼び出しの(切り詰められた)出力をインライン表示 | はい |
その他のフラグ:--show-output(detailed モードで出力を表示)、--input-width / --output-width(切り詰め幅)、--no-art(ハリネズミのバナーを省略)、--base-url(デフォルトは us.posthog.com)。
scripts/fleet_survey.py — フリート全体を調査する
スカウト、有効/無効、姿勢、実行頻度、最終実行、最終結果をひと目で確認できる表を表示します。また、「要確認」セクションでは、一度も実行されていないスカウト、ドライランのまま停止しているスカウト、最終実行が失敗したスカウトを示します。
# call --json scout-config-list {} -> cfg.json
# (optional) call --json scout-runs-list { "limit": 30 } -> runs.json (small limit!)
python scripts/fleet_survey.py --config cfg.json --runs runs.json --now <current-ISO-time>
相対時間の「経過」列を表示するには、--now(現在時刻、ISO-8601)を指定します。最終結果の列は、実行行の emitted_report_ids / edited_report_ids から、実行で書き込まれた内容を直接読み取ります。
scripts/assess_health.py — 実行履歴の期間を指定して健全性を評価する
上記の「健全性とパフォーマンスを評価する」ワークフローを実装しています。スカウトごとの表(実行回数、成功率、レポート率、実行頻度の間隔に対する差、遵守状況、所要時間の中央値、メモリーの増加)に加え、「要確認」セクションでは、すべての実行が失敗したスカウト、タイムアウトと思われる失敗、実行頻度の停滞、古さ、空のスクラッチパッドを示します。
# call --json scout-runs-list { "limit": 100, "date_from": "<ISO>" } -> runs.json
# (optional) call --json scout-config-list {} -> cfg.json
# (optional) call --json scout-scratchpad-search {} -> mem.json
python scripts/assess_health.py --runs runs.json --config cfg.json \
--scratchpad mem.json --now <current-ISO-time> [--skill signals-scout-general]
--config を指定すると、実行頻度の遵守状況(期待される間隔)と古さを評価できます。run_cron_schedule が設定されたスカウトは cron として扱われ、間隔ベースの遵守状況、停滞、古さのフラグの対象外になります。古さの評価では、正確な最終実行時刻である last_run_at を使用します。ウィンドウ内の実行履歴は、最新の実行が 100 件の上限によって省かれることがあるためです。
--scratchpad がない場合、メモリー列には n/a が表示され、メモリーに関するフラグも立ちません。
レポート率は実行行の emitted_report_ids / edited_report_ids から直接読み取るため、正確です。ただし、数えるのは 書き込み のみです。シグナルとノイズの比率は、inbox-reports-list でレポートのステータスを確認して判断してください。
ヒント
- 常に
emitの姿勢を明示してください。 「ドライランで実行中」は、スカウトが正常なのにユーザーが壊れていると思う最も一般的な理由です。 - 何もないクローズアウトも成功です。 実行のほとんどでは何も見つからないはずです。 問題がない空の実行が大量に続いても、問題として報告しないでください。
- 実行で書き込まれた内容は、実行の主要なフィールドです。 散文形式の
summaryを解析せずに書き込まれた内容を見つけるには、実行ごとのemitted_report_ids/edited_report_idsを確認するか、runs-list?emitted=trueで絞り込んでください。source_product: "signals_scout"の受信トレイフィルターには、フリートが表面化させた_レポート_が一覧表示されます。ここで結果が空でも、フィルターが壊れているのではなく、まだ何も書き込まれていないことを意味します(スカウトは高い基準を保っています)。 emitted_count: 0は「何もしなかった」という意味ではありません。emitted_count/emitted_finding_idsはレガシーのシグナルチャネル用フィールドです。レポートチャネルのスカウトでは、成果があってもなくても0/空のままです。 出力はレポート列で判断してください。レガシーの集計値がゼロ以外なら、その実行はまだレガシーチャネルを使っているスカウトによるもので、実際の出力はその実行にあります。- 約15分続いた
failed実行は、通常、スカウトの故障ではなくタイムアウトです。 実行ごとの予算は15分で、完了する実行は数分で終わります。failure_reasonにはタイムアウトが明記されるため、実行時間から判断する前に確認してください。 多くの場合、スカウトが調査に時間をかけすぎて予算を使い切っています(フリートは「短時間実行のレシピ」をスクラッチパッドに記録して自動修正します)。ただし、スカウト自体は数分で完了したのに、クローズアウトが切断されてその後停止したという誤検知のタイムアウトもあります。 どちらなのかはセッションログ(上記)で見分けられます。実際に調査しすぎた場合は、制限時間の直前までツール呼び出しが記録されます。誤検知のタイムアウトでは、それよりかなり前に記録が途絶えます。 実行時間だけから調査しすぎたと判断しないでください。 - まず実行の
summaryを示し、その後に全トランスクリプトを確認するためのtask_urlを案内してください。実行の生データをユーザーにそのまま提示しないでください。 - **
last_run_at: null**は、コーディネーターがそのスカウトを一度もディスパッチしていないことを意味します。スカウトが一度も実行されていないという意味ではありません。手動実行(scout-run-now)やワークフローによる実行ではこのタイムスタンプが更新されないため、スカウトを未実行と判断する前にscout-runs-listを確認してください。その後、有効になっていることとプロジェクトが登録されていることを確認します(cronスカウトは、作成後、最初の実行枠が来るまで待機するだけの場合もあります)。 - 実行が少ないスカウトについて説明するには、プロジェクトのプロファイルを確認してください。
scout-project-profile-getでは、監視対象のサーフェスが実際に使われているかどうかを確認できます。ログのないプロジェクトを監視するログスカウトには、実行することがありません。 - このスキルは読み取り専用です。 スカウトのスケジュール、姿勢、本文を変更するには、
authoring-scoutsスキルに引き継いでください。このスキルでは、scout-config-updateとskills-storeの編集手順を扱います。