From camunda-skills
Authors and validates DMN 1.3 decisions for Camunda 8 — decision tables and literal expressions inside a Decision Requirements Diagram. Includes linting and behavioural validation.
How this skill is triggered — by the user, by Claude, or both
Slash command
/camunda-skills:camunda-dmnThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Author executable DMN 1.3 decisions for Camunda 8.8+. A `.dmn` file holds one Decision Requirements Diagram with one or more decisions; each decision is either a decision table or a literal expression. A BPMN business rule task references a decision by ID and gets the result back as a process variable.
Author executable DMN 1.3 decisions for Camunda 8.8+. A .dmn file holds one Decision Requirements Diagram with one or more decisions; each decision is either a decision table or a literal expression. A BPMN business rule task references a decision by ID and gets the result back as a process variable.
<zeebe:calledDecision decisionId="..." resultVariable="..."/>)A DMN file declares the DMN 1.3 namespace and wraps one or more <decision> elements:
<definitions xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/"
id="DinnerDecisions" name="Dinner Decisions"
namespace="http://camunda.org/schema/1.0/dmn">
<decision id="dish" name="Dish">
<decisionTable id="decisionTable_dish" hitPolicy="UNIQUE">
<!-- inputs, outputs, rules -->
</decisionTable>
</decision>
</definitions>
The default namespace and the namespace="http://camunda.org/schema/1.0/dmn" attribute are mandatory.
A decision contains either a <decisionTable> (inputs / outputs / rules + hit policy) or a <literalExpression> (single FEEL expression — useful for combining upstream decisions). Multi-decision files link decisions with <informationRequirement><requiredDecision href="#upstream"/></informationRequirement>; Camunda evaluates only the root decision referenced from BPMN and pulls in required decisions transparently.
See references/decision-tables.md for the full XML of input/output clauses, unary-test grammar, worked examples per hit policy, COLLECT aggregators, type table, and DRG linking.
id, output name, decision-table column names: alphanumeric + _ only. No whitespace, no - (which is a FEEL operator), no other special characters. A violation silently breaks BPMN references — the resolved value is null at runtime.name attributes (Decision, InputData, BusinessKnowledgeModel, KnowledgeSource, DecisionService): any string. dmnlint flags missing name — set one even when id already conveys intent."HIGH" is a string literal; bare HIGH parses as a variable reference and evaluates to null — no parse error, no lint warning.Set on the decisionTable element (default UNIQUE). Camunda 8 supports five; the DMN spec defines more — PRIORITY and OUTPUT ORDER are not supported.
| Hit policy | Result | Behaviour |
|---|---|---|
UNIQUE | single | Exactly one rule must match; multi-match = runtime error. |
ANY | single | Multiple may match, must all produce the same output; otherwise runtime error. |
FIRST | single | Top-to-bottom; first match wins. |
RULE ORDER | list | All matching rules' outputs, in rule order. |
COLLECT | list / scalar | All matches in arbitrary order. With aggregation="SUM" | "MIN" | "MAX" | "COUNT", collapses to a single value. |
Default to UNIQUE. Use FIRST for hard-then-soft semantics (e.g. "blocklist first, then accept rules"). Use COLLECT when a list output is genuinely the goal. See references/decision-tables.md for worked examples per policy.
<bpmn:businessRuleTask id="ApplyDiscount" name="Apply discount">
<bpmn:extensionElements>
<zeebe:calledDecision decisionId="discount" resultVariable="discountPercent"/>
</bpmn:extensionElements>
</bpmn:businessRuleTask>
decisionId matches the DMN decision id. resultVariable receives the result — single-result for UNIQUE/ANY/FIRST, list for RULE ORDER/COLLECT (or scalar with aggregator).
resultVariable overwrites. If the name matches an existing input variable, the input is clobbered — pick a distinct name (e.g. discountPercent not customer) so downstream activities can still read the input.
<zeebe:calledDecision> also accepts bindingType — latest (default), deployment, versionTag. See camunda-bpmn for the binding-type table; deployment is the right choice when BPMN and DMN are co-deployed.
DMN uses FEEL in inputExpression, inputEntry (unary tests), outputEntry, and literalExpression. Unlike BPMN, no = prefix — every text element is parsed as FEEL.
Input entries use the unary tests subset: the input value is implicit, < 5 means ? < 5, comma-separated literals are OR, comma-separated comparisons are AND, ranges are [1..10] / (1..10), not(...) negates, - matches anything.
See references/feel-in-dmn.md for the unary-test grammar, what you cannot do in a unary test, variable scope across linked decisions, and DMN-specific FEEL features.
Two layers — run both before declaring a file done.
1. Structural lint. A DMN edit is not structurally done until npx dmnlint reports zero issues.
[ -f .dmnlintrc ] || echo '{ "extends": "dmnlint:recommended" }' > .dmnlintrc
npx --yes dmnlint path/to/decision.dmn
Common rules: label-required (add a name), no-duplicate-requirements (drop the duplicate informationRequirement edge). See references/dmnlint.md for the full rule → fix mapping.
2. Behaviour validation by execution. dmnlint does not understand FEEL, hit-policy correctness, or type matches. Run the decision:
UNIQUE partition / FIRST cascade / COLLECT path. See camunda-process-test.c8ctl deploy decision.dmn process.bpmn --profile=local and start an instance with c8ctl await pi --id MyProcess --variables '{...}' --profile=local. Incidents surface as EXTRACT_VALUE_ERROR (FEEL problem) or DECISION_EVALUATION_FAILED (hit-policy violation). See camunda-process-mgmt.A green BPMN-completes test only proves the decision didn't fail — not that the right rules fired. For behavioural correctness assertions (assertThatDecision, rule-ordinal matching per hit policy, DRG coverage), see references/testing-decisions.md.
<variable> rules, type table, pitfallsdmnlint:recommended rules, rule → fix mapping, common pitfalls beyond what the linter catchesassertThatDecision, rule-ordinal matching, strategy by hit policy, DRG coverage, mock-vs-testGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub camunda/skills --plugin camunda-skills