Help us improve
Share bugs, ideas, or general feedback.
From mcp-companion
Guides creation of Qlerify workflows with BPMN diagrams, lanes, groups, domain events, entities, commands, read models, and bounded contexts using correct tool sequence and $ref paths.
npx claudepluginhub qlerify/qlerify-plugins --plugin mcp-companionHow this skill is triggered — by the user, by Claude, or both
Slash command
/mcp-companion:workflow-creationThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Build well-structured Qlerify workflows by following a specific tool sequence. Skipping steps
Creates BPMN process diagrams using flowchart patterns, including activities, gateways, events, swimlanes, and decision points for workflow documentation.
Creates swimlane Event Models for event-driven systems using Adam Dymitruk's methodology. Generates ASCII or Mermaid diagrams at overview, standard, or detailed depths for design and planning.
Simulates event storming workshops with multi-persona agents to discover domain events, commands, actors, and bounded contexts. Use full-simulation, quick, or guided modes for domain modeling.
Share bugs, ideas, or general feedback.
Build well-structured Qlerify workflows by following a specific tool sequence. Skipping steps or calling tools out of order leads to broken references and incomplete diagrams.
A Qlerify workflow is a BPMN-style diagram combined with domain-driven design (DDD) elements:
Tools use $ref paths to link elements together. The get_workflow tool returns the full workflow specification
where each element has a $ref path:
#/domainEvents/OrderPlaced#/schemas/entities/Order#/schemas/commands/CreateOrder#/schemas/readModels/GetOrderDetailsUse these paths when creating commands, read models, or referencing entities in fields.
$ref path generationEvent names are converted to PascalCase $ref keys:
"Order Placed" → OrderPlaced"Check-in Completed" → CheckInCompleted?, !, &, #, /) break $ref path resolution — avoid them entirelyUse only alphanumeric characters and spaces in event names. If you use hyphens, call get_workflow
afterward to verify the actual $ref key before referencing it in subsequent calls.
Note: Gateway events (bpmn:ExclusiveGateway) may not appear in the get_workflow domainEvents section.
If you need to reference a gateway, call get_workflow to discover its actual $ref path, or use a clean
name without special characters and infer the PascalCase key.
Follow these steps in order. Each step depends on the previous one.
Step 1 — Identify or create the workflow
For an existing workflow, call list_workflows to find it, then get_workflow to understand
its current state. For a new workflow, call create_workflow with a descriptive name.
Step 2 — Create lanes
Every event must belong to a lane. Lanes represent real-world actor roles (people) or Automation (system-triggered actions). Do NOT create lanes for internal services or technical components.
Call create_lane for each actor. Aim for 2-4 lanes.
Lane design rules:
Common patterns:
Step 3 — Create groups
Groups organize events into phases. Call create_group for each phase in chronological order.
Groups are positioned automatically — just create them in the order they should appear. Common patterns:
Step 4 — Create domain events
Build the event flow by chaining calls to create_domain_event. Each event needs:
lane — The lane name (e.g., "Customer")follows — A $ref path to the preceding event, or "start" for flow entry pointstype — Either bpmn:Task (regular event) or bpmn:ExclusiveGateway (decision diamond)Optional parameters:
group — Sets a group boundary starting at this event. Only set on the first event of a new group. Do not set group on subsequent events in the same group.aggregateRoot — A $ref path to an entity (e.g., #/schemas/entities/Order). Links the entity as aggregate root on this event. Set this for every event — see note below.acceptanceCriteria — Array of Given-When-Then acceptance criteria strings.color — Visual color: peach, yellow, green, teal, blue, lavender, pink, grayBuild the flow left-to-right, top-to-bottom, creating events in the order they occur in the business process.
Aggregate root requirement: Every domain event SHOULD have an aggregate root — it identifies which
entity this event primarily affects. If the entity doesn't exist yet when creating the event, set the
aggregate root later in Step 5b using update_domain_event after entities are created. Do not leave
events without aggregate roots.
Step 5a — Create bounded contexts
Create bounded contexts BEFORE entities, so entities can be assigned during creation. Call
create_bounded_context for each logical boundary.
Bounded context design rules:
Examples:
Step 5b — Create entities and link aggregate roots
Call create_entity for each core domain object. Entities must be created before commands and
read models so they can be referenced.
name, dataType, exampleData (3 realistic values), isRequiredrelatedEntity ($ref path like #/schemas/entities/OrderItem) and cardinality to express entity relationships from the owning entity's perspectiveboundedContext parameter (the BC must already exist from Step 5a)string, number, boolean, objectAfter creating entities, update any events that don't have aggregate roots yet:
update_domain_event(domainEvent: "#/domainEvents/OrderPlaced", aggregateRoot: "#/schemas/entities/Order")
Every event must have an aggregate root before proceeding.
Step 6 — Create commands on events
Call create_command for each state-changing operation. Each command is automatically attached
to an event via the required domainEvent parameter (a $ref path like #/domainEvents/OrderPlaced).
This auto-creates the Command card on that event.
hideInForm: trueEvery event should have a command. After creating commands, call get_workflow and verify there
are no events without a command card. Events without commands represent gaps in the business process.
Command field rules (API request payloads):
Commands represent what a caller sends to perform an action. Fields should be flat and simple:
bookingId (string), hotelId (string), customerId (string). Do NOT use relatedEntity for simple ID lookups — it creates nonsensical nested structures like { hotelId: { id: "123" } } instead of the correct { hotelId: "123" }relatedEntity on commands for embedded collections where you need to send multiple fields from a related entity (e.g., orderItems with productName, quantity, unitPrice)isFilter: truerelatedEntity — if the field ends in "Id", it's a flat string reference, not a nested objectStep 7 — Create read models on events
Call create_read_model for each data retrieval view. Each read model is automatically attached
to an event via the required domainEvent parameter. This auto-creates the Read Model card.
entity ($ref path like #/schemas/entities/Order)cardinality: "one-to-one" for single-record queries, "one-to-many" for list queriesRead model field rules (API response payloads):
Read models represent what the API returns. Fields can be richer than command fields:
isFilter: true for query parameters (what you search/filter by). Filter fields can be cross-entity parameters (e.g., checkInDate, priceMin on a hotel search) — this is expected and validisFilter for returned data fieldsrelatedEntity for composed response data — nested objects make sense in responses (e.g., guest field with relatedEntity Guest containing firstName, lastName, email)guest, hotel, room), NOT with "Id" suffixStep 8 — Validate the domain model
Run validate_domain_model to check for structural issues. This catches field mismatches between
commands/read models and their aggregate root entities.
FIELD_NOT_IN_ENTITY issues on read model filter fields are often expected — cross-entity query parameters (e.g., checkInDate on a Hotel read model) are valid filter fields that don't need to exist on the entityCommon validation issues and fixes:
relatedEntity field to entityguestEmail) → Replace with flat ID ref (guestId) and let the service look up related data internally$ref pathrelatedEntity Usage Summary| Context | Use relatedEntity? | Example |
|---|---|---|
| Command: simple ID lookup | NO — use flat string field | bookingId: "bk-001" |
| Command: embedded collection | YES — multiple fields needed | orderItems: [{ productName, qty, price }] |
| Read Model: composed response | YES — nested joined data | guest: { firstName, lastName, email } |
| Read Model: filter parameter | NO — use flat field with isFilter: true | checkInDate (isFilter) |
| Entity: relationship | YES — defines data model links | order → OrderItem (one-to-many) |
Naming rule: If using relatedEntity, name the field as the entity (guest, hotel, orderItems).
If it's a flat ID reference, name it with "Id" suffix (guestId, hotelId). Never combine "Id" suffix
with relatedEntity.
Lanes: User, Automation | Groups: Create, Read, Update, Delete Flow: User action event → Automation processing event per operation
Lanes: Requester, Approver, Automation | Groups: Submit, Review, Execute Flow: Request submitted → Review pending → Approved/Rejected gateway → Executed
Lanes: Customer, Admin, Automation | Groups per saga step Flow: Customer/Admin actions trigger events, Automation handles cross-service coordination via decision gateways
?, !, &, #./download skill to save the specification to a file. This is much faster than fetching via MCP tools for large workflows.For detailed natural-language descriptions of every MCP tool, parameters, and usage tips:
references/tools.md — Complete tool reference with natural-language descriptions, parameters, and usage tipsFor a complete worked example showing all 8 steps with realistic tool calls and data:
examples/ecommerce-workflow.md — End-to-end e-commerce order workflow creation with 3 lanes, 7 events, 2 entities, 4 commands, 2 read models, a decision gateway, and validation