# How the Craft Agents Automation System Triggers Actions Based on Events

> Discover how the Craft Agents automation system triggers actions using an event bus and JSON config to match events, evaluate conditions, and dispatch prompts, webhooks, or logs.

- Repository: [Craft Ai Agents/craft-agents-oss](https://github.com/craft-ai-agents/craft-agents-oss)
- Tags: how-to-guide
- Published: 2026-07-06

---

**The Craft Agents automation system uses a workspace-isolated event bus and declarative JSON configuration to match incoming events against regex or cron patterns, evaluate conditional logic, and dispatch actions through specialized handlers for prompts, webhooks, and logging.**

The Craft Agents open-source repository implements a reactive automation pipeline that transforms workspace events into executable actions. At its core, the system combines a lightweight event bus with a JSON-driven configuration schema to enable event-driven workflows without global mutable state. The entire engine is contained in the `@craft-agents/shared` package and centers around the `AutomationSystem` class.

## Event Bus Architecture and Workspace Isolation

Every `AutomationSystem` instance creates its own **WorkspaceEventBus** to ensure strict isolation between workspaces. This design prevents cross-workspace event leakage and eliminates global mutable state.

In [`packages/shared/src/automations/automation-system.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/automations/automation-system.ts) (lines 65-68), the constructor initializes the bus:

```typescript
this.eventBus = new WorkspaceEventBus(options.workspaceId);

```

Handlers subscribe to this bus using `handler.subscribe(this.eventBus)`, receiving only events emitted within their specific workspace context.

## Configuration Loading and Validation

The system reads automation rules from a workspace-specific [`automations.json`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/automations.json) file. During initialization, `AutomationSystem` validates the configuration, back-fills missing matcher IDs, and compacts the history file.

According to the source code in [`packages/shared/src/automations/automation-system.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/automations/automation-system.ts) (lines 14-27), the constructor handles configuration loading:

```typescript
const config = await loadOrCreateConfig(configPath);
this.configProvider = new ConfigProvider(config);

```

The JSON structure maps event names to arrays of matchers, each containing conditions and action definitions.

## Event Matching Logic

When `eventBus.emit(eventName, payload)` fires, handlers retrieve matching rules via `configProvider.getMatchersForEvent(event)`. The system evaluates matches through two primary functions:

- **`matcherMatches`** – for app events
- **`matcherMatchesSdk`** – for agent events

Both functions check the `enabled` flag, apply regex patterns (`matcher.matcher`) or cron expressions (`matcher.cron`), and evaluate optional conditions via `evaluateConditions`.

In [`packages/shared/src/automations/utils.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/automations/utils.ts) (lines 64-82), the condition evaluator processes time-of-day restrictions, state changes, and logical combinations before allowing the action to proceed.

## Handler Types and Action Execution

The system registers three core handlers during initialization:

1. **PromptHandler** – Processes prompt actions by building sandboxed environments
2. **WebhookHandler** – Executes HTTP calls for webhook actions
3. **EventLogHandler** – Persists events to a history file

### PromptHandler Implementation

When processing prompt actions, `PromptHandler` constructs a sandboxed environment using `buildEnvFromPayload` and expands `${VAR}` placeholders within the prompt text. It parses `@mentions` via `parsePromptReferences` and assembles `PendingPrompt` objects.

As implemented in [`packages/shared/src/automations/handlers/prompt-handler.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/automations/handlers/prompt-handler.ts) (lines 47-62), the handler delivers ready-to-run prompts through the `onPromptsReady` callback supplied during system initialization.

### WebhookHandler and Security

`WebhookHandler` follows a similar flow but uses `buildWebhookEnv` to expose only `CRAFT_WH_*` secrets, ensuring sensitive credentials remain scoped to webhook contexts.

## Scheduler Integration

For time-based automation, the `SchedulerService` periodically emits `SchedulerTick` events when `enableScheduler` is true. The system evaluates cron-based matchers against the current time using `matchesCron`.

In [`packages/shared/src/automations/utils.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/automations/utils.ts) (lines 52-58), the cron matcher determines whether the current minute matches the configured schedule, enabling cron-based automation rules.

## Lifecycle Management

The `AutomationSystem` provides explicit cleanup through its `dispose()` method. This stops the scheduler service, disposes all registered handlers, and clears the internal metadata cache.

According to the source in [`packages/shared/src/automations/automation-system.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/automations/automation-system.ts) (lines 140-155), proper disposal ensures no memory leaks occur when workspace instances are destroyed.

## Implementation Example

Creating an automation system requires configuring the workspace root and event callbacks:

```typescript
import { AutomationSystem } from '@craft-agents/shared/automations/automation-system';

const system = new AutomationSystem({
  workspaceRootPath: '/my/workspace',
  workspaceId: 'ws-123',
  enableScheduler: true,
  onPromptsReady: (prompts) => {
    console.log('Ready prompts:', prompts);
  },
});

```

Configure automations via [`automations.json`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/automations.json):

```json
{
  "automations": {
    "LabelAdd": [
      {
        "id": "a1b2c3",
        "name": "Welcome new label",
        "matcher": "^welcome$",
        "actions": [
          {
            "type": "prompt",
            "prompt": "A new label \"${label}\" was added – should I create a session?",
            "labels": ["auto"],
            "permissionMode": "read"
          }
        ]
      }
    ]
  }
}

```

Emit events from UI components or services:

```typescript
system.eventBus.emit('LabelAdd', {
  workspaceId: 'ws-123',
  sessionId: 'sess-456',
  label: 'welcome',
  timestamp: Date.now(),
});

```

## Summary

- The **WorkspaceEventBus** provides isolated event streaming per workspace, preventing cross-contamination between tenant contexts.
- **Matcher functions** (`matcherMatches`, `matcherMatchesSdk`) evaluate regex patterns, cron schedules, and conditional logic before triggering actions.
- **Three specialized handlers** process matched events: `PromptHandler` for AI prompts, `WebhookHandler` for HTTP callbacks, and `EventLogHandler` for audit trails.
- The system uses **sandboxed environments** (`buildEnvFromPayload`) to safely expand variables and references within automated prompts.
- **Scheduler integration** enables cron-based automation through `SchedulerTick` events evaluated against [`automations.json`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/automations.json) configurations.

## Frequently Asked Questions

### What file format does Craft Agents use for automation configuration?

The system uses a JSON file named [`automations.json`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/automations.json) located in the workspace root. This declarative configuration maps event names to arrays of matcher objects, each containing regex patterns or cron schedules, conditions, and action definitions. The `AutomationSystem` validates this file on startup and back-fills missing matcher IDs automatically.

### How does the system prevent cross-workspace event leakage?

Each workspace receives its own `WorkspaceEventBus` instance created with a unique `workspaceId`. Handlers subscribe only to their specific bus instance, ensuring events emitted in one workspace never propagate to handlers in another. This architecture eliminates global mutable state and enforces strict tenant isolation.

### What types of conditions can be evaluated before triggering an action?

The `evaluateConditions` function supports time-of-day restrictions, state change detection, and logical combinations of multiple criteria. These conditions execute after pattern matching (regex or cron) but before action dispatch, allowing fine-grained control over when automations fire.

### How does the scheduler trigger automated actions?

When `enableScheduler` is true, the `SchedulerService` emits `SchedulerTick` events at regular intervals. The system evaluates these ticks against cron expressions in [`automations.json`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/automations.json) using `matchesCron`. When the current time matches a configured schedule, the system executes the associated actions through the standard handler pipeline.