openclaw - 💡(How to fix) Fix [Feature]: Expose Discord slash interaction response controls to plugin commands [2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#51041Fetched 2026-04-08 01:05:10
View on GitHub
Comments
2
Participants
2
Timeline
3
Reactions
0
Participants
Timeline (top)
commented ×2labeled ×1

Add stuff like ctx/follow up/editing replies to the api so we can edit command outputs for discord

Root Cause

Plugin commands are currently good for deterministic commands, but Discord UX patterns often require mixed visibility (ephemeral + public) and follow-up edits. This requires interaction-level control in plugin handlers.

I'm lazy so I made krill write this. Was hoping if you guys can add this.

Code Example

api.registerCommand({
name: "example",
description: "example",
acceptsArgs: true,
async handler(ctx) {
await ctx.discord?.respond.defer({ ephemeral: true });
await ctx.discord?.respond.followUp({
text: "Visible message",
ephemeral: false
});
:white_check_mark:
Click to react
:hearts:
Click to react
:sob:
Click to react
Translate
View Raw (Left Click) / Copy Raw (Right Click)
Add Reaction
Reply
Forward
More
[5:09 PM]Friday, March 20, 2026 5:09 PM
return { text: "done" };
}
});

---

Possible `ctx.discord` shape:

---

### Notes

- Should work in guild channels and group DMs.
- Should preserve existing OpenClaw authorization checks and routing.
- Backward compatible: if plugin doesn’t use new responder, old behavior remains unchanged.

### Why this matters

Plugin commands are currently good for deterministic commands, but Discord UX patterns often require mixed visibility (ephemeral + public) and follow-up edits. This requires interaction-level control in plugin handlers.
RAW_BUFFERClick to expand / collapse

Summary

Add stuff like ctx/follow up/editing replies to the api so we can edit command outputs for discord

Problem to solve

In native OpenClaw plugin commands (api.registerCommand({ handler(ctx) { ... } })) on Discord, the handler only receives PluginCommandContext and returns ReplyPayload.

That means plugin command handlers cannot access Discord interaction response primitives like:

  • defer(...)
  • reply(...)
  • followUp(...)
  • editReply(...) So I cannot do a common Discord flow:
  1. send an ephemeral initial slash-command response
  2. send a non-ephemeral visible follow-up to the same conversation
  3. optionally edit the initial response

This is especially useful in group DMs where I want private confirmation + public result.

Current behavior

registerCommand handler context has no interaction responder APIs. Only global channels.discord.slashCommand.ephemeral default exists.

Requested behavior

Expose interaction-level response controls for Discord native command handlers, while keeping existing command auth/policy behavior.

Proposed API shape (example)

api.registerCommand({
name: "example",
description: "example",
acceptsArgs: true,
async handler(ctx) {
await ctx.discord?.respond.defer({ ephemeral: true });
await ctx.discord?.respond.followUp({
text: "Visible message",
ephemeral: false
});
:white_check_mark:
Click to react
:hearts:
Click to react
:sob:
Click to react
Translate
View Raw (Left Click) / Copy Raw (Right Click)
Add Reaction
Reply
Forward
More
[5:09 PM]Friday, March 20, 2026 5:09 PM
return { text: "done" };
}
});

Possible `ctx.discord` shape:

```ts
type DiscordCommandResponder = {
defer: (opts?: { ephemeral?: boolean }) => Promise<void>;
reply: (opts: { text: string; ephemeral?: boolean }) => Promise<void>;
followUp: (opts: { text: string; ephemeral?: boolean }) => Promise<void>;
editReply: (opts: { text?: string }) => Promise<void>;
};

Notes

  • Should work in guild channels and group DMs.
  • Should preserve existing OpenClaw authorization checks and routing.
  • Backward compatible: if plugin doesn’t use new responder, old behavior remains unchanged.

Why this matters

Plugin commands are currently good for deterministic commands, but Discord UX patterns often require mixed visibility (ephemeral + public) and follow-up edits. This requires interaction-level control in plugin handlers.

I'm lazy so I made krill write this. Was hoping if you guys can add this.

Proposed solution

Just add options to the api to let us do these

Alternatives considered

No response

Impact

Plugin creation is being limited somewhat

Evidence/examples

<img width="357" height="337" alt="Image" src="https://github.com/user-attachments/assets/4e52e014-5945-4b93-afe7-4cb07794696d" />

Additional information

No response

extent analysis

Fix Plan

To add interaction-level response controls for Discord native command handlers, we need to modify the api.registerCommand function to include the proposed ctx.discord shape. Here are the steps:

  • Update the PluginCommandContext type to include the discord property with the DiscordCommandResponder type.
  • Implement the defer, reply, followUp, and editReply methods in the DiscordCommandResponder type.
  • Modify the registerCommand function to pass the DiscordCommandResponder instance to the command handler.

Example code:

type DiscordCommandResponder = {
  defer: (opts?: { ephemeral?: boolean }) => Promise<void>;
  reply: (opts: { text: string; ephemeral?: boolean }) => Promise<void>;
  followUp: (opts: { text: string; ephemeral?: boolean }) => Promise<void>;
  editReply: (opts: { text?: string }) => Promise<void>;
};

interface PluginCommandContext {
  // ... existing properties
  discord?: DiscordCommandResponder;
}

api.registerCommand({
  name: "example",
  description: "example",
  acceptsArgs: true,
  async handler(ctx: PluginCommandContext) {
    if (ctx.discord) {
      await ctx.discord.defer({ ephemeral: true });
      await ctx.discord.followUp({
        text: "Visible message",
        ephemeral: false
      });
      return { text: "done" };
    }
  }
});

Verification

To verify that the fix worked, you can test the updated registerCommand function with a sample command handler that uses the ctx.discord methods. For example:

api.registerCommand({
  name: "test",
  description: "test",
  acceptsArgs: true,
  async handler(ctx: PluginCommandContext) {
    if (ctx.discord) {
      await ctx.discord.defer({ ephemeral: true });
      await ctx.discord.followUp({
        text: "Visible message",
        ephemeral: false
      });
      await ctx.discord.editReply({ text: "Updated message" });
      return { text: "done" };
    }
  }
});

Check that the command handler can successfully defer, reply, follow up, and edit the reply using the ctx.discord methods.

Extra Tips

  • Make sure to handle cases where ctx.discord is undefined or null.
  • Consider adding error handling for the defer, reply, followUp, and editReply methods.
  • Document the updated api.registerCommand function and the ctx.discord methods to ensure that plugin developers understand how to use the new features.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix [Feature]: Expose Discord slash interaction response controls to plugin commands [2 comments, 2 participants]