Signal System

Signal Triggers

Complete guide to signal-based workflow triggers and event-driven workflow initiation in Compozy

Signal triggers enable automatic workflow initiation through event-driven patterns in Compozy, transforming reactive system design from manual orchestration to intelligent automation. Workflows start automatically when specific signals are received, creating sophisticated publish-subscribe architectures that respond to system events, external webhooks, user actions, or signal tasks from distributed workflows. This integration with workflow configuration and the Event API creates the foundation for enterprise-scale reactive architectures.

Enterprise Benefits

Reactive Architecture

Build systems that automatically respond to business events, system alerts, and user actions with zero manual intervention

Loose Coupling

Decouple event producers from consumers using publish-subscribe patterns, enabling independent service evolution

Real-Time Processing

Process events as they occur with sub-second latency using Temporal's distributed execution engine

Schema Validation

Use JSON Schema to validate signal payloads and ensure data integrity

Trigger Architecture

Loading diagram...
  • Signal Publication

    Events are published via Event API, signal tasks, or external integrations

  • Signal Routing

    Dispatcher Workflow routes signals to target workflows using signal name matching and schema validation

  • Child Workflow Execution

    Target workflows start as child workflows with signal payload merged into input context and proper execution tracking

  • Temporal Orchestration

    Child workflows are managed by Temporal with built-in retry, timeout, and state persistence capabilities

Configuration

Understanding signal trigger configuration is essential for building event-driven workflows. Signal triggers are defined in the triggers section of your workflow configuration and support sophisticated filtering and validation using template expressions for precise control over workflow activation.

1

Define Trigger Type

Specify signal trigger in workflow configuration
id: user-registration-handler
version: "1.0"
description: "Handle new user registrations"

triggers:
  - type: signal
    name: "user-registered"
2

Configure Input Schema

Define expected signal payload structure using JSON Schema
input:
  type: object
  properties:
    user_id:
      type: string
      description: "Unique user identifier"
    email:
      type: string
      format: email
    registration_data:
      type: object
      properties:
        source: { type: string }
        plan: { type: string }
  required: [user_id, email]
3

Implement Processing Logic

Define tasks that execute when signal is received
tasks:
  - id: validate-registration
    type: basic
    $use: tool(local::tools.#(id=="user-validator"))
    with:
      user_data: "{{ .workflow.input.registration_data }}"

  - id: create-profile
    type: basic
    $use: agent(local::agents.#(id=="profile-creator"))
    instructions: "Create comprehensive user profile"
    with:
      user_id: "{{ .workflow.input.user_id }}"
      email: "{{ .workflow.input.email }}"
    depends_on: [validate-registration]

Properties

PropertyRequiredDescription
typeYesMust be signal for signal-based triggers. Part of Compozy's workflow trigger system.
nameYesUnique signal identifier matching events sent via Event API or signal tasks. Supports kebab-case naming convention.
schemaNoJSON Schema validation for signal payload. Ensures data integrity and provides clear contracts for signal publishers.

Practical Examples

Explore real-world implementations of signal triggers across different use cases. These examples demonstrate best practices for event-driven workflow design.

This example demonstrates a complete user onboarding workflow triggered by registration events. It showcases validation, parallel processing, and notification patterns commonly used in production systems.

id: user-registration-handler
version: "1.0"
description: "Complete user onboarding triggered by registration events"

triggers:
  - type: signal
    name: "user-registered"

input:
  type: object
  properties:
    user_id:
      type: string
      description: "Unique user identifier"
    email:
      type: string
      format: email
    registration_data:
      type: object
      properties:
        name: { type: string }
        source: { type: string }
        plan: { type: string, enum: ["free", "pro", "enterprise"] }
  required: [user_id, email, registration_data]

tasks:
  - id: parallel-onboarding
    type: parallel
    strategy: best_effort
    tasks:
      - id: validate-registration
        type: basic
        $use: tool(local::tools.#(id=="user-validator"))
        with:
          user_data: "{{ .workflow.input.registration_data }}"
          compliance_check: true

      - id: create-user-profile
        type: basic
        $use: agent(local::agents.#(id=="profile-creator"))
        instructions: |
          Create a comprehensive user profile with:
          - Account preferences based on registration source
          - Default settings for their plan type
          - Personalization recommendations
        with:
          user_id: "{{ .workflow.input.user_id }}"
          email: "{{ .workflow.input.email }}"
          plan: "{{ .workflow.input.registration_data.plan }}"

  - id: route-by-plan
    type: router
    condition: "{{ .workflow.input.registration_data.plan }}"
    routes:
      free:
        type: basic
        $use: tool(local::tools.#(id=="email-sender"))
        with:
          template: "welcome-free"
          to: "{{ .workflow.input.email }}"

      pro:
        type: composite
        tasks:
          - id: send-pro-welcome
            type: basic
            $use: tool(local::tools.#(id=="email-sender"))
            with:
              template: "welcome-pro"
              to: "{{ .workflow.input.email }}"

          - id: schedule-onboarding
            type: signal
            signal:
              id: "schedule-onboarding-call"
              payload:
                user_id: "{{ .workflow.input.user_id }}"
                plan: "pro"
            depends_on: [send-pro-welcome]

      enterprise:
        type: signal
        signal:
          id: "enterprise-onboarding-required"
          payload:
            user_id: "{{ .workflow.input.user_id }}"
            email: "{{ .workflow.input.email }}"
            priority: "high"

    depends_on: [parallel-onboarding]

  - id: notify-completion
    type: signal
    signal:
      id: "onboarding-completed"
      payload:
        user_id: "{{ .workflow.input.user_id }}"
        plan: "{{ .workflow.input.registration_data.plan }}"
        timestamp: "{{ now }}"
    depends_on: [route-by-plan]

Best Practices

Schema Validation

Use JSON Schema validation to ensure signal quality and prevent invalid workflows

Resource Management

Configure concurrency limits and timeouts to maintain system stability under high load

Payload Efficiency

Minimize signal payload size while maintaining necessary context for processing

Monitoring & Metrics

Track trigger rates, execution times, and resource usage for optimization insights

Signal Design Guidelines

  • Naming Conventions

    Use kebab-case with clear hierarchy: domain-entity-action (e.g., order-payment-completed, user-profile-updated). See naming best practices for more details.

  • Payload Structure

    Define consistent schemas: Use JSON Schema validation to ensure payload consistency across publishers and consumers

  • Version Management

    Plan for evolution: Include version info in signal names or payloads for backward compatibility during deployment cycles

  • Error Recovery

    Design for failure: Implement retry logic, dead letter queues, and compensation workflows using error handling patterns

Next Steps