Skip to content

Notifications

Mycel includes native connectors for sending notifications through multiple channels. Each connector is configured once and used as a flow target like any other connector.

Overview

Connector Channel Config
email SMTP email host, port, username, password
slack Slack messages token (Bot token)
discord Discord messages bot_token, or webhook_url
sms SMS via Twilio account_sid, auth_token, from
push FCM / APNs provider, credentials_file
webhook HTTP callbacks url, method, headers

For complete per-connector reference, see docs/connectors/notifications.md.

Email

connector "mailer" {
  type     = "email"
  host     = env("SMTP_HOST")
  port     = 587
  username = env("SMTP_USER")
  password = env("SMTP_PASSWORD")
  from     = "noreply@example.com"
  tls      = true
}

flow "send_welcome_email" {
  from {
    connector = "rabbit"
    operation = "user.registered"
  }

  transform {
    to      = "input.email"
    subject = "'Welcome to MyApp, ' + input.name + '!'"
    body    = "'Hello ' + input.name + ', your account is ready.'"
  }

  to {
    connector = "mailer"
    operation = "send"
  }
}

Slack

connector "slack_alerts" {
  type  = "slack"
  token = env("SLACK_BOT_TOKEN")
}

flow "alert_on_error" {
  # This would typically be an aspect
  from {
    connector = "api"
    operation = "POST /critical"
  }

  transform {
    channel = "'#alerts'"
    text    = "'Critical event: ' + input.event_type"
  }

  to {
    connector = "slack_alerts"
    operation = "chat.postMessage"
  }
}

Discord

connector "discord_bot" {
  type      = "discord"
  bot_token = env("DISCORD_BOT_TOKEN")
}

flow "send_discord_notification" {
  from {
    connector = "rabbit"
    operation = "events"
  }

  transform {
    channel_id = "'123456789'"
    content    = "input.message"
  }

  to {
    connector = "discord_bot"
    operation = "channels.messages"
  }
}

SMS (Twilio)

connector "sms_service" {
  type        = "sms"
  account_sid = env("TWILIO_ACCOUNT_SID")
  auth_token  = env("TWILIO_AUTH_TOKEN")
  from        = env("TWILIO_FROM_NUMBER")
}

flow "send_otp_sms" {
  from {
    connector = "api"
    operation = "POST /auth/otp"
  }

  transform {
    to   = "input.phone"
    body = "'Your OTP: ' + input.code"
  }

  to {
    connector = "sms_service"
    operation = "send"
  }
}

Push Notifications

# FCM (Firebase Cloud Messaging)
connector "push_fcm" {
  type                 = "push"
  driver               = "fcm"
  service_account_json = env("FCM_SERVICE_ACCOUNT", "./firebase-credentials.json")
  project_id           = "my-firebase-project"
}

flow "send_push" {
  from {
    connector = "rabbit"
    operation = "push.notifications"
  }

  transform {
    token = "input.device_token"
    title = "input.title"
    body  = "input.message"
    data  = "input.extra_data"
  }

  to {
    connector = "push_fcm"
    operation = "send"
  }
}

Webhook

connector "external_webhook" {
  type   = "webhook"
  mode   = "outbound"
  url    = env("WEBHOOK_URL")
  method = "POST"

  # Outgoing calls are signed rather than carrying a shared header: the
  # receiver checks the signature against the same secret.
  secret           = env("WEBHOOK_SECRET")
  signature_header = "X-Webhook-Signature"
}

flow "notify_external_system" {
  from {
    connector = "rabbit"
    operation = "events"
  }
  to {
    connector = "external_webhook"
    operation = "send"
  }
}

Using with Aspects

The most powerful use of notifications is with aspects — send alerts or notifications across multiple flows without duplicating code:

aspect "notify_on_error" {
  when = "on_error"
  on   = ["api_*"]

  action {
    connector = "slack_alerts"
    operation = "chat.postMessage"
    transform {
      channel = "'#errors'"
      text    = "':rotating_light: Flow failed: ' + _flow + ' (' + string(error.code) + '): ' + error.message"
    }
  }
}

This sends a Slack message whenever any flow matching api_* fails.

Configurable API URLs

All notification connectors support overriding the default API URL for testing or custom endpoints:

connector "slack_test" {
  type    = "slack"
  token   = env("SLACK_TOKEN")
  api_url = "http://localhost:8080"  # Point to a mock for testing
}

See Also