# Action System

Actions are the cornerstone of Vellum’s approach to modularity, providing a powerful abstraction for decoupled communication between mods. By allowing mods to send and respond to messages without direct dependencies, actions enable a flexible, event-driven system that promotes loose coupling and scalability. This section explains what actions are, how they work, and why they’re a game-changer for non-coupled interaction.

---

## What Are Actions?

Actions are lightweight messages that mods can **dispatch** to signal events or requests, and other mods can **handle** to respond. Each action consists of:
- **Type**: A string that identifies the action (e.g., `'counter:updated'`, `'app:register'`).
- **Detail**: An optional object carrying data relevant to the action (e.g., `{ value: 42 }`).

When an action is dispatched, Vellum finds all registered handlers for that action type and invokes them with the action’s detail. This means mods can communicate without knowing who’s sending or receiving the message—just the action type and data structure matter.

---

## How Actions Work

Actions work like a bulletin board: one mod posts a message (dispatches an action), and any interested mods pick it up (handle it). Here’s the flow:

1. **Dispatching**: A mod uses the toolkit’s `dispatchAction` method to send an action.
   ```javascript
   toolkit.dispatchAction({ type: 'counter:updated', detail: { value: 10 } });
   ```

2. **Handling**: Vellum calls every handler registered for that action type, passing the detail.
   ```javascript
   const updateDisplay = (detail) => console.log(`New value: \${detail.value}`);
   toolkit.dispatchAction({
     type: 'action:register',
     detail: { actionType: 'counter:updated', modName: 'display', handler: updateDisplay }
   });
   ```

3. **Non-Coupled Interaction**: The dispatching mod doesn’t know or care who handles the action, and handlers don’t need to know who sent it.

This creates a **many-to-many communication model** where multiple mods can dispatch the same action type, and multiple mods can respond—without ever referencing each other directly.

---

## Decoupled Message Passing

Actions shine because they abstract away direct mod-to-mod dependencies, replacing them with a shared language of action types and data. This decoupling unlocks several strengths:

- **Independence**: Mods can be developed, added, or removed without breaking other parts of the system, as long as they respect action contracts.
- **Extensibility**: New functionality can plug into existing actions (e.g., a logging mod can handle `'counter:updated'` alongside a display mod).
- **Flexibility**: Actions can carry any data in their `detail`, making them adaptable to diverse use cases.
- **Dynamic Behavior**: Mods can register or unregister handlers at runtime, reacting to the app’s state or user needs.

### Example: Counter and Display Mods
Imagine a counter mod and a display mod:
- **Counter Mod**: Dispatches `'counter:updated'` with `{ value: 5 }` whenever the count changes.
- **Display Mod**: Registers a handler for `'counter:updated'` to update the UI.
- **Logger Mod**: Also handles `'counter:updated'` to log changes.

The counter mod doesn’t know the display or logger exists, and they don’t know about each other. They all just agree on `'counter:updated'` and its detail structure. Add a validator mod later? Just register another handler—no code changes needed elsewhere.

---

## Key Features of Actions

### Registering and Unregistering Handlers
Mods control when they listen using built-in actions:
- **`'action:register'`**: Adds a handler for an action type.
  ```javascript
  toolkit.dispatchAction({
    type: 'action:register',
    detail: { actionType: 'app:register', modName: 'manager', handler: registerApp }
  });
  ```
- **`'action:unregister'`**: Stops listening to an action type.
  ```javascript
  toolkit.dispatchAction({
    type: 'action:unregister',
    detail: { actionType: 'app:register', modName: 'manager' }
  });
  ```

### Multiple Handlers
One action can trigger multiple handlers. For `'counter:updated'`:
- A UI mod updates the screen.
- A sound mod plays a beep.
- A stats mod tracks trends.

This enables **plugin-like behavior** where mods collaborate without coordination.

### Error Resilience
If a handler fails, Vellum logs the error but keeps running other handlers, ensuring one bad mod doesn’t crash the system.

### Project-Defined Semantics
Vellum provides the mechanism, but action types and meanings are up to the project. This lets you define a custom vocabulary (e.g., `'ui:refresh'`, `'data:loaded'`) tailored to your app.

---

## Practical Example

Here’s how actions tie mods together without coupling:

- **App Registration**:
  ```javascript
  // app-counter.mjs
  toolkit.dispatchAction({
    type: 'app:register',
    detail: { id: 'counter', name: 'Counter' }
  });
  ```
  ```javascript
  // mod-app-manager.mjs
  const registerApp = (detail) => console.log(`Registered: \${detail.name}`);
  toolkit.dispatchAction({
    type: 'action:register',
    detail: { actionType: 'app:register', modName: 'app-manager', handler: registerApp }
  });
  ```
- **Result**: The counter app registers itself, and the manager handles it—zero direct references between them.

---

## Why It Matters

Actions turn mods into independent actors that communicate through a shared event system. This abstraction:
- **Reduces Complexity**: No need to wire mods together manually.
- **Boosts Reusability**: Mods can work in any Vellum project that uses the same actions.
- **Enables Collaboration**: Multiple mods can respond to the same event in unique ways, like a symphony of independent instruments.

In short, actions make Vellum mods talk to each other without ever needing to meet—powerful, clean, and endlessly extensible.

---

## Next Steps
- **Learn More**: Explore how to use the toolkit to dispatch actions in [Toolkit API](./toolkit.md).
- **See Examples**: Check out [Examples and Tutorials](./examples/) for real-world action usage.
- **Technical Details**: Refer to the [API Reference](./api-reference.md) for action-related functions.