hermes - 💡(How to fix) Fix [Feature]: Mattermost: Add interactive button-based approval for dangerous commands

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…

Root Cause

Root cause: Mattermost intercepts all messages starting with / Both the Mattermost server and client intercept any message beginning with / and try to execute it as a native slash command.

Code Example

async def send_exec_approval(self, chat_id, command, session_key, description, metadata):
    payload = {
        "channel_id": chat_id,
        "message": "⚠️ Command Approval Required",
        "attachments": [{
            "title": description,
            "text": f"

---

**Handle the callback:** The gateway already has an HTTP server infrastructure. Register a route that receives Mattermost interactive message callbacks, calls `resolve_gateway_approval(session_key, choice)` (same function Discord uses), and returns the updated message with disabled buttons to confirm the action.

**Authorization:** Verify that the clicking user is the same user who initiated the command (or is in `MATTERMOST_ALLOWED_USERS`), matching Discord's `_check_caller_authorized()` behavior.

### 2. Register slash commands via Mattermost REST API

Following the existing Discord/Discord pattern, register all `COMMAND_REGISTRY` gateway commands as Mattermost custom slash commands on adapter startup via `POST /api/v4/commands`:

- `trigger`: command name (`approve`, `deny`, `help`, `yolo`, `retry`, etc.)
- `url`: gateway HTTP endpoint to receive the command
- `method`: `P` (POST)
- `auto_complete`: `true`
- `display_name`: `Hermes: /{name}`

This matches the approach already proposed in #6296 and gives Mattermost feature parity with Telegram, Slack, and Discord.

## Benefits

- **Dangerous command approval works** — the most critical UX flow, fully interactive with buttons
- **All slash commands work**`/approve`, `/deny`, `/yolo`, `/help`, `/retry` etc. from every Mattermost client
- **Autocomplete** — users see all Hermes commands when typing `/` in Mattermost
- **Feature parity**Mattermost gets the same first-class experience as Discord/Telegram/Slack
- **Reuses existing infrastructure**`resolve_gateway_approval()`, `COMMAND_REGISTRY`, and the gateway HTTP server are already there

## Scope

- `send_exec_approval()` implementation: ~50 lines in `gateway/platforms/mattermost.py`
- interactive callback handler: ~40 lines in `gateway/platforms/mattermost.py`
- slash command registration: ~30 lines in the `connect()` method
- gateway HTTP route registration: ~10 lines in `gateway/run.py`

## Impact

Unblocks Hermes usage on Mattermost for all users. Without this, no one can approve dangerous commands or use any slash command from Mattermost — the platform is effectively crippled for Hermes interaction.


### Alternatives Considered

_No response_

### Feature Type

Gateway / messaging improvement

### Scope

Medium (few files, < 300 lines)

### Contribution

- [ ] I'd like to implement this myself and submit a PR

### Debug Report (optional)
RAW_BUFFERClick to expand / collapse

Problem or Use Case

The Mattermost gateway adapter is effectively unusable for any user interaction that requires slash commands — most critically, the /approve and /deny flow for dangerous command approval.

Root cause: Mattermost intercepts all messages starting with / Both the Mattermost server and client intercept any message beginning with / and try to execute it as a native slash command.

The message never reaches the Hermes bot.

Proposed Solution

Current state

  1. No interactive buttons — Unlike Discord (which has send_exec_approval() with ExecApprovalView — 4 clickable buttons), the Mattermost adapter has no button-based approval mechanism.
  2. Fallback is broken — When send_exec_approval() is absent from the adapter, gateway/run.py falls back to a plain text message instructing the user to reply with /approve once etc. Since / is intercepted, this instructs the user to do something that's impossible.
  3. All slash commands are broken/yolo, /retry, /help, /model, /skills — none work from any Mattermost client.

Existing Platform Parity

PlatformApproval mechanismSlash command UX
DiscordExecApprovalView — 4 buttons (embedded with colors)Native Discord slash commands — auto-registered
TelegramText /approve + Telegram BotCommand menuBotCommand menu — auto-registered via telegram_bot_commands()
SlackButton-based approval via Slack Block Kit/hermes subcommand routing
MattermostNone — broken text fallbackNone — no slash commands registered

Proposed Solution

1. Interactive approval buttons

Mattermost supports interactive message buttons via post attachments with actions[].integration. The approach mirrors Discord's:

Send approval message:

async def send_exec_approval(self, chat_id, command, session_key, description, metadata):
    payload = {
        "channel_id": chat_id,
        "message": "⚠️ Command Approval Required",
        "attachments": [{
            "title": description,
            "text": f"```\n{command}\n```",
            "actions": [
                {
                    "name": "Allow Once",
                    "integration": {
                        "url": f"{self._gateway_callback_url}/approval",
                        "context": {"session_key": session_key, "action": "once"}
                    }
                },
                {
                    "name": "Allow Session",
                    "integration": {
                        "url": f"{self._gateway_callback_url}/approval",
                        "context": {"session_key": session_key, "action": "session"}
                    }
                },
                {
                    "name": "Always Allow",
                    "integration": {
                        "url": f"{self._gateway_callback_url}/approval",
                        "context": {"session_key": session_key, "action": "always"}
                    }
                },
                {
                    "name": "Deny",
                    "integration": {
                        "url": f"{self._gateway_callback_url}/approval",
                        "context": {"session_key": session_key, "action": "deny"}
                    }
                }
            ]
        }]
    }

Handle the callback: The gateway already has an HTTP server infrastructure. Register a route that receives Mattermost interactive message callbacks, calls resolve_gateway_approval(session_key, choice) (same function Discord uses), and returns the updated message with disabled buttons to confirm the action.

Authorization: Verify that the clicking user is the same user who initiated the command (or is in MATTERMOST_ALLOWED_USERS), matching Discord's _check_caller_authorized() behavior.

2. Register slash commands via Mattermost REST API

Following the existing Discord/Discord pattern, register all COMMAND_REGISTRY gateway commands as Mattermost custom slash commands on adapter startup via POST /api/v4/commands:

  • trigger: command name (approve, deny, help, yolo, retry, etc.)
  • url: gateway HTTP endpoint to receive the command
  • method: P (POST)
  • auto_complete: true
  • display_name: Hermes: /{name}

This matches the approach already proposed in #6296 and gives Mattermost feature parity with Telegram, Slack, and Discord.

Benefits

  • Dangerous command approval works — the most critical UX flow, fully interactive with buttons
  • All slash commands work/approve, /deny, /yolo, /help, /retry etc. from every Mattermost client
  • Autocomplete — users see all Hermes commands when typing / in Mattermost
  • Feature parity — Mattermost gets the same first-class experience as Discord/Telegram/Slack
  • Reuses existing infrastructureresolve_gateway_approval(), COMMAND_REGISTRY, and the gateway HTTP server are already there

Scope

  • send_exec_approval() implementation: ~50 lines in gateway/platforms/mattermost.py
  • interactive callback handler: ~40 lines in gateway/platforms/mattermost.py
  • slash command registration: ~30 lines in the connect() method
  • gateway HTTP route registration: ~10 lines in gateway/run.py

Impact

Unblocks Hermes usage on Mattermost for all users. Without this, no one can approve dangerous commands or use any slash command from Mattermost — the platform is effectively crippled for Hermes interaction.

Alternatives Considered

No response

Feature Type

Gateway / messaging improvement

Scope

Medium (few files, < 300 lines)

Contribution

  • I'd like to implement this myself and submit a PR

Debug Report (optional)

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

hermes - 💡(How to fix) Fix [Feature]: Mattermost: Add interactive button-based approval for dangerous commands