mcpField
C
camunda-feel

camunda-feel

github.com/camunda开发26135 次安装今天更新
代码仓库

关于 camunda-feel

面向 Camunda 8 流程开发者的 FEEL 表达式编写、调试与求值指南,覆盖 BPMN、DMN 和表单场景,并说明集群引擎与本地引擎的差异。

主要功能

  1. 01编写与检查 FEEL 表达式
  2. 02通过 c8ctl 求值
  3. 03使用变量上下文测试
  4. 04覆盖 BPMN、DMN 和表单场景
  5. 05比较集群与本地引擎结果

适用场景

  1. 01验证 BPMN 网关条件和变量映射
  2. 02调试 DMN 决策表达式
  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 表达式

编写、调试和评估 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 Agent 流程中的 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 使用 JavaScript 引擎 feelin 在本地评估表达式——在没有集群时很有用。**仅在用户明确要求,或无法连接集群且用户已确认使用此回退方案时使用。**切勿静默回退。

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)中,它返回本地时区午夜时刻的日期时间(例如 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

如果下游函数要求参数为日期类型,本地结果还可能引发集群中不会出现的类型错误。

核心语法

数据类型:数字(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 不会在算术运算中自动进行类型转换——"prefix-" + userId(其中 userId 是数字)会静默求值为 null,并发出 Can't add 'N' to '"prefix-"' 警告,而不是报错。完整规则和调试提示请参阅 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"

空值安全访问:

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

故障排除

  • FEEL_RESOLUTION_ERROR — 表达式中引用的变量在求值时不存在于变量上下文中。使用预期的运行时变量运行 c8ctl feel evaluate '<expr>' --vars '<json>' 进行确认。
  • 表达式意外返回 null — 常见原因:+ 拼接时类型不匹配(参见上面的 string() 规则);使用从 0 开始的索引(应使用 events[1],而非 events[0]);调用不存在的辅助函数(first() 不存在);上下文条目之间缺少逗号。c8ctl feel evaluate 在文本模式下会将实际的 null 结果显示为 <null>,以便与 FEEL 字符串 "null" 区分(后者仍显示为 null)。

参考资料

详细参考资料请查阅 references/:

  • function-reference.md — FEEL 内置函数完整列表(字符串、数值、列表、上下文、日期/时间、布尔值)
  • common-patterns.md — 日期运算、列表筛选、多条目上下文模式,以及用于 Agent 式 AI 的 fromAi()

评论

支持 Markdown