mcpField
C
camunda-feel

camunda-feel

github.com/camunda開発26135 回インストール1 日前に更新
リポジトリ

camunda-feel について

Camunda 8 開発者向けに、BPMN、DMN、フォームで使う FEEL 式の作成、デバッグ、評価方法を案内します。クラスターエンジンとローカルエンジンの違いも扱います。

主な機能

  1. 01FEEL 式の作成と確認
  2. 02c8ctl による評価
  3. 03変数コンテキストでのテスト
  4. 04BPMN、DMN、フォームへの対応
  5. 05クラスターとローカルのエンジン比較

活用シーン

  1. 01BPMN のゲートウェイ条件とマッピングの検証
  2. 02DMN の判定式のデバッグ
  3. 03フォームの検証や条件付き表示の確認
  4. 04変数、型変換、日付の問題の調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/camunda/skills --skill camunda-feel

インストール後、Claude Code で/camunda-feelを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

portability.json
references/
common-patterns.md
function-reference.md

詳細

Camunda FEEL Expressions

Camunda 8 の BPMN プロセス、DMN の意思決定、フォームで使用される FEEL 式を作成、デバッグ、評価します。

前提条件

  • c8ctl CLI がインストールされ、設定されていること(c8ctl add profile)— c8ctl feel evaluate を提供します
  • デフォルトのクラスターエンジンによる評価には Camunda 8.9 以降のクラスターが必要です(POST /v2/expression/evaluation を使用します)

相互参照

  • camunda-bpmn:FEEL 式が BPMN の条件または I/O マッピングに含まれる場合に使用します
  • camunda-dmn:FEEL が DMN 内の入力式、入力エントリー(一項テスト)、出力エントリー、リテラル式に含まれる場合に使用します
  • camunda-forms:FEEL 式でフォームの検証または条件付き表示を制御する場合に使用します
  • camunda-ai-agents:FEEL 式がプロンプト、fromAi() のパラメーター宣言、または AI エージェントプロセスにおける toolCallResult の整形に使われる場合に使用します

手順

Camunda における FEEL

FEEL は次の用途で使用されます。

  • ゲートウェイ条件:変数の値に基づいてプロセスフローを分岐します
  • 入力/出力マッピング:プロセススコープ間で変数を変換します
  • タイマー定義:期間、日付、繰り返しを定義します
  • DMN 意思決定テーブル:入力/出力ルールを定義します
  • フォーム検証:ユーザー入力を検証します

BPMN XML のすべての FEEL 式には、先頭に = を付ける必要があります。

<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">=amount &gt; 1000</bpmn:conditionExpression>
式の評価

FEEL 式を検証してデバッグするには、c8ctl feel evaluate を使用します。デフォルトでは、設定済みクラスターの Scala FEEL エンジンに対して実行されます。これは Zeebe が実行時に使用するエンジンと同じなので、結果は本番環境の動作と正確に一致します。

# Simple expression
c8ctl feel evaluate '1 + 2'

# Expression with individual variables (leading = optional)
c8ctl feel evaluate '=amount * 1.15' --var amount=100

# Multiple variables
c8ctl feel evaluate 'a + b' --var a=1 --var b=2

# JSON values for complex types
c8ctl feel evaluate 'sum(items)' --var 'items=[1,2,3]'

# Bulk variables as a single JSON object
c8ctl feel evaluate 'orderTotal > 1000 and customer.tier = "premium"' \
  --vars '{"orderTotal": 1500, "customer": {"tier": "premium"}}'

# Dot-path nesting on the CLI
c8ctl feel evaluate 'customer.name' --var customer.name=Alice

デバッグのワークフロー:

  1. 式を記述します
  2. 想定される変数コンテキストを特定します
  3. c8ctl feel evaluate を使ってクラスターエンジンに対して評価し、検証します
  4. 評価に失敗した場合は、エラーメッセージに基づいて修正し、再試行します
オフライン評価(--engine local)

c8ctl feel evaluate --engine local は、feelin JavaScript エンジンを使って式をローカルで評価します。クラスターを利用できない場合に便利です。明示的に依頼された場合、またはクラスターに接続できず、かつユーザーがフォールバックを確認した場合にのみ使用してください。 確認なしにフォールバックしないでください。

feelin の動作は、本番環境で Zeebe が実行する Scala FEEL エンジンとは異なります。型の強制、関数のサポート、日付/時刻の処理にわずかな違いがあるため、ローカルで成功した式がクラスターで失敗する(またはその逆)ことがあります。--engine local で得た結果を利用する前に、必ずクラスターに対して再検証してください。

c8ctl feel evaluate '=amount * 1.15' --var amount=100 --engine local

具体的な差異:today() は異なる型を返します。 クラスターエンジンでは、today() は date を返します(例:2026-05-12)。--engine local(feelin)では、ローカルタイムゾーンの午前0時を示す日時を返します(例:2026-05-12T00:00:00.000+02:00)。これにより、後続の比較で問題が発生します。

# cluster engine — passes
c8ctl feel evaluate 'today() = date("2026-05-12")'           # → true

# local engine — fails silently
c8ctl feel evaluate 'today() = date("2026-05-12")' --engine local   # → false

後続の関数で date 型の引数が必要な場合、ローカルの結果は型エラーを引き起こすこともありますが、そのエラーはクラスターでは発生しません。

基本構文

データ型:数値(1、1.5)、文字列("hello")、ブール値(true/false)、null、日付(date("2024-01-15"))、時刻(time("14:30:00"))、日時(date and time("2024-01-15T14:30:00"))、期間(duration("P1D"))、リスト([1, 2, 3])、コンテキスト({name: "Alice"})、範囲([1..10])

演算子:+、-、*、/、**、=、!=、<、>、<=、>=、and、or、not()、between x and y、in

If-Then-Else(すべての if に else が必要です):

if score >= 80 then "A" else if score >= 60 then "B" else "C"

For ループ:

for x in [1, 2, 3] return x * 2

量化子:

every x in items satisfies x.price > 0
some x in items satisfies x.status = "urgent"

リスト操作:

  • 1 始まりのインデックス:list[1]、負のインデックス:list[-1]
  • フィルター:items[price > 100]
  • 射影:items.name は各項目から name を抽出します

コンテキスト操作:

  • プロパティへのアクセス:customer.name
  • get value(ctx, "key")、get entries(ctx)
  • context put(ctx, "key", value)、context merge(ctx1, ctx2)
一般的なパターンと例

例 — ゲートウェイ条件:

=orderTotal > 1000 and customer.tier = "premium"

変換を伴う入力マッピング:

="https://api.example.com/users/" + string(userId)

string() ラッパーは必須であり、単なるスタイル上の指定ではありません。FEEL は算術演算で型を自動変換しません。userId が数値の場合、"prefix-" + userId はエラーではなく、Can't add 'N' to '"prefix-"' という警告とともに、暗黙のうちに null と評価されます。ルールの全容とデバッグのヒントについては、references/common-patterns.md § 型変換の落とし穴を参照してください。

結果式(API レスポンスから抽出):

={user: response.body, status: response.statusCode}

エラー式(失敗時に BPMN エラーをスロー):

=if response.statusCode >= 400 then bpmnError("HTTP_ERROR", string(response.statusCode)) else null

タイマー期間(FEEL が必須):

="PT" + string(delayHours) + "H"

null 安全なアクセス:

=if customer != null then customer.name else "Unknown"

トラブルシューティング

  • FEEL_RESOLUTION_ERROR — 式で参照されている変数が、評価時に変数コンテキストに存在しません。実行時に想定される変数を指定して c8ctl feel evaluate '<expr>' --vars '<json>' を実行し、確認してください。
  • 式が予期せず null を返す — よくある原因:+ による連結での型の不一致(上記の string() のルールを参照);0 始まりのインデックス指定(events[0] ではなく events[1] を使用);存在しないヘルパーの呼び出し(first() は存在しません);コンテキストのエントリー間のカンマ抜け。c8ctl feel evaluate は、実際の null 結果をテキストモードで <null> と表示し、FEEL の文字列 "null"(こちらは null と表示されます)と区別します。

参考資料

詳細なリファレンス資料については、references/ にある以下のファイルを参照してください。

  • function-reference.md — FEEL 組み込み関数の完全な一覧(文字列、数値、リスト、コンテキスト、日付/時刻、ブール値)
  • common-patterns.md — 日付の算術演算、リストのフィルタリング、複数エントリーのコンテキストパターン、エージェント型 AI 向けの fromAi()

コメント