Hermes Agent Skill Authoring
NousResearch/hermes-agent
Author in-repo SKILL.md files: frontmatter and structure. An agent skill from NousResearch/hermes-agent.
Author Mendix workflows in MDL — user tasks, decisions, parallel splits, jumps, waits and boundary events, with CREATE, ALTER and DROP.
$ npx skills add mendixlabs/mxcli --skill write-workflows -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install mendixlabs/mxcli write-workflows --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/mendixlabs/mxcli.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/mendix/write-workflows .claude/skills/write-workflows && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "write-workflows" agent skill from https://github.com/mendixlabs/mxcli/tree/main/.claude/skills/mendix/write-workflows into .claude/skills/write-workflows/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "write-workflows", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/mendixlabs/mxcli/tree/main/.claude/skills/mendix/write-workflowsType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add mendixlabs/mxcli --skill write-workflows -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install mendixlabs/mxcli write-workflows --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/mendixlabs/mxcli.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/mendix/write-workflows .agents/skills/write-workflows && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "write-workflows" agent skill from https://github.com/mendixlabs/mxcli/tree/main/.claude/skills/mendix/write-workflows into .agents/skills/write-workflows/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "write-workflows", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add mendixlabs/mxcli --skill write-workflows -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install mendixlabs/mxcli write-workflows --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/mendixlabs/mxcli.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/mendix/write-workflows .cursor/skills/write-workflows && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "write-workflows" agent skill from https://github.com/mendixlabs/mxcli/tree/main/.claude/skills/mendix/write-workflows into .cursor/skills/write-workflows/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "write-workflows", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/mendixlabs/mxcli.git --path .claude/skills/mendix/write-workflows--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add mendixlabs/mxcli --skill write-workflows -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install mendixlabs/mxcli write-workflows --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/mendixlabs/mxcli.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/mendix/write-workflows .gemini/skills/write-workflows && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "write-workflows" agent skill from https://github.com/mendixlabs/mxcli/tree/main/.claude/skills/mendix/write-workflows into .gemini/skills/write-workflows/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "write-workflows", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install mendixlabs/mxcli write-workflowsInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add mendixlabs/mxcli --skill write-workflows -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/mendixlabs/mxcli.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/mendix/write-workflows .github/skills/write-workflows && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "write-workflows" agent skill from https://github.com/mendixlabs/mxcli/tree/main/.claude/skills/mendix/write-workflows into .github/skills/write-workflows/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "write-workflows", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add mendixlabs/mxcli --skill write-workflows -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install mendixlabs/mxcli write-workflows --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/mendixlabs/mxcli.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/mendix/write-workflows .opencode/skills/write-workflows && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "write-workflows" agent skill from https://github.com/mendixlabs/mxcli/tree/main/.claude/skills/mendix/write-workflows into .opencode/skills/write-workflows/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "write-workflows", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
write-workflowsAuthor Mendix workflows in MDL — user tasks, decisions, parallel splits, jumps, waits and boundary events, with CREATE, ALTER and DROP.
Write Workflows is an agent skill from mendixlabs/mxcli. Author Mendix workflows in MDL — user tasks, decisions, parallel splits, jumps, waits and boundary events, with CREATE, ALTER and DROP. Use when building a business process with human steps, timers or parallel branches.
Its SKILL.md is about 8.7k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
The repository describes itself as: Mendix cli tool, a headless way to work with Mendix projects. Enables Mendix projects for use with 3rd party agentic coding tools like Claude Code and Copilot. Includes a… The licence is Apache-2.0.
Read from SKILL.md and the folder at commit a924d11. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are sql, bash and mdl).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Write Workflows loads about 8.7k tokens when it runs. Until then it costs about 59 tokens; SKILL.md has 4,095 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from mendixlabs/mxcli at commit a924d11, republished under its Apache-2.0 licence (© mendixlabs). 4,095 words, ~8,680 tokens.
.claude/skills/write-workflows/SKILL.md (or your agent's skills folder).Guidance for authoring workflows in Mendix projects with MDL — not just
reading them. CREATE WORKFLOW / DROP WORKFLOW / ALTER WORKFLOW are fully
supported and build in Studio Pro. Workflows are not read-only in mxcli; do
not punt workflow creation to Studio Pro.
ALTER WORKFLOW).DESCRIBE WORKFLOW output (round-trippable).A workflow is a Workflows$Workflow unit driven by a context entity: the
persistent entity each workflow instance is about (the Expense being approved,
the LeaveRequest being reviewed). User tasks render a page bound to
System.WorkflowUserTask.
The header options may be written in any order — each at most once — and the
body must close with END WORKFLOW. (They used to be order-sensitive, in
exactly the sequence below; a clause written out of place failed with
mismatched input 'DISPLAY' expecting {ON, BEGIN, EXPORT, DUE, OVERVIEW}, which
named neither the clause nor the rule. See ako/mxcli#586.)
mdl 1;
create workflow Module.ApprovalFlow
parameter $Context: Module.Request -- REQUIRED: must be a $-variable + context entity
display 'Request Approval' -- optional human-readable name
description 'Approves incoming requests' -- optional
export level Hidden -- optional: Hidden | API (default Hidden)
overview page Module.WF_Overview -- optional; takes a System.Workflow param
on workflow events (UserTaskStarted, UserTaskEnded) -- optional, repeatable
microflow Module.ACT_AuditTask as 'Task audit'
on any workflow event microflow Module.ACT_LogEvent -- every type this Mendix version has
begin
-- activities here, each terminated with ;
end workflow;Clause order does not matter, but repetition is refused. A workflow's header clauses and a user task's clauses are a set: any order, each at most once. Writing one twice is reported by name —
line 5:2: duplicate DISPLAY clause on workflow Module.ApprovalFlow
(already given on line 4) — each clause may appear at most once, in any orderThree clauses are list-valued and accumulate instead: the header's
on workflow event(s) handlers, and a task's outcomes and boundary event.
The two targeting spellings count as one clause — a user task stores one
user source — so targeting microflow … and targeting xpath … on the same
task is a duplicate, not two clauses. It used to be accepted, with the one
written last silently winning.
Two gotchas that trip up first attempts:
PARAMETER takes a $-variable then a context entity: parameter $Context: Module.Entity. parameter Module.Entity and parameter name: Module.Entity
both fail (expecting VARIABLE).end workflow, not end. end; fails (missing WORKFLOW).System.Workflow parameter, not the workflow's
context object. Measured on mxbuild 11.6.6: a page without one is
CE7410 "The selected page 'Overview' should accept a parameter of type 'Workflow'". (The task page takes System.WorkflowUserTask instead —
two different pages, two different parameters.)The context is always stored as WorkflowContext. Whatever you name the
variable in the header, mxcli writes the parameter as WorkflowContext, so
$WorkflowContext/Attribute is the canonical way to reach it in an expression.
The name you declared ($Context above) and any casing of the canonical name
($workflowContext) are rewritten to it on write — in decision conditions, user
task due dates and XPath targeting, wait-for-timer delays, and with (…)
parameter mappings. Anything else is an undefined variable and Mendix fails the
build with CE0117 "Error(s) in expression.".
create or modify workflow … is supported (create or replace is its deprecated spelling, MDL-DEPR001).
Expressions are bare, as everywhere in MDL: a decision's condition, a timer's
delay, a due date (decision $WorkflowContext/Total > 1000, due date addDays([%CurrentDateTime%], 3)). The older string form (decision '…') still
parses and warns MDL-DEPR080; mxcli fmt --upgrade rewrites it.
Every activity statement ends with ;. Blocks { … } nest a sub-flow.
mdl 1;
create or modify workflow Module.ApprovalFlow
parameter $Context: Module.Request
begin
-- User task: renders a page, offers named outcomes (branches)
user task Review 'Review the request'
page Module.ReviewPage
targeting users microflow Module.ACT_Reviewers -- or: targeting users xpath [Active = true()]
on created microflow Module.ACT_AssignReviewer -- optional: runs when the task is created
description 'Please review'
outcomes
'Approve' { call microflow Module.ACT_Process; }
'Reject' { call microflow Module.ACT_Notify; };
-- Multi user task: same clauses, one task per targeted user
multi user task GroupSignoff 'Group sign-off'
page Module.ReviewPage
outcomes 'Done' { };
-- Call a microflow (server logic); optional name, parameter mapping + outcomes
call microflow Module.ACT_Validate(Item = $WorkflowContext) as callMicroflow1;
-- Decision: a boolean or enum exclusive split. The name is optional; give one
-- when a `jump to` targets it.
decision decision1 $WorkflowContext/Total > 1000
outcomes
true -> { call microflow Module.ACT_Escalate; }
false -> { call microflow Module.ACT_AutoApprove; };
-- An enum decision: each outcome is a FULLY QUALIFIED enumeration value
-- (Module.Enumeration.Value), plus one '' outcome for "none of the above".
decision decision2 $WorkflowContext/Status
outcomes
'Module.ENUM_Status.Approved' -> { }
'Module.ENUM_Status.Rejected' -> { }
'' -> { };
-- Parallel split: independent branches run concurrently
parallel split split1
path 1 { call microflow Module.ACT_Notify; }
path 2 { call microflow Module.ACT_Log; };
-- Wait for a timer, then continue (duration is a Mendix expression)
wait for timer timer1 addHours([%CurrentDateTime%], 1);
-- Wait for an external notification (e.g. an event)
wait for notification waitForNotification1;
-- An intermediate notification event (Mendix 11.11+): what `notify workflow`
-- targets by name
notification DocumentsReceived caption 'Documents received';
-- Loop back, or stop the whole workflow, from inside an outcome. A `jump to`
-- and an `end workflow` must each END their path, so neither can close the
-- main flow itself (CE6679 / CE6671).
user task Confirm 'Confirm the booking'
page Module.ReviewPage
outcomes
'Redo' { jump to Review; }
'Cancel' { end workflow caption 'Cancelled'; }
'Done' { };
-- Call a sub-workflow
call workflow Module.SubProcess as callWorkflow1 caption 'delegate';
end workflow;Notes attach to an activity with @annotation '…' on the line before it,
as in a microflow; the workflow's own note is the header clause
annotation '…', and an event sub-process takes @annotation before
event subprocess. One note per activity; no other @ annotation is accepted.
mdl 1;
create workflow Module.Approve
parameter $WorkflowContext: Module.Request
annotation 'Started from the request form'
begin
@annotation 'Escalates after two days'
user task review 'Review' page Module.Review_Task outcomes 'Done' { };
end workflow;Do NOT use a standalone
annotation '...';statement in a workflow body. It parses, but the note is written into the activity flow, which Mendix loads by constructing every child with aFlowparent — no annotation type takes one, so the resulting.mprcannot be loaded at all.mxclirefuses it (MDL-WF04) at check and exec time. Attach the note to an activity with@annotation.
Boundary events attach a timer to a user task / call-microflow / wait:
mdl 1;
create or modify workflow Module.WithBoundary
parameter $Context: Module.Request
begin
user task Review 'Review'
page Module.ReviewPage
outcomes 'Done' { }
boundary event interrupting timer addDays([%CurrentDateTime%], 3) {
call microflow Module.ACT_Escalate;
};
end workflow;interrupting or non interrupting. A bare boundary event timer writes a type no Mendix 11 runtime has: check and mxbuild pass, and the
runtime then refuses to start the application ("Class
'Workflows$TimerBoundaryEvent' could not be found"). mxcli refuses the bare form
on Mendix 11 (MDL-WF07).'addDays([%CurrentDateTime%], 3)'
— not an ISO duration like 'P3D'.call microflow, as above. Without it the two kinds fail in different places:
an interrupting path is CE0105 at build, and a non-interrupting one builds
cleanly and then stops the runtime from starting ("Expected the flow to end with
an end event"). Use jump to <task> when the path should return to the task.notify workflow
targets it, so it takes a name instead of a delay:
boundary event interrupting notification Withdrawn 'Request withdrawn' { end workflow; }.
The name is unique in the workflow. Only one interrupting boundary event per
activity, of either kind (CE6697, MDL-WF15). alter workflow … { insert into X { boundary event … } } cannot add one yet — restate the workflow.--mcp), Studio Pro dictates how a notification path ends, which
mxbuild does not: an interrupting one ends in end workflow; (in jump to inside
a parallel split), a non-interrupting one runs to its end. mxcli refuses the
other shapes with that remedy, because Studio Pro's constructor would rewrite or
reject them.Event sub-processes are flows outside the main flow, written after the main body.
A notification (11.8+) or a timer (11.13+) starts one while the workflow runs;
interrupting cancels every active path first, non interrupting runs alongside:
mdl 1;
create or modify workflow HR.Leave
parameter $Context: HR.Request
begin
user task Review 'Review' page HR.ReviewPage outcomes 'Approve' { } 'Reject' { };
event subprocess ESP_Cancel 'Cancel request'
on interrupting notification espCancelStart 'Cancel received' {
call microflow HR.ACT_LogCancel;
};
event subprocess ESP_Reminder 'Daily reminder'
on non interrupting timer addDays([%CurrentDateTime%], 1) as espReminderStart {
call microflow HR.ACT_Remind;
};
end workflow;end workflow, a jump to, or branches that all end). A body with
no end is CE0105.jump to stays inside its sub-process — a jump to its own activities or its
start event builds; into another sub-process, or between one and the main flow,
is CE6682 (MDL-WF05).mdl 1;
drop workflow Module.ApprovalFlow;In-place edits go through the workflow mutator — no full rewrite. alter workflow is the generic alter (the same shape as alter page): the operations
go in { … }, properties are set with set ( Key: value ), and a fragment is
written exactly as in create workflow.
mdl 1;
alter workflow Module.ApprovalFlow {
set (Display: 'Updated Approval', DueDate: addDays([%CurrentDateTime%], 7));
set (Page: Module.AltReviewPage, Description: 'Check the amount') on Review;
set (Targeting: xpath [Active = true()]) on Review;
insert before Review { call microflow Module.ACT_Prepare; }
insert after Review { call microflow Module.ACT_Log; call microflow Module.ACT_Notify; }
replace ACT_Validate with { call microflow Module.ACT_Process; }
drop ObsoleteStep;
};Addressing an activity. A target is the activity's name (Review —
describe workflow prints every name) or its caption in quotes
('Review the request'); add @n to choose one of several matches. A name wins
over a caption that repeats it. An ambiguous target is refused, and the error
lists the matches (@1 user task Review, @2 decision Review) — mxcli never
guesses. Every target is resolved before anything changes, so a refused
statement leaves the workflow untouched. The flow's start activity (start1,
caption 'Start') is addressable too, but nothing goes before it — insert before start1 is refused (it would be CE9526); use insert after start1.
Workflow keys: Display, Description, ExportLevel, DueDate,
OverviewPage, Parameter: $WorkflowContext: Module.Entity. Activity keys
(with on <activity>): Page, Description, Targeting: microflow M.F /
Targeting: xpath [ … ], DueDate.
Adding to an activity: insert into. What goes in the braces is the
activity's own clause, as create workflow writes it — and it has to match the
activity kind, because an activity's outcome list is typed:
| Fragment | Writes | Only on |
|---|---|---|
insert into X { outcomes '<name>' { … } } | UserTaskOutcome | a user task |
insert into X { outcomes '<Module.Enum.Value>' -> { … } } (or true, false, default) | …ConditionOutcome | a decision, a call microflow |
insert into X { path { … } } (path n must be the next number) | ParallelSplitOutcome | a parallel split |
insert into X { boundary event interrupting timer <expr> { … } } | a boundary event | user task, call microflow, call workflow, wait for notification |
Aim one at the wrong kind and the outcome lands in a list that cannot hold it,
which is not a build error: the project stops loading, so Studio Pro will
not open it and mx check dies before it validates anything (ako/mxcli#415).
mxcli refuses all of these — at check --references and at exec, which call
the same function — and the refusal names the fragment that fits the target.
Removing a member: drop X outcome 'Reject', drop Decision1 outcome true
(false, default), drop Split1 path 2, drop X boundary event. Removing a
branch cannot write a wrong type; it leaves an ordinary build error (CE6686)
rather than an unloadable project. path n addresses a parallel split only
— on a user task it used to delete the n-th outcome (ako/mxcli#791) and is now
refused; drop a user task's outcome by its value. drop X boundary event names
no event, so on an activity with several it is refused under mdl 1 (under
mdl 0 it drops the first and warns MDL-V1-BOUNDARYDROP).
The old per-action statements (alter workflow M.W set display 'X';, set activity X page …, insert outcome 'N' on X { }, drop path 'Path 2' on X)
still parse and warn MDL-DEPR140–149; mxcli fmt --upgrade rewrites them.
See mdl-examples/doctype-tests/24-workflow-examples.mdl for the full surface.
DESCRIBE WORKFLOW Module.Name emits executable, re-runnable MDL — user
tasks, decisions, splits, jump-to targets, wait activities and boundary events
all come back as statements (not comments). You can learn the exact syntax by
describing a Studio-Pro-authored workflow, and describe → drop → exec
reproduces a workflow that builds. (The implicit start/end activities are
omitted, as they are re-synthesised on create.) describe prints
create or modify workflow, and re-running it on the workflow it came from
changes nothing: the rewrite keeps the stored names of the activities MDL cannot
name (Studio Pro's start1, end1, …), the empty flow of an outcome that leads
nowhere, and the empty event sub-process list.
That is for learning the syntax and for workflows your scripts own. To change an
existing Studio Pro workflow, use alter workflow, never drop → exec: that
re-creates the document with new identities and loses anything MDL cannot express
(see choose-edit-mode).
Event sub-processes come back as event subprocess … on … blocks after the main
body, and notification activities and notification boundary events as statements.
jump to depends on themMendix stores JumpToActivity.TargetActivity as an activity name string, not
a pointer — so a jump is only as good as the name it aims at. Every activity type
takes an optional explicit name (as <name> for the two call activities, a bare
name for the rest); without one mxcli derives it from the caption, or from the
called document for call microflow / call workflow.
That default is fine for a workflow written from scratch, and it is why two
decisions sharing a caption used to collide on one name. It is not fine when
reproducing a workflow Studio Pro authored: Studio Pro names activities by type
and ordinal — decision1, split1, callMicroflow1, userTask1,
waitForNotification1 — with no relation to the caption. describe workflow
emits the stored name whenever it is not derivable, so the jump wiring survives a
re-execution; before that it did not, and a jump to decision1 reached MxBuild as
a jump to itself (CE6681, "not possible to jump to end activities or jump-to
activities" — an error naming a different fault). See ako/mxcli#408.
mxcli check resolves every jump against the activity names the script itself
declares (MDL-WF05) and lists the valid targets when one misses.
CREATE OR MODIFY WORKFLOW rebuilds the workflow from the statement,
so anything the script does not restate is deleted — including each boundary
event's whole handler flow. This is the failure that costs real work: it is not
reported by mx check afterwards, because the result is a perfectly valid
workflow that simply no longer does what it did.
mxcli refuses the two cases where that would lose something:
describe workflow now emits for you;The safe way to change one activity in a workflow carrying hand-placed structure
is ALTER WORKFLOW, which mutates in place and touches nothing else.
These run inside a microflow (not in the workflow body) and drive a running
workflow / its tasks. They are easy to miss — there is no complete task:
set task outcome $Task 'Approve'; — completes a System.WorkflowUserTask with a
named outcome. This is how a microflow (e.g. a task page's button) finishes a task
and does the domain work; the outcome branches still record which one was chosen.$Notified = notify workflow $Wf target Module.Workflow.Name; resumes the element
it names — a notification-started event sub-process, a notification activity, a
notification boundary event or a wait for notification. The target is
required: a notify without one fails the build (CE0166, MDL-WF16). Name the
element as Module.Workflow.ElementName; mxcli works out which kind it is and
refuses one a notification cannot reach (a timer start, a user task).open user task $Task, lock workflow $WfDef, and
workflow operation abort|pause|restart|retry|continue $Wf are also statements.
A lock or unlock names its workflow definition ($WfDef or Module.Workflow);
pause all / unpause all after it is Studio Pro's "Pause / Unpause instances".
A bare lock workflow all is refused (MDL-WF17) — it built as CE1825.A common shape: the task page's buttons call a microflow that does the change and
then set task outcome $Task '<Outcome>', leaving the workflow's outcome branch
bodies empty.
The outcome is a literal, by design. Mendix stores
Microflows$SetTaskOutcomeAction.Outcome by name — a reference to one outcome of
the user task, resolved when the app is built — so there is no expression slot to
hold a value computed at runtime. set task outcome $Task $Outcome; is a parse
error (under every language version) that says so. A shared claim-and-complete
microflow, called from every button with the outcome as a parameter, therefore
needs one branch per outcome, each with its own literal:
mdl 1;
create microflow Approvals.ACT_CompleteTask (
$Task: System.WorkflowUserTask,
$Outcome: String
)
begin
change $Task (System.WorkflowUserTask_Assignees = [%CurrentUser%]);
commit $Task;
if $Outcome = 'Approve' then
set task outcome $Task 'Approve';
else
set task outcome $Task 'Reject';
end if;
end;With more outcomes, chain elsif arms, or give each button its own small
microflow that names its outcome — that keeps the outcome checked against the
task when the app is built, which a runtime string never would be.
set task outcome on a task nobody has claimed fails at runtime, and it fails
quietly — the button appears to do nothing and the only trace is in the runtime log:
ERROR - Client: You can't complete this user task, it is not assigned to you.mxcli check and mx check both pass; the build is clean. mxcli check now warns
about it (MDL-WORKFLOW10), but the platform rule is worth knowing rather than
being told.
The trap is that targeting xpath / targeting microflow decides who may SEE a
task — it does not assign it. There is no assign task statement; claiming is a
plain write to the Assignees association, and it must come first:
mdl 1;
create microflow Module.ACT_CompleteTask ( $Task: System.WorkflowUserTask )
begin
change $Task (System.WorkflowUserTask_Assignees = [%CurrentUser%]);
commit $Task;
set task outcome $Task 'Plan';
end;If the task is claimed somewhere else — earlier in the process, or in a microflow this one calls — the warning does not apply.
Related: WorkflowUserTask.Name holds the task's CAPTION, not the activity
name. A task declared user task "ReviewAndPlan" 'Review and plan' stores
Name = 'Review and plan', so routing an inbox on the activity name silently never
matches. Route on your own entity's status instead.
The System module's enumerations are not in the project file — Mendix ships
them with the platform — so mxcli synthesizes them from its own table of platform
definitions. describe enumeration System.WorkflowUserTaskState and
list enumerations report them, read-only:
mxcli -p app.mpr describe enumeration System.WorkflowUserTaskStateThey used to return nothing, which is why guessing a value and hitting CE1613
"The selected enumeration value no longer exists" was the only way to find out
(mendixlabs/mxcli#1102). Check the values before branching on one — they are
case-sensitive, and WorkflowActivityState (Finished) is a different
enumeration from WorkflowActivityExecutionState (Completed).
Constraining on an attribute ([EndTime = empty] selects open tasks) is still
often the better XPath, but it is no longer a workaround for not knowing the
values. The full list and the System entities are in system-module.
Some workflow state has no MDL spelling, and a rewrite refuses rather than
reset it. An event sub-process and a workflow event handler subscribed to no
event types are set in Studio Pro.
create or modify on a workflow that holds any of them is refused with the
list, and so is alter workflow … { replace X with { … } } on an activity that holds
one. Change such a workflow with alter workflow … { set ( … ) on X; } (it
edits the stored document and keeps the rest) or in Studio Pro.
end workflow ends the whole workflow from inside a branch — the workflow
counterpart of a microflow's return. return; itself is refused in a workflow
(MDL-WF11): inside a { } block it reads as "leave this block", which is
exactly the fallthrough end workflow prevents. Measured placement rules
(mxbuild 11.13, both engines), all checked without a project:
CE1844, MDL-WF08 (a path cannot end the workflow
while the others run; jumping out of a path is refused too, CE6682);CE6671, MDL-WF09;end workflow or jump to,
also through a nested decision — nothing may follow it, not even the end of
the main flow: CE6689, MDL-WF10. Let one path continue; a path that
reaches the end of the workflow needs no end workflow.end workflow is its End.
An outcome left empty does not stop anything — it rejoins the main flow.
caption '…' sets the End's caption, as on every workflow activity (comment '…' is its deprecated alias, MDL-DEPR104).A multi-user task says who must respond and how their outcomes decide:
participants all | <n> | <n> percent, decide by … and await all users,
in any order (see the clause-order note below). The rules (decide by):
consensus fallback '<outcome>', majority more than half fallback '…',
majority most chosen fallback '…', threshold <n> percent|votes fallback '…',
veto '<outcome>', microflow Module.Decide. Omitted means all participants,
consensus falling back to the first outcome, and not waiting. Measured on
mxbuild 11.13:
CE1866) and a veto
needs its outcome (CE1867); check refuses a missing one, and a name
that is not one of the task's outcomes (MDL-WF13);CE5012); its parameters
are free;await all users is refused — each omitted clause would reset it.An AI agent task is call agent microflow (Mendix 11.9+) — the call
microflow statement stored as Workflows$AIAgentTaskActivity, with the same
argument list, as, comment, outcomes and boundary events. The microflow is
where the agent is invoked. Measured on mxbuild 11.13 against the identical
call microflow, one rule differs: its microflow must take a parameter
(CE1590 "Missing parameter"), usually the context object passed as
(Param = $WorkflowContext). Return Boolean or an enumeration to
branch on the answer.
Handler microflows have fixed signatures (measured, mxbuild 11.13):
on created microflow takes exactly System.WorkflowUserTask and the context
entity, in either order — anything else is CE6683 — and returns nothing
(CE5012).System.WorkflowEvent,
System.WorkflowRecord and System.WorkflowActivityRecord, in any order
(CE6691).MDL-WF12) and a type
the project's version does not have. The list is in mxcli syntax workflow.event-handlers.on any workflow event stores the full list for the project's version (Studio
Pro stores a list, not a flag), so it needs Mendix 11.6+; name the types on
older projects.A user task needs a task page to be useful; without one Mendix flags the
task (CE1834). Bind the page to System.WorkflowUserTask.
The task page takes the TASK, not the workflow's context object. It must
declare a System.WorkflowUserTask parameter: a page with no parameters is
CE7410, a page whose parameters are all something else (the usual mistake:
the context entity) is CE7412. Other parameters may sit alongside the task
one — that builds clean. Multi-user tasks follow the same rule.
A targeting microflow takes exactly two parameters: System.Workflow and
the workflow's context entity, in either order. One parameter, none, or a
third is CE6677. The context parameter may be typed to a generalization of
the context entity, not a specialization. targeting groups microflow takes
the same two and returns a list of System.WorkflowGroup; users targeting
returns a list of System.User.
mxcli check --references reports both signatures before anything is
written, for pages and microflows in the project or created earlier in the
same script (measured on Mendix 11.13; not applied to older projects). exec
refuses the workflow statement itself, so the workflow is never written — but
the statements before it in the script already are. Run check --references
first. Plain mxcli check without a project cannot see these.
A user task / decision with a single outcome and no activity can trip
CE1876 — give each branch a body or a distinct outcome.
An enum decision's outcome must be Module.Enumeration.Value. Mendix
stores it as an EnumerationValueIdentifier and parses it when the project is
loaded, before any consistency check — so a short name is not a build
error with a CE number, it leaves a project Studio Pro and mxbuild cannot open
(StorageLoadException). Measured: 'Approved' and 'Status.Approved' both
make the project unloadable; 'Sales.ENUM_Status.Approved' checks at 0
errors. Shortening it because the enumeration is in the same module does not
work. mxcli check refuses all three of these as MDL-WF03, and exec
refuses to run a script it flags.
An enum decision also needs one '' -> { } outcome for "none of the
above": Mendix generates one outcome per enumeration value plus the empty one,
and MxBuild compares the stored set against that, so anything else is CE6686
("Regenerate the outcomes"). check reports a missing one as MDL-WF06. It
applies equally to a call microflow activity branching on an enumeration
return, and to a decision introduced by ALTER WORKFLOW … INSERT AFTER /
REPLACE ACTIVITY. A required (not null) attribute does not exempt it —
measured, the empty outcome is still required. Boolean (true/false)
decisions do not take one.
Arguments go right after the callee, as bare expressions, like every other
call: call microflow HR.Escalate(Request = $WorkflowContext) as callMicroflow1.
The older with (Request = '$WorkflowContext'), the expression inside a
string, still parses with the same meaning but is deprecated (MDL-DEPR008);
mxcli fmt --upgrade rewrites it.
The context Parameter entity must be persistent.
Write the context variable as $WorkflowContext, matching the parameter
name exactly. Mendix expressions are case-sensitive on 11.9+, so a lowercase
$workflowContext is an undefined variable and yields CE0117.
A workflow's characteristic failures are runtime failures — an instance that
starts and stops, a task that never reaches an inbox, a task page that renders
blank. None of them is visible to mxcli check, mxcli lint or mx check,
which all validate the model rather than the data the model no longer matches.
So do not stop at "it builds".
Everything needed is already a skill — read the one you need rather than hand-rolling admin-API calls:
| To see | Read |
|---|---|
| Live instances and open tasks (OQL against the running app) | verify-with-oql, write-oql-queries |
| The exception that stopped an instance | analyze-runtime — run --local tees the runtime log to <projectDir>/.mxcli/runtime.log |
System.Workflow / System.WorkflowUserTask / System.WorkflowDefinition shapes | system-module |
| Driving a task end to end and asserting the result | test-app, run-local |
Raw admin API, incl. POST /dev/preview_execute_oql | runtime-admin-api |
Two traps worth knowing before you start:
Trying to compare VoidConditionValue$('') to BooleanValue('true'). mxcli check catches this as
MDL004 — so do not skip it, and do not reach for --no-check to get past
it. Read the message in the order it is written: the receiver is the stored
outcome's condition, the argument is what the microflow actually returned../bin/mxcli check script.mdl # syntax + activity grammar
./bin/mxcli check script.mdl -p app.mpr --references # entity/page/microflow refs existThen list workflows (lists the workflow, its parameter entity, and activity
count) and, if Docker is available, mxcli docker build -p app.mpr for the full
Studio-Pro validation.
© mendixlabs, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .claude/skills/mendix/write-workflows of mendixlabs/mxcli.
Open the folder on GitHubat commit a924d11
Write Workflows next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Write Workflows this skillmendixlabs/mxcli | 128 | — | ~8.7k | Automated safety check: Pass | Apache-2.0 | |
| Hermes Agent Skill AuthoringNousResearch/hermes-agent | 252k | — | ~3.6k | Automated safety check: Pass | MIT | |
| Configuring Oauth2 Authorization Flowmukul975/Anthropic-Cybersecurity-Skills | 34k | — | ~1.7k | Automated safety check: Pass | Apache-2.0 | |
| Implementing GCP Binary Authorizationmukul975/Anthropic-Cybersecurity-Skills | 34k | — | ~2k | Automated safety check: Pass | Apache-2.0 | |
| Collectors Authoringnetdata/netdata | 81k | — | ~1.9k | Automated safety check: Pass | GPL-3.0 | |
| Parallel Execution Optimizeraffaan-m/ECC | 274k | 1 repos | ~712 | Automated safety check: Pass | MIT |
NousResearch/hermes-agent
Author in-repo SKILL.md files: frontmatter and structure. An agent skill from NousResearch/hermes-agent.
mukul975/Anthropic-Cybersecurity-Skills
Configures secure OAuth 2.0 authorization flows, including Authorization Code with PKCE, Client Credentials, and Device Authorization Grant, covering flow selection, PKCE implementation, token…
mukul975/Anthropic-Cybersecurity-Skills
Implements GCP Binary Authorization end to end, including creating KMS-backed attestors, Container Analysis notes, deploy-time policies, and signing image attestations, so that only trusted…
netdata/netdata
Author, modify, or review Netdata collectors across Go, IBM, C, Rust and external plugins.
affaan-m/ECC
Speed up a task by turning it into a dependency graph of parallel lanes with a lane matrix, batched reads and checks, write surfaces isolated by file, worktree, branch, or service, and a final…
mukul975/Anthropic-Cybersecurity-Skills
Drive a federal system through the NIST Risk Management Framework (SP 800-37 Rev 2) to an Authorization to Operate (ATO): Prepare, Categorize (FIPS 199), Select a control baseline (FIPS 200 / SP…
mendixlabs/mxcli
Push OData query options into the SQL of a Mendix resource served by a read microflow, so $filter, $orderby, $top, $skip, $count and the key lookup reach the database instead of being silently…
mendixlabs/mxcli
Chart a Mendix app with Vega-Lite through a pluggable widget that takes the specification and the data as separate properties, so the model emits rows and never assembles a chart payload.
mendixlabs/mxcli
Author Mendix AI agent documents in MDL — Model, Knowledge Base, Consumed MCP Service and Agent, with variables, tools and multi-line prompts.
mendixlabs/mxcli
Run set-based INSERT, UPDATE and DELETE against Mendix entities through OQL statements, which the runtime supports and Studio Pro cannot author.
mendixlabs/mxcli
Stand up an HTTP endpoint you control instead of a live third-party API, and point the Mendix app at it — Prism from an OpenAPI contract, a constant swap, or a forward proxy.
mendixlabs/mxcli
Call external REST APIs from Mendix — the three approaches (inline REST CALL, consumed REST client document, generated from OpenAPI) and how to choose.
Author Mendix workflows in MDL — user tasks, decisions, parallel splits, jumps, waits and boundary events, with CREATE, ALTER and DROP. Write Workflows is an agent skill from mendixlabs/mxcli. Author Mendix workflows in MDL — user tasks, decisions, parallel splits, jumps, waits and boundary events, with CREATE, ALTER and DROP.
Write Workflows fits situations like: building a business process with human steps; parallel branches.
Run `npx skills add mendixlabs/mxcli --skill write-workflows -a claude-code`. Or copy the skill folder (.claude/skills/mendix/write-workflows in mendixlabs/mxcli) into .claude/skills/write-workflows in your project. Claude Code loads it when a task matches its description.
Run `npx skills add mendixlabs/mxcli --skill write-workflows -a codex`. Or copy the skill folder (.claude/skills/mendix/write-workflows in mendixlabs/mxcli) into .agents/skills/write-workflows in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add mendixlabs/mxcli --skill write-workflows -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/write-workflows, .gemini/skills/write-workflows, .github/skills/write-workflows and .opencode/skills/write-workflows in your project.
SKILL.md names no scripts, command-line tools or credentials: Write Workflows is instructions for the agent only.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Write Workflows is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 8.7k tokens (SKILL.md is roughly 35k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Write Workflows: Hermes Agent Skill Authoring (NousResearch/hermes-agent, 252k stars), Configuring Oauth2 Authorization Flow (mukul975/Anthropic-Cybersecurity-Skills, 34k stars), Implementing GCP Binary Authorization (mukul975/Anthropic-Cybersecurity-Skills, 34k stars) and Collectors Authoring (netdata/netdata, 81k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
mendixlabs (a GitHub organization) maintains it in mendixlabs/mxcli, which has 128 GitHub stars. The repository holds 75 skills in this directory. The repository was last updated on October 7, 2026.
Source: mendixlabs/mxcli on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.