guild_id are dropped, and direct messages (DMs) are not supported.
Design Philosophy
This limitation is by design, not a bug:- Simplified mental model: Developers only need to think about one context (guilds)
- Natural isolation: Guild ID provides a natural boundary for isolates and storage
- Security: Guild-scoped permissions align with Discord’s permission model
- Resource management: Guild ID is used for routing, caching, and rate limiting
The guild-only scope is documented in AGENTS.md:8 and enforced throughout the runtime.
Event Filtering
Events without aguild_id are dropped at the Discord handler level (apps/runtime/src/discord_handler.rs):
MessageCreate(apps/runtime/src/discord_handler.rs:74-77)MessageUpdate(apps/runtime/src/discord_handler.rs:97-99)MessageDelete(apps/runtime/src/discord_handler.rs:128-130)InteractionCreate(apps/runtime/src/discord_handler.rs:195-197)ReactionAdd(apps/runtime/src/discord_handler.rs:264-266)ReactionRemove(apps/runtime/src/discord_handler.rs:288-290)
What This Means
No Direct Messages
DMs to the bot are silently ignored:No Global Commands
Slash commands must be registered per-guild:No User/Bot-Scoped Events
Events that don’t have a guild context are dropped:- User updates (username changes, avatar changes)
- Presence updates outside guilds
- Voice state updates in DM calls
- Group DM events
Benefits of Guild-Only Scope
1. Natural Isolation
Guild ID provides a natural isolation boundary:2. Simplified Storage
KV storage is naturally scoped per guild:3. Clear Permission Model
Guild-scoped commands align with Discord’s permission system:4. Easier Debugging
Logs, metrics, and errors are naturally grouped by guild:Workarounds for DM Use Cases
If you absolutely need to handle DMs, consider these alternatives:1. Redirect to Guild Channel
Use a separate bot (outside flora) to listen for DMs and forward them to a guild channel:2. Use Interactions in Guilds
Instead of DMs, use ephemeral interactions:3. Use a Different Framework
If DMs are a core requirement, consider:- discord.js - Full Discord API support
- Serenity - Rust Discord library
- discordgo - Go Discord library
Impact on API Design
The guild-only scope influences every part of the flora API:Event Payloads
All event payloads includeguild_id (apps/runtime/src/discord_handler.rs:426-440):
Option<String> is for Discord API compatibility, but flora guarantees it’s always Some().
KV Ops
KV ops extract guild ID fromOpState (apps/runtime/src/ops/kv.rs):
Secrets Scope
Secrets can be runtime-scoped or guild-scoped (apps/runtime/src/runtime/secrets.rs):Technical Enforcement
The guild-only scope is enforced at multiple levels:- Event handler - Non-guild events are dropped (apps/runtime/src/discord_handler.rs)
- Runtime dispatch -
guild_idis required for event dispatch (apps/runtime/src/runtime/mod.rs:179-207) - Deployment service - Deployments are keyed by guild ID (apps/runtime/src/services/deployments/mod.rs)
- KV service - Storage is partitioned by guild ID (apps/runtime/src/services/kv/service.rs)
- Logging - All log entries include guild context (apps/runtime/src/log_sink.rs)
Future Considerations
While the guild-only scope is a core design principle, the flora team may consider:- Opt-in DM support via a separate event namespace (e.g.,
dmMessageCreate) - Global command registration as a compile-time option
- User-scoped storage alongside guild-scoped KV