segments について
RevOS MCP サーバーを介してオーディエンスセグメントを作成、編集、適用するスキルです。API 書き込みでは条件が十分に検証されないため、キューブのメタデータ、保存値、結合経路、保存結果の確認を重視します。
主な機能
- 01キューブのメタデータと結合を確認
- 02オーディエンス条件を構築
- 03条件設定前に保存値を確認
- 04一対多結合による増殖を回避
- 05セグメントを作成・更新
- 06書き込み結果を読み戻して検証
活用シーン
- 01セマンティックモデルのデータから対象を作成
- 02他の条件を失わずにセグメント条件を編集
- 03テーブルビューをセグメントで絞り込み
MCP 対応
RevOS MCP サーバーの segments リソースで汎用ツールを使用します。api_read でセグメントの一覧取得と読み出しを行い、api_write で作成・更新します。キューブのメタデータやクエリにも同じツールを使用します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ revosai/ skills --skill segmentsインストール後、Claude Code で/segmentsを入力して読み込まれたか確認します。
同梱ファイルevals/evals.jsonreferences/filter-syntax.md
詳細
セグメント
セグメントは保存済みのオーディエンスです。ルートキューブのレコードごとに1行を持ち、フィルターに一致するレコードが保持されます。テーブルではなくセマンティックモデル(キューブ)上で定義されます。テーブルはセグメントを借りて行を絞り込みます。
RevOS MCP サーバーの汎用ツールを使い、segments
リソースからアクセスします。api_read で一覧表示と取得を行い、api_write で作成(id なし)と更新(id あり)を行います。api_details({ resource: "segments", operation: "create" }) がリクエストボディの形式に関する正式な仕様です。このスキルでは、そのスキーマだけではわからないことを説明します。
常に念頭に置くこと:**サーバーはセグメントの保存時にほとんど検証しません。**メンバー名、結合パス、条件がルートに対して妥当かどうかは、RevOS UI のセグメントエディターでのみ検証されます。また、セグメントをテーブルのデフォルトビューに設定すると、その条件はテーブルのビューにコンパイルされます。そのため、無効なメンバーがあるとセグメントだけでなく、組織のモデルが壊れる可能性があります。 API 経由では、壊れたセグメントも 200 で保存され、その後に失敗することがあります。さらに悪い場合、評価時に誤ったレコードにひそかに一致することもあります。以下のチェックは書き込む前に自分で行ってください。また、書き込み後にセグメントを読み戻せば、実際に何が保存されたかを確認できます。
ツールの呼び出し
引数の形式は、ここでは特に重要です。キーを誤った場所に指定しても、拒否されずに無視されることがよくあります。ボディを誤ったキーの下に置いた書き込みが成功を返し、セグメントのバージョンを更新しても、何も変更されない場合があります。
// List / get / named reads — `params` for query-string filters, `body` for a named read that takes one
api_read { "resource": "segments", "params": { "filter": "name == \"Enterprise accounts\"" } }
api_read { "resource": "segments", "id": "<segment id>" }
api_read { "resource": "cubes", "method": "meta", "params": { "filter": "name == \"crm_deals\"" } }
api_read { "resource": "cubes", "method": "query",
"body": { "query": { "dimensions": ["crm_deals.stage"], "limit": 20 } } }
// Create (no id) / update (with id) — the record always goes under `data`
api_write { "resource": "segments", "data": { "name": "…", "type": "DYNAMIC", "cubes": [ … ], "filter": { … } } }
api_write { "resource": "segments", "id": "<segment id>", "data": { "filter": { … } } }
名前付きの読み取り(meta や query など)の選択には、operation ではなく method を使います。キューブのクエリは params ではなく、body.query に指定します。
セグメントの作成
1. ルートキューブを選ぶ — 何を「メンバー」とするかが決まります
「成約した取引がある企業」では企業がメンバーになり、「成約した取引」では取引がメンバーになります。同じデータでも、オーディエンスは異なります。ユーザーが最終的に対象としたいものを行として持つキューブを選び、本当に曖昧な場合はユーザーに確認してください。作成後にルートを変更しないでください。API は変更を止めませんが、セグメントを使って構築されたものはすべてルートを前提としています。代わりに新しいセグメントを作成してください。
まずカタログを読み、その後でルートの完全な定義を読みます。
{ "resource": "cubes", "method": "meta", "params": { "fields": "name,title,description", "pageSize": 100 } }
{ "resource": "cubes", "method": "meta", "params": { "filter": "name == \"crm_companies\"" } }
完全な定義には、メンバー(常に <cube>.<member> と記述)、各ディメンションの type、primaryKey: true のディメンション、キューブが宣言している場合の meta.nameDimension、およびキューブの joins が含まれます。メンバー名を推測してはいけません。名前は組織ごとに異なります。
ビジネス上の名前が付いたキューブを優先してください。ただし、ユーザーが明らかにそのようなキューブを求めている場合は除きます。ここでいうキューブとは、説明が簡素または欠落しており、機械的な名前が付いたヘルパーキューブです。
2. cubes を構成する — まずルートを置き、次にフィルター対象の他のキューブを1つずつ追加します
"cubes": [
{ "joinPath": "crm_companies", "primaryKeyDimension": "id", "nameDimension": "name" },
{ "joinPath": "crm_companies.crm_deals" }
]
cubes[0]がルートです。そのjoinPathはキューブ名だけです。primaryKeyDimensionにはルートの主キーのディメンション(キューブのプレフィックスを除いたメンバー名)を設定し、キューブがmeta.nameDimensionを宣言している場合はnameDimensionにそれを設定します。そうでなく、キューブにnameという名前のディメンションがあれば、それを設定します。セグメントからテーブルを作成する際、これらを使ってid列とname列を構成します。ルートに主キーのディメンションがない場合は、そのことを伝えてください。セグメントはidを基準に評価されますが、idが存在しない可能性があります。- 条件が参照する他の各キューブには、
joinPathを指定したエントリーが必要です。そのパスはjoinsに従ってルートから対象キューブまでたどるドット区切りのパスです。"root.middle.target"。各段階をキューブのjoinsと照合してください。また、キューブに一覧表示されるのは、そのキューブ自身が宣言した結合のみです。AにBが記載されていない場合でも、結合パスがないと結論づける前にBのjoinsも確認してください。 - 同じキューブに至る経路が実際に2つ異なる場合、選ぶ経路によって結果が変わります。黙って選ばず、どの関係を意味しているのかユーザーに確認してください。
3. フィルターを記述する — ファンアウトに注意
filter は RevOS 独自の条件形式です(Cube.js のクエリではありません)。
"filter": {
"combinationMode": "AND",
"items": [
{ "member": "crm_companies.industry", "type": "EQUAL", "value": "Software" },
{ "filterType": "Group", "combinationMode": "OR", "items": [
{ "member": "crm_companies.country", "type": "EQUAL", "value": "DE" },
{ "member": "crm_companies.country", "type": "EQUAL", "value": "AT" } ] }
]
}
使用できる演算子、メンバーの種類ごとに適した演算子、日付の値、JSON スキーマには示されていない検証ルールについては、references/filter-syntax.md に記載されています。単純な EQUAL を超える条件を記述する前に、必ずお読みください。特に重要なルールが 2 つあります。複数の値を指定する「in」はありません(value は文字列または数値を 1 つだけ指定するため、「DE または AT」は上記のように OR グループにします)。また、IS/IS_NOT に指定できるのは TODAY、IN_THE_FUTURE、IN_THE_PAST だけです。
文字列に対して EQUAL/NOT_EQUAL を使う前に、保存されている値を確認してください。 一致判定は完全一致かつ大文字と小文字を区別します。また、ユーザーの言葉(「active」「enterprise」「won」)と、データソースに保存されている値(ACTIVE、Enterprise、closedwon)は異なることがよくあります。値を誤ってもエラーにはならず、セグメントが空になるだけです。実際の値は、簡単なクエリで確認できます。
api_read { "resource": "cubes", "method": "query",
"body": { "query": { "dimensions": ["billing_subscriptions.status"], "limit": 20 } } }
保存されている表記を使い、ユーザーの言葉に一致するものがなければ、推測せずに確認してください。
ファンアウト — 保存は問題なくできても、回答が誤る落とし穴です。 ルートキューブが別のキューブを複数持つ場合、そのキューブに対するディメンション条件は、「そのような行が少なくとも 1 つあるメンバー」を確実に意味するものではありません。ルートが子行に展開されてしまうため、まさにこの理由で UI では保存が拒否されます。API はこれを防ぎません。結合はどちら側にも定義できるため、両方のキューブの joins を確認してください(Cube は snake_case と camelCase の両方に対応しています)。
| 見つかった結合 | ルートが持つのは… |
|---|---|
root → other: many_to_one/belongsTo または one_to_one/hasOne | 1 つ |
other → root: one_to_many/hasMany または one_to_one/hasOne | 1 つ |
root → other: one_to_many/hasMany | 複数 |
other → root: many_to_one/belongsTo(例:crm_deals → crm_companies) | 複数 |
代わりに、子キューブのメジャーを使った条件に言い換えてください。これにより、ルートの行ごとに集計されます。
- 「取引が 3 件以上ある企業」 →
{ "member": "crm_deals.count", "type": "GREATER_THAN_OR_EQUAL", "value": 3 } - 「取引が 1 件以上ある企業」 →
crm_deals.countGREATER_THAN0。
子キューブに条件を表すメジャーがない場合(例:「ステージが won の取引がある」で、won の取引数のメジャーがない場合)は、ファンアウトを起こすディメンション条件を記述してはいけません。現在のセマンティックモデルでは、このルートからその条件をサポートしていないことをユーザーにはっきり伝え、サポートされている選択肢として、代わりに子キューブをルートにしたセグメント(won の取引)を使うか、キューブにメジャーを追加する方法を提案してください。
ルートが 1 つだけ持つキューブに対する条件は、ディメンション条件として問題ありません。
4. type を選ぶ — ユーザーが明確に希望しない限り DYNAMIC
- DYNAMIC(デフォルトで使用):RevOS によって 1 日に数回(6 時間ごと)自動で再評価されるため、データに追従します。新しく作成した DYNAMIC セグメントは、次回の定期評価まで
status: "PENDING"と表示されます。保存直後にobjectCountが空でもユーザーが驚かないよう、その旨を伝えてください。編集したセグメントは、次回の評価まで以前のステータスとobjectCountが維持されますが、そのセグメントを対象とするテーブルには新しいフィルターがすぐに適用されます。 - STATIC は評価時点のメンバーを固定しますが、MCP ツールでは評価を実行できません。ここで作成した STATIC セグメントは、誰かが RevOS UI で Evaluate を押すまで
PENDINGのままです。また、処理待ちの間、そのセグメントを対象とするテーブルにはフィルターが適用されず、すべての行が表示されます。ユーザーが固定スナップショットを明示的に希望した場合に限って作成し、利用する前に UI で Evaluate を実行するよう伝えてください。
作成後に type を変更することはできません。
5. 名前を付け、作成し、結果を報告する
name は必須です(1~255 文字)。対象者を平易な言葉で説明する1行の description を追加します。作成する前に、同名のものがないか確認します —
api_read({ resource: "segments", params: { filter: "name == \"…\"" } })。
同名のものがあれば、2つ目を作る前に、そのセグメントを指しているのか確認してください。
続いて、api_write({ resource: "segments", data: { name, description, type, cubes, filter } }) を実行します。
返された id を使って api_read で読み戻し、cubes と filter が送信した内容と一致するか比較します。一致しているはずです。一致していない場合、意図したとおりに書き込まれていないため、成功を報告するのではなく、呼び出しを修正してください。
その後、1~2文でユーザーに次の内容を伝えます。ルート(1件のメンバーが何を指すか)、平易な言葉での条件、タイプ、および評価されるまでは PENDING であることです。ファニングディメンションではなくメジャーを選んだ、特定の結合パスを選んだなど、判断を加えた場合は、どれを選び、なぜそうしたのかも伝えてください。
セグメントの編集
セグメントの id と、変更するフィールドだけを指定して api_write を実行します。注意点として、送信した各フィールドは保存済みの値全体を置き換えます。 filter と cubes は単一のフィールドです。新しい条件を1つだけ含むフィルターを送ると、省略した条件はすべて失われます。
-
書き込む直前に、最新の状態を
api_read({ resource: "segments", id })で読み取ります。 -
新しい値を追加する前に、その値がどのように保存されているか確認します。 ユーザーが会話で使った言葉(「スタートアッププラン」、「解約済み」、「EMEA」)はデータ由来ではありません。既存の条件から分かるのは、既存の値の表記だけです。新しい条件で使うディメンションをクエリします。
api_read { "resource": "cubes", "method": "query", "body": { "query": { "dimensions": ["crm_companies.plan"], "limit": 20 } } }保存されている表記を使います。ユーザーの言った内容に一致する保存済みの値がなければ、何にも一致しない条件を書き込むのではなく、ユーザーに確認してください。
-
現在の
filter(およびcubes)を基にし、ユーザーが依頼した内容だけを変更します。 -
新しい条件が、まだ
cubesに含まれていないキューブを参照する場合は、そのjoinPathエントリーを追加し、cubes配列全体も送信します。あるキューブ上の最後の条件を削除した場合は、そのエントリーも削除します。 -
typeは更新できないため、送信しないでください。また、ルート(cubes[0])も変更しないでください。API は変更を受け付けますが、そのセグメントを基に作成されたすべてのテーブルとカードは、以前のルートを前提としています。別のルートにする場合は、新しいセグメントを作成してください。 -
書き込み後、もう一度
api_readでセグメントを読み込み、filterが意図した内容で保存されているか確認します。versionが更新されただけでは、変更が反映された証拠になりません。
更新するたびにセグメントの version が上がります(UI では古いバージョンに復元できます。編集に不安を感じているユーザーには、そのことを伝えるとよいでしょう)。STATIC セグメントは filter または cubes が変更されると PENDING に戻り、そのセグメントが適用されているすべてのテーブルは、誰かが UI で Evaluate を押すまですべての行を表示します。このような編集を行う前に、ユーザーに警告してください。セグメントがテーブルのデフォルトビューに適用されている場合は、編集後も meta がコンパイルされることを確認してください。
セグメントを使ってテーブルの行を絞り込む
テーブル自体にはフィルターがなく、フィルターを持つのはそのビューです。テーブルにセグメントのメンバーだけを表示するには、テーブルのデフォルトビューにセグメントを設定します。
api_read({ resource: "table-views", method: "list", id: "<TABLE id>" })— 一覧はテーブルにひも付いているため、ここではテーブルのidを指定します。isDefault: trueのエントリーを選びます。api_write({ resource: "table-views", id: "<that VIEW's id>", data: { "segmentId": "<segment id>" } })。
セグメントを適用すると、ビュー独自のアドホックフィルターは上書きされます(このフィルターは保持され、セグメントを解除すると復元されます)。ビューにフィルターがある場合は、segmentId とともに "filter": {} を送信します。"segmentId": null を指定すると、セグメントが解除されます。テーブルの行の取得元であるキューブ(メインストリーム)をルートに持つセグメントを使ってください。UI はこのように対応付けており、サーバー側では確認されません。セグメントが STATIC で READY でない場合は、評価されるまでテーブルにすべての行が表示されることを警告してください。その後、meta が引き続きコンパイルされることを確認します。セグメントの条件と結合が、テーブルのビューに組み込まれるためです。
セグメントのトラブルシューティング
セグメントをapi_readし、statusを確認します。
PENDING— 保存済みですが、まだ評価されていません。作成または編集の直後であれば正常です。DYNAMICは独自のスケジュールで追いつきますが、STATICはUIでEvaluateを実行する必要があります。EVALUATING— 処理中です。しばらくしてから再確認してください。FAILED—evaluationErrorに理由が記載されています。通常はCubeが原因です。可能性の高い順に、一般的な原因を挙げます。存在しないメンバー(cubesのmetaを再読み込みして名前を修正してください)、またはメンバーに対して種類が異なる条件値です。上記の手順でセグメントを編集して修正すると、次回の実行時に再評価されます。READYだがメンバーや件数が正しくない — よくある原因は、ファンアウトするディメンション条件(手順3を参照)、ユーザーが「メンバー」と言って意図したものと一致しないルートキューブ、または別の経路を通った結合パスです。そもそも実際の結合ではない場合もあります。この場合、評価は失敗せずにセグメントの結合パスを黙って破棄し、Cube独自の経路で件数を数えます。
削除
api_delete({ resource: "segments", id })を実行すると、セグメントが完全に削除され、STATICセグメントの場合はメンバーのスナップショットも削除されます。元に戻すことはできません。呼び出す前に、次の手順を実行してください。
-
セグメントを読み込み、タイプ、ルートキューブ、条件、メンバー数を確認します。
-
STATICセグメントのキューブ。 最初にこれを確認してください。削除できなくなる原因になる可能性があります。STATICセグメントは
segment_<id, - → _>というキューブにコンパイルされます。次の場所でその名前を探してください。- テーブルの
streams、ID、joinPath(fields: "id,name,streams"):セグメントを起点にしたテーブルは、そのキューブをルートとします。 - 他のセグメントの
cubesとfilter(完全なレコード)。 - 保存済みキューブの
joins(cubesに対するapi_read、fields: "name,definition")。
セグメントを削除すると、これらのいずれかがコンパイルできなくなり、組織全体のモデルが機能しなくなります。見つかった内容を報告して作業を中止し、この削除に関してほかの変更は行わないでください。
- テーブルの
-
ビュー。 セグメントが紐付いたテーブルビューが1つでもある間は、削除が拒否されます(
409)。usageCountは該当するビューの数です。これはgetではなくlistにのみ含まれます。params: { filter: "name == \"<name>\"", fields: "id,name,usageCount" }を指定してください。0なら次に進みます。それ以外の場合は、テーブルを一覧表示してから各テーブルのビュー(table-views、method: "list"、TABLEのID、filter: "segmentId == \"<segment id>\"")を調べ、usageCount分のビューが見つかるまで続けます。どのテーブルに適用されているかをユーザーに伝えてください。紐付けを解除(segmentId: null)すると、そのテーブルにはすべての行が表示されるため、解除するのはユーザーの同意がある場合だけにしてください。 -
ダッシュボードカード。
usageCountには数えられず、409の原因にもなりません。セグメントを削除してもカードにはsegmentIdが残り、ダッシュボードでは利用不可と表示されます。api_read { "resource": "dashboard-cards", "params": { "filter": "segmentId == \"<segment id>\"" } }でカードを探し、どのダッシュボードからどのカードが失われるかをユーザーに伝えてください。 -
このセグメントの削除について、明示的な同意を得てください。1つの削除への承認は、別のセグメントには適用されません。
-
api_deleteを実行し、その後もmetaがコンパイルできることと、セグメントが一覧から消えていることを確認します。metaが失敗した場合、元に戻す方法はありません。エラーを読み、まだセグメントのキューブを参照している箇所(手順2の場所)を見つけて、何を変更する必要があるかをユーザーに伝えてください。
失敗した試行で自分が作成したセグメントであっても例外ではありません。そのことを伝え、削除する前に確認を求めてください。
書き込み操作(作成、更新、削除、ビューへの紐付け)のいずれかで403が返された場合、ユーザーのロールではセグメントを変更できません。Memberが必要です。これらのツールでは、評価、複製、以前のバージョンの復元はできません。ユーザーにはRevOS UIを案内してください。