/docs / workflows / event system

Event System

Event triggers let workflows react to things that happen -- emails arriving, workflows completing, platform changes detected. Events are the connective tissue between workflows, enabling fan-out pipelines and multi-agent coordination.

Event sources

Events can originate from four distinct sources, each representing a different mechanism for producing events within the system.

SourceMechanismExample values
emitActivity calls emit toolemail.customer-service, lead.qualified
watchWatch trigger auto-emitsgws.email.new, gws.calendar.changed
platformPlatform capabilitiescalendar.changed, email.received
systemNebo lifecycleworkflow.{id}.completed, workflow.{id}.failed

Event envelope

Every event flows through the system wrapped in a standard envelope. The payload becomes the triggered workflow's inputs, available as _event_payload.

{
  "source": "email.customer-service",
  "payload": { "from": "j@example.com", "subject": "Order issue" },
  "origin": "workflow:email-triage:run-550e8400",
  "timestamp": 1709740800
}
FieldTypeDescription
sourcestringDot-namespaced event identifier used for matching against trigger sources
payloadobjectArbitrary JSON data passed as _event_payload to the triggered workflow's inputs
originstringTrace identifier showing where the event was produced (workflow:{binding}:run-{id})
timestampnumberUnix epoch seconds when the event was emitted

Source matching

Event triggers use the sources array to define which events activate the workflow. Patterns support exact match and trailing wildcard.

PatternMatches
email.urgentExact match only
email.*Any event starting with email.

A trigger configuration using source matching:

{
  "type": "event",
  "sources": ["email.urgent", "calendar.*"]
}
An empty sources array is valid JSON but the trigger will never fire -- always include at least one source.

Emit namespace

Events emitted from activities use the source name as-is -- there is no automatic namespace prefix. Activities must include the full source name to avoid collisions across agents.

emit(source: "executive-assistant.briefing.ready", payload: {...})
Convention: Prefix event sources with the agent slug to prevent cross-agent collisions. Other agents subscribe to the full source name.

Workflow-level emit

In addition to the emit tool inside activities, workflow bindings support a top-level emit field that fires automatically on completion:

{
  "workflows": {
    "morning-briefing": {
      "trigger": { "type": "schedule", "cron": "0 7 * * *" },
      "description": "Daily morning briefing",
      "activities": [...],
      "emit": "briefing.ready"
    }
  }
}

By convention, prefix with the agent slug (e.g., executive-assistant.briefing.ready) to avoid cross-agent collisions.

Emitting from activities

The emit tool is a built-in tool always available inside activities. It emits an event into the EventBus, where other agents can subscribe to it.

emit(source: "executive-assistant.email.customer-service", payload: {
  "from": "j@example.com",
  "subject": "..."
})

Each emit call is a discrete event. If an activity emits 5 events, each fires independently against all active subscriptions. This enables fan-out pipelines.

Built-in tools

Two tools are always available inside activities:

ToolPurpose
emitEmit an event into the EventBus. Other agents can subscribe to it.
exitStop the workflow early with a reason (clean termination, not failure).

System events

The system automatically emits lifecycle events for every workflow run. These enable workflow chaining -- when workflow A completes, workflow B can trigger.

EventWhen
workflow.{id}.completedA workflow run finishes successfully
workflow.{id}.failedA workflow run fails

System events enable workflow chaining: A completes, then B triggers. For example, a workflow can subscribe to workflow.morning-briefing.completed to run after the morning briefing finishes.

Progress events

In addition to completion events, the engine emits progress events for live monitoring. These events are broadcast over WebSocket, enabling the UI to show real-time workflow progress.

EventWhenPayload
ActivityStartedEach activity begins executingActivity ID, workflow run ID
TaskUpdatedDuring activity executionProgress details, current activity state

Event-only watches

A watch with event set but no activities is valid. It relays plugin output into the EventBus without processing anything inline. This is useful for decoupling event production from event consumption -- one agent produces events, other agents subscribe and react.

{
  "email-relay": {
    "trigger": {
      "type": "watch",
      "plugin": "gws",
      "event": "email.new",
      "command": "gmail +watch --format ndjson"
    },
    "description": "Relay new email events into the EventBus"
  }
}

Other agents subscribe to the emitted events:

{
  "handle-emails": {
    "trigger": { "type": "event", "sources": ["gws.email.new"] },
    "activities": [...]
  }
}
When event is set on a watch trigger, each NDJSON line output by the plugin auto-emits into the EventBus as {plugin}.{event} (e.g., gws.email.new).

Example: email triage pipeline

A complete multi-workflow pipeline using events. The watcher monitors Gmail, triage classifies and emits, and each emission triggers the appropriate handler with the email data as inputs.

{
  "workflows": {
    "email-watcher": {
      "trigger": {
        "type": "watch",
        "plugin": "gws",
        "event": "email.new",
        "command": "gmail +watch --format ndjson"
      },
      "description": "React to new emails in real-time",
      "activities": [
        {
          "id": "triage",
          "intent": "Classify the incoming email and route it",
          "steps": [
            "Read the email content from _watch_payload",
            "Classify as: customer-service, sales-inquiry, or ignore",
            "If not ignore, emit the appropriate event with email data"
          ],
          "token_budget": { "max": 2048 }
        }
      ],
      "budget": { "total_per_run": 2048 }
    },
    "handle-cs": {
      "trigger": { "type": "event", "sources": ["email.customer-service"] },
      "description": "Handle customer service emails",
      "activities": [
        {
          "id": "respond",
          "intent": "Draft a helpful response to the customer service email",
          "skills": ["@acme/skills/cs-templates"],
          "token_budget": { "max": 3000 }
        }
      ],
      "budget": { "total_per_run": 3000 }
    },
    "handle-sales": {
      "trigger": { "type": "event", "sources": ["email.sales-inquiry"] },
      "description": "Handle inbound sales inquiries",
      "activities": [
        {
          "id": "qualify",
          "intent": "Qualify the lead and add to CRM",
          "skills": ["@acme/skills/lead-qualification"],
          "token_budget": { "max": 3000 }
        }
      ],
      "budget": { "total_per_run": 3000 }
    }
  }
}

Read top to bottom: the watcher monitors Gmail. For each email, triage classifies and emits. Each emission triggers the appropriate handler with the email data as inputs.

Validation rules

The following validation rules apply to event-related workflow configuration. Invalid bindings are skipped with a warning -- they do not prevent the agent from loading.

  • Each binding must have a trigger (required)
  • Either ref or activities must be present (one defines what runs)
  • Trigger type must be one of: schedule, heartbeat, event, watch, folder, manual
  • Event triggers should have at least one entry in sources
  • Watch triggers must have a plugin and either event or command
  • Activity IDs must be unique within each binding
  • If budget.total_per_run > 0, the sum of all activity token_budget.max must not exceed it
  • All {{key}} placeholders in commands must match an input key exactly
  • An Agent with no workflows is valid (chat-only + persona + skills)
Lenient parsing: Individual workflow bindings that fail to parse (e.g., invalid trigger format) are skipped with a warning -- they do not prevent the agent from loading. The agent still appears in the UI with its remaining valid workflows.

Related pages

  • Workflows Overview -- workflow binding structure, budget math, and the full workflow model
  • Activities -- how activities execute, context chaining, error handling, and cancellation
  • Triggers -- schedule, heartbeat, event, watch, and manual trigger types