---
name: eca-guide
description: >
  Drupal ECA (Events-Conditions-Actions) documentation and knowledge base.
  Use this skill when working with ECA models, automating Drupal behavior
  through events and actions, configuring ECA plugins, debugging ECA
  processing, or building no-code/low-code workflows in Drupal 11.3+.
  Also trigger when the user asks about: ECA tokens, gateways, loops,
  custom events, entity events, form manipulation, access control, cron
  automation, endpoints, content moderation with ECA, ECA sub-modules
  (eca_content, eca_form, eca_user, eca_views, eca_workflow, eca_commerce,
  eca_endpoint, eca_access, etc.), the Workflow Modeler, BPMN.iO modeler,
  or importing/exporting ECA models. Even if the user does not say "ECA"
  explicitly, trigger this skill if they describe wanting to react to
  Drupal events and execute actions conditionally.
---

# Drupal ECA Guide

## Accessing ECA Documentation

The full ECA documentation is published at <https://ecaguide.org>. There
are several machine-readable access methods available for agents:

### MCP Server (recommended for agents)

A public Model Context Protocol server is available at:

```
https://ecaguide.org/mcp
```

This server exposes three tools:

| Tool                        | Description                                                                         |
|-----------------------------|-------------------------------------------------------------------------------------|
| `search_docs(query, top_k)` | BM25 keyword search across all documentation. Returns ranked results with excerpts. |
| `get_page(path)`            | Read a specific page by path (e.g. `eca/concepts/events/index.md`).                 |
| `list_sections()`           | Returns the documentation index listing all sections and pages.                     |

To use the public server, configure your agent with:

```json
{
  "mcpServers": {
    "eca-guide": {
      "url": "https://ecaguide.org/mcp"
    }
  }
}
```

To run the MCP server locally (for offline use or development), clone the
documentation repository and run:

```shell
pip install mcp>=1.0.0
python mcp/server.py --site-dir site
```

Local stdio configuration for agents:

```json
{
  "mcpServers": {
    "eca-guide": {
      "command": "python",
      "args": ["mcp/server.py", "--site-dir", "site"],
      "cwd": "/path/to/eca-mkdocs"
    }
  }
}
```

The local server can also run as an HTTP endpoint:

```shell
python mcp/server.py --site-dir site --transport http --port 8808
```

### llms.txt (lightweight alternative)

The site publishes LLM-optimized content at:

- `https://ecaguide.org/llms.txt` -- structured index of all pages with
  descriptions. Use this to discover what documentation exists and then
  fetch individual pages.
- `https://ecaguide.org/llms-full.txt` -- full documentation content in a
  single file (~151K words). Use when you need comprehensive context.

Individual pages are also available as clean Markdown by appending `.md` to
the URL path (e.g. `https://ecaguide.org/eca/concepts/events/index.md`).

### Plugin Reference

The complete plugin reference (all events, conditions, and actions) is
auto-generated and available at `https://ecaguide.org/plugins/`. For
details on a specific plugin, use the MCP server's `search_docs` or
`get_page` tools, or fetch the page directly via its URL with `.md`
appended.

## What is ECA?

ECA (Events - Conditions - Actions) is the recommended rules engine for
Drupal 11.3+. It processes business logic models by subscribing to
Drupal's Symfony event system. When an event fires, ECA evaluates
conditions and executes actions accordingly.

Key characteristics:

- Requires Drupal 11.3 or later.
- Models are Drupal config entities, fully compatible with config sync
  and Drush.
- The processing engine (`eca` module) runs without any UI -- modelers
  are separate modules managed through the Modeler API.
- The Workflow Modeler (React Flow-based) is the recommended visual
  editor.
- ~500 actions, ~70 conditions, ~200 events available across core and
  contrib.
- Extensible via PHP plugins -- events, conditions, and actions are all
  Drupal plugin types.

## Architecture

Each ECA model is stored as a single config entity:

- `eca.eca.[MODEL_ID]` -- contains all events, conditions, actions,
  gateways, and modeler data. This is what ECA uses at runtime and
  what modelers read and write when editing.

The Modeler API (`modeler_api` module) provides the framework for
visual editors to interact with ECA models. It is a dependency of
`eca_ui` and is installed automatically. On production sites, modelers
and `eca_ui` can be disabled -- the processing engine runs standalone.

## Installation

```shell
# Recommended: use the Starterkit recipe
composer require drupal/eca_starterkit
drush recipe ../recipes/eca_starterkit

# Or manual install:
composer require drupal/eca drupal/modeler
drush en eca eca_ui modeler
# Enable sub-modules as needed, e.g.:
drush en eca_content eca_form eca_user eca_views eca_misc
```

The `modeler_api` module is installed automatically as a dependency of
`eca_ui`. The Workflow Modeler (`drupal/modeler`) is the recommended
visual editor.

Admin UI path: `/admin/config/workflow/eca`

## Core Concepts

### Events

Events are the starting point of every ECA model -- triggers that tell
ECA to begin processing. Events are Symfony events dispatched by Drupal
core or contrib modules. ECA subscribes to all events and checks them
against enabled models.

Common categories: content entity events (presave, insert, update,
delete), user events (login, logout, register), form events (build,
validate, submit), cron events, custom events, and request/response
(kernel) events.

Most events provide tokens automatically. Entity events provide the
entity as `entity` and also under its type name (e.g. `node`, `user`).
The tokens `user` and `current_user` are always available.

### Conditions

Conditions are yes/no checks attached to connections (edges) between
components. They determine whether a path of actions should execute.
Conditions never modify data.

Key points:

- Conditions go on connections, not as standalone nodes on the canvas.
- Every condition can be negated (inverted).
- AND logic: multiple conditions on the same connection or chained in
  sequence.
- OR logic: separate connections from the same source to the same
  target, each with a different condition.

Common conditions: scalar comparison, entity type and bundle check,
user role check, entity field value check, route match.

### Actions

Actions perform the actual work: creating content, sending emails,
modifying entities, setting token values, redirecting users, etc.

Key points:

- Actions execute sequentially in connection order.
- Many actions produce tokens (check the "Token name" field).
- Modifying an entity does not save it automatically -- use a separate
  "Entity: save" action.
- Actions from non-ECA modules may need the "Replace tokens" field set
  to "yes" for token replacement to work.

### Tokens

Tokens are variables that store values during ECA processing. They use
the syntax `[token_name:property]` in configuration fields that say
"This property supports tokens."

Important rules:

- Token names (without brackets) are used in "Token name" fields.
- Tokens are scoped to the current event process -- they do not persist
  after processing completes.
- `[entity:field_name]` returns the rendered value;
  `[entity:field_name:value]` returns the raw value.
- Use dot notation for multi-value field deltas:
  `field_skills.0.target_id` (not bracket notation, which conflicts
  with token syntax).
- The `:value` suffix extracts the raw scalar from typed data objects.
- Nested tokens are not replaced automatically -- use the "Token:
  replace" action for recursive replacement.

For persistent storage, use the key-value store, state, temp store,
config, or parameters actions.

### Custom Events

User-defined events triggered from within ECA models. Used for
modularity, looping, and reusable sub-workflows.

Two types:

- Custom event: basic, receives forwarded tokens.
- Entity-aware custom event: also carries an entity (always available
  as `entity` token).

Trigger with the "Trigger custom event" action or via Drush:

```shell
drush eca:trigger:custom-event my_event_id
```

Always list required tokens in the "Tokens to forward" field.

### Entity Event Order

When an entity is saved, events fire in this order:

1. Initialize content entity (default field values populated)
2. Presave content entity (last chance to modify before DB write)
3. Physical save to database
4. Insert (new) or Update (existing) content entity

Use Presave to modify the entity being saved (do NOT add a save action
in Presave -- it causes infinite loops). Use Insert/Update for actions
that need the entity fully persisted.

### Gateways

Gateways combine conditions or branch execution paths. The current
gateway implementation is not fully BPMN-compliant:

- All outgoing paths execute sequentially (no true exclusive logic).
- Multiple incoming paths each trigger independent processing.
- Use explicit conditions on outgoing paths for branching.

### Loops

ECA has no dedicated loop element. Patterns for iteration:

- Execute a Views query, which triggers a custom event per result
  entity.
- Use "List: loop through items" to iterate over a list token.
- Use recursive custom events for conditional loops (ensure a
  termination condition to avoid infinite loops).

### Permissions

ECA models execute under the current user's permissions:

- Web requests: logged-in user (or Anonymous).
- Cron/Drush: Anonymous (UID 0) by default.

To elevate permissions:

- Use "User: switch current account" to switch to a specific UID.
- Use "User: switch to service user" for a globally configured
  service account.
- Configure a global execution user in ECA settings.

The original user is available as `[session_user]` during a switch.

## ECA Sub-Modules

Enable only what you need:

| Sub-module     | Key capability                                                                  |
|----------------|---------------------------------------------------------------------------------|
| `eca_base`     | Core: cron, custom events, tokens, key-value stores, lists, state               |
| `eca_content`  | Content entity lifecycle: presave, insert, update, delete, load, view, validate |
| `eca_form`     | Form API: build, validate, submit, field manipulation                           |
| `eca_user`     | User events: login, logout, register, cancel, role changes                      |
| `eca_access`   | Entity/field access control                                                     |
| `eca_config`   | React to config save/delete/import/rename                                       |
| `eca_endpoint` | Custom HTTP endpoints with full request/response control                        |
| `eca_cache`    | Read/write/invalidate cache items                                               |
| `eca_views`    | Execute Views queries, export results                                           |
| `eca_workflow` | Content moderation / workflow transitions                                       |
| `eca_misc`     | Kernel events, route events, miscellaneous Drupal core events                   |
| `eca_queue`    | Async processing via Drupal's queue system                                      |
| `eca_log`      | React to and create log messages                                                |
| `eca_render`   | Manipulate render arrays                                                        |
| `eca_file`     | File rename and write operations                                                |

For the full list of contrib modules extending ECA (including Commerce,
AI, Webform, Flag, and 60+ others), read `references/modules.md`.

## Debugging

Three approaches:

1. **Visual debug mode** (Workflow Modeler): Enable at ECA Settings
   or click the Test button in the modeler. Shows detailed token data
   at every processing step.
2. **Database logging**: Enable `dblog`, set ECA log level to Debug at
   `/admin/config/workflow/eca/settings`. Review at the ECA Log page.
3. **Webprofiler**: Per-request isolation of ECA log messages. Requires
   `eca_webprofiler` module.

Disable debug mode after use -- it has significant performance impact:

```shell
drush state:set _eca_internal_debug_mode 0
```

## Troubleshooting

### Site broken by an ECA model

Add to `settings.php`:

```php
$settings['eca_disable'] = TRUE;
```

Fix the model, then remove the line.

### Model not firing

- Check that the model is enabled (not just saved).
- Verify the correct sub-module is enabled.
- Check event filters -- entity type/bundle must match exactly
  (format: `node article` for the type field).
- Use debugging to check if the event is being received.

### Token not resolving

- Use the "Token: exists" condition to verify availability.
- Tokens only flow forward through connected paths.
- Quote tokens in YAML: `"[node:title]"`.
- Append `:value` for raw scalar values.

### Infinite loops

- Never save an entity inside a Presave event handler for that entity.
- Use conditions or the "Lock: acquire" action to prevent re-entry.
- Consider `eca_queue` for async processing to break recursion.

### Missing plugin when saving

Add `?eca_validation=off` to the model edit URL to temporarily bypass
validation, fix the model, then save normally.

## Importing Models

Three methods:

1. **Recipes** (recommended): `composer require drupal-eca-recipe/eca_lib_XXXX`
   then `drush recipe ../recipes/eca_lib_XXXX`.
2. **Admin UI**: Import an `eca.eca.[MODEL_ID].yml` config file or a
   `.tar.gz` archive at `/admin/config/workflow/eca`.
3. **Config sync**: Place the `eca.eca.[MODEL_ID].yml` config file in
   the sync directory and run `drush config:import`.

## Best Practices

- Group related logic in one model; separate unrelated logic.
- Use descriptive labels on every element (they appear in logs).
- Always quote token references in YAML: `"[node:title]"`.
- Use `Token: set value` for intermediate computed values.
- Create and test models in dev, deploy via config sync.
- On production, disable `eca_ui`, modelers, and `modeler_api` --
  the ECA processing engine runs standalone.
- Run `drush updatedb` after ECA module updates, then re-export config.

## Developing Custom Plugins

ECA provides Drush generators:

```shell
drush en eca_development
drush gen eca-event       # event plugin scaffold
drush gen eca-condition   # condition plugin scaffold
drush gen eca-action      # action plugin scaffold
```

For detailed PHP patterns (custom actions, conditions, events with
derivers, dependency injection, token integration), read
`references/developing-plugins.md`.

## Reference Files

For deeper information, read the appropriate reference file:

- `references/modules.md` -- Full list of ECA sub-modules and contrib
  modules with links
- `references/developing-plugins.md` -- PHP patterns for custom ECA
  plugins
