关于 camunda-feel
面向 Camunda 8 流程开发者的 FEEL 表达式编写、调试与求值指南,覆盖 BPMN、DMN 和表单场景,并说明集群引擎与本地引擎的差异。
主要功能
- 01编写与检查 FEEL 表达式
- 02通过 c8ctl 求值
- 03使用变量上下文测试
- 04覆盖 BPMN、DMN 和表单场景
- 05比较集群与本地引擎结果
适用场景
- 01验证 BPMN 网关条件和变量映射
- 02调试 DMN 决策表达式
- 03检查表单验证或条件可见性
- 04排查变量、类型转换和日期问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ camunda/ skills --skill camunda-feel安装后在 Claude Code 中输入/camunda-feel确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
portability.jsonreferences/common-patterns.mdfunction-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 > 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
调试工作流:
- 编写表达式
- 确定预期的变量上下文
- 通过
c8ctl feel evaluate使用集群引擎进行验证 - 如果评估失败,根据错误消息修复并重试
离线评估(--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()