Skip to content

feat(cron): support DM and gateway platform targets for scheduled messages #866

@chaodu-agent

Description

@chaodu-agent

Description

Allow cronjob scheduled messages to target DMs (direct messages) in addition to channels/threads, and support gateway-connected platforms (Telegram, LINE, Feishu, Google Chat, etc.) as delivery targets — not just Discord and Slack.

Use Case

As an operator, I want to receive scheduled prompts (daily summaries, reminders) as a DM rather than in a shared channel. Currently channel is required and only Discord/Slack channel IDs are supported. There is no way to send a cron message to:

  1. A Discord DM with a specific user
  2. A Telegram chat, LINE conversation, or Feishu DM via the custom gateway

This forces users to create private channels as a workaround for personal scheduled messages, and completely blocks cron usage for gateway-connected platforms.

Proposed Solution

Introduce a target_type field to distinguish delivery targets. The existing channel field is repurposed as target_id (with channel kept as an alias for backward compatibility).

Field Definition

Field Required Default Description
target_type "channel" "channel" — post to a channel (current behavior). "thread" — post to an existing thread. "dm" — open/reuse a DM with a user.
target_id The ID of the target. Interpretation depends on target_type and platform.
channel Alias for target_id (backward compat). If both are set, target_id takes precedence.
thread_id When target_type = "channel", optionally post into this thread (existing behavior).

Examples

1. Channel (current behavior, unchanged)

Post to a Discord channel — creates a new thread for the agent reply:

[[cron.jobs]]
schedule = "0 9 * * 1-5"
platform = "discord"
target_type = "channel"              # default, can be omitted
target_id = "1490282656913559673"    # Discord channel ID
message = "summarize yesterday merged PRs"
sender_name = "DailyOps"
timezone = "Asia/Taipei"
2. Existing thread

Post into a specific existing thread:

[[cron.jobs]]
schedule = "0 9 * * 1-5"
platform = "discord"
target_type = "thread"
target_id = "1506450748169523282"    # Discord thread ID
message = "daily standup reminder"
sender_name = "StandupBot"
timezone = "Asia/Taipei"
3. Discord DM

Send a DM to a specific Discord user:

[[cron.jobs]]
schedule = "0 8 * * 1-5"
platform = "discord"
target_type = "dm"
target_id = "845835116920307722"     # Discord user ID
message = "good morning! here is your daily agenda"
sender_name = "MorningBot"
timezone = "Asia/Taipei"

OAB calls the Discord API to open (or reuse) a DM channel with the user, then sends the message there.

4. Gateway — Telegram DM

Send via the custom gateway to a Telegram user:

[[cron.jobs]]
schedule = "0 9 * * 1-5"
platform = "gateway"
target_type = "dm"
target_id = "123456789"              # Telegram user/chat ID
message = "daily security scan report"
sender_name = "SecurityBot"
timezone = "UTC"
5. Gateway — LINE DM

Send via the custom gateway to a LINE user:

[[cron.jobs]]
schedule = "0 18 * * 1-5"
platform = "gateway"
target_type = "dm"
target_id = "U1234567890abcdef"      # LINE user ID
message = "end of day summary"
sender_name = "EODBot"
timezone = "Asia/Taipei"
6. Gateway — Feishu group chat

Send to a Feishu group chat:

[[cron.jobs]]
schedule = "0 9 * * 1-5"
platform = "gateway"
target_type = "channel"
target_id = "oc_abcdef123456"        # Feishu chat_id
message = "weekly team sync reminder"
sender_name = "TeamBot"
timezone = "Asia/Shanghai"
7. Backward compatibility (existing config still works)
[[cron.jobs]]
schedule = "0 9 * * 1-5"
channel = "1490282656913559673"      # old field, treated as target_id with target_type="channel"
message = "summarize yesterday merged PRs"

Routing Logic

fire_cronjob()
  │
  ├─ platform = "discord" or "slack"
  │    ├─ target_type = "channel" → post to channel (create thread)  [existing behavior]
  │    ├─ target_type = "thread"  → post into existing thread
  │    └─ target_type = "dm"      → open DM channel with user, post there
  │
  └─ platform = "gateway"
       │  Emit GatewayEvent over WebSocket to custom gateway
       ├─ target_type = "channel" → gateway routes to group/channel
       ├─ target_type = "dm"      → gateway routes to 1:1 DM
       └─ target_type = "thread"  → gateway routes to thread/topic

The gateway uses target_id + platform credentials to call the appropriate API (Telegram sendMessage, LINE Push API, Feishu send_message, etc.).

Prior Art

  • The gateway custom webhook already supports triggering agents from external cron jobs via curl -X POST (documented in gateway/README.md). This FR brings that capability into the native config-driven scheduler.
  • Discord.js bots commonly support DM targets for scheduled messages via user.send().
  • Discord API: POST /users/@me/channels with recipient_id to create/get a DM channel.

Related Issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions