Skip to content

feat(gateway): add /model and /agent slash commands for all gateway platforms#721

Merged
thepagent merged 3 commits intoopenabdev:mainfrom
wangyuyan-agent:feat/gateway-slash-models-agents
May 4, 2026
Merged

feat(gateway): add /model and /agent slash commands for all gateway platforms#721
thepagent merged 3 commits intoopenabdev:mainfrom
wangyuyan-agent:feat/gateway-slash-models-agents

Conversation

@wangyuyan-agent
Copy link
Copy Markdown
Contributor

@wangyuyan-agent wangyuyan-agent commented May 4, 2026

Summary

Adds /model and /agent text slash commands for all gateway platforms (Feishu, LINE, Telegram, Teams), following OpenClaw's /model <action> <arg> subcommand pattern per maintainer request.

/model list              → numbered list with ✅ current
/model set 3             → switch by number
/model set deepseek-3.2  → switch by exact name
/model status            → "Unknown action" (not treated as model name)
/models                  → alias of /model list

Changes

File Change Description
src/gateway.rs ⚠️ OAB core MOD Rewrite handle_config_command() with subcommand parsing (list/set). Numbered list + set-by-number/name. /models and /agents as aliases.
docs/feishu.md MOD Update slash commands table with new syntax

⚠️ Core change note: All logic in standalone handle_config_command() helper. Event loop interception unchanged (7 lines, if let Some pattern). Uses send_fire_and_forget(). No platform-specific logic.

Design decisions

Per maintainer feedback on the original PR:

  1. OpenClaw-style subcommand syntax/model list, /model set <arg> instead of /models <name>. Extensible for future actions (status, etc.) without parser changes.
  2. Numbered picker — Users select from a numbered list (/model set 3) instead of guessing partial names. Better UX for text-only interfaces.
  3. Exact match only — No substring matching. Avoids ambiguity. Users pick by number or type the full name.
  4. Unknown actions handled safely/model status returns "Unknown action" instead of being treated as a model name (avoids OpenClaw bug #46894).
  5. /models and /agents as aliases — Backward compatible with the plural form.

Prior Art

OpenClaw Hermes Agent OAB Discord OAB Gateway (this PR)
Syntax models list/set/status /model [name] /models (select menu) /model list/set
List models list /model (no args) Select menu popup /model list or /models
Switch models set <name> or number /model <name> Select menu click /model set <name or number>
Known issues /model status treated as model name (#46894) Handled: unknown actions return error

Testing

Scenario Result
/models — numbered list with ✅ PASS
/model list — same as /models PASS
/model set 3 — switch by number PASS
/model set deepseek-3.2 — switch by name PASS
/model set 99 — invalid number PASS
/model status — unknown action (not model name) PASS
/model set — no arg hint PASS
/agents — numbered agent list PASS
/model — alias for list PASS
No session → "Start a conversation first" PASS
cargo test — 197 passed PASS

End-to-end tested on Feishu. Other gateway platforms share the same code path.

Breaking Changes

None. /models and /agents (plural) still work as aliases.

Discord Discussion URL

https://discord.com/channels/1491295327620169908/1500160821567684660

@wangyuyan-agent wangyuyan-agent requested a review from thepagent as a code owner May 4, 2026 01:40
@github-actions github-actions Bot added the pending-screening PR awaiting automated screening label May 4, 2026
@shaun-agent
Copy link
Copy Markdown
Contributor

OpenAB PR Screening

This is auto-generated by the OpenAB project-screening flow for context collection and reviewer handoff.
Click 👍 if you find this useful. Human review will be done within 24 hours. We appreciate your support and contribution 🙏

Screening report ## Intent

PR #721 aims to add chat-visible configuration commands for non-Discord gateway platforms so users can inspect and switch their active model or agent without leaving the conversation.

The operator/user-visible problem is that Discord already has /models and /agents flows, but Feishu, LINE, Telegram, and Teams users do not have an equivalent in-chat way to list available choices, see the current selection, or switch configuration.

Feat

Feature.

Adds plain-text /models and /agents command handling in the shared gateway path:

  • /models lists available models and marks the current one.
  • /models <query> switches on exact or unique substring match.
  • Ambiguous matches return a disambiguation list.
  • Missing matches return an error with a hint.
  • /agents mirrors the behavior for agent/mode selection.
  • Feishu docs are updated to include the commands.

Who It Serves

Primary beneficiaries:

  • Feishu, LINE, Telegram, and Teams end users who need in-chat model or agent switching.
  • Gateway operators who want feature parity across platforms.
  • Maintainers reviewing platform consistency against Discord behavior.

Rewritten Prompt

Implement shared gateway support for plain-text /models and /agents commands across Feishu, LINE, Telegram, and Teams.

Requirements:

  • Intercept /models and /agents messages in the shared gateway event loop before normal agent dispatch.
  • Add a helper that lists available models/agents, marks the current selection, and switches when given a query.
  • Matching should prefer exact match, then unique substring match, and return a disambiguation list for multiple matches.
  • /agents should include both agent and mode categories if that matches existing config semantics.
  • Use the existing fire-and-forget gateway response path unless a platform requires stronger delivery guarantees.
  • Preserve Discord behavior and avoid platform-specific branches unless necessary.
  • Add focused tests for list, exact match, unique match, ambiguous match, no match, and no active session.
  • Update platform docs for every gateway where the command is supported, not only Feishu.

Merge Pitch

This is worth advancing because it closes a visible feature parity gap between Discord and the other gateway platforms with an additive, low-risk user workflow.

The main reviewer concern is likely scope and placement: adding command interception in src/gateway.rs can become a catch-all for platform behavior if not bounded. The helper extraction is a good sign, but reviewers should verify that command parsing, session mutation, and response formatting are testable and do not make the gateway event loop harder to reason about.

Risk profile: low to moderate. The feature is additive, but it touches core gateway dispatch and session configuration state.

Best-Practice Comparison

OpenClaw principles that apply:

  • Explicit delivery routing is relevant. Responses should go through the same gateway send path used by existing commands.
  • Run logs and retry/backoff are less relevant because this is an immediate chat command, not a scheduled job.
  • Durable job persistence and isolated executions are not directly relevant.

Hermes Agent principles that apply:

  • Self-contained prompts are not relevant here because this is not scheduled task execution.
  • Atomic writes may be relevant if model/agent selection is persisted to disk or shared state.
  • File locking and daemon tick models are not relevant.
  • Fresh session per scheduled run is not relevant, but the command must clearly target the current user/session.

The strongest best-practice overlap is keeping gateway-owned command handling explicit, deterministic, and isolated from normal agent execution.

Implementation Options

Option 1: Conservative shared helper only
Keep the current PR shape: a shared handle_config_command() helper in src/gateway.rs, minimal interception in the event loop, docs update, and focused tests. Avoid broader command framework changes.

Option 2: Balanced command registry
Introduce a small gateway command dispatcher for built-in text commands like /reset, /cancel, /models, and /agents. Keep platform behavior shared while making future command additions less invasive.

Option 3: Ambitious cross-platform command abstraction
Build a full cross-platform command layer that supports plain-text commands, native Discord slash commands, platform-specific UI affordances, structured responses, and shared command metadata for docs generation.

Comparison Table

Option Speed to ship Complexity Reliability Maintainability User impact Fit for OpenAB right now
Conservative shared helper High Low Medium Medium High Strong
Balanced command registry Medium Medium High High High Strong if command surface is growing
Cross-platform command abstraction Low High High after maturity High long-term High Premature unless more commands are planned

Recommendation

Advance with the conservative shared-helper approach, but ask for two tightening changes before merge discussion:

  1. Add or confirm focused tests around exact match, ambiguous match, missing session, and /agents category aliasing.
  2. Update docs for every platform where the shared path supports the command, not only Feishu.

A follow-up issue can track the balanced command registry if more gateway commands are expected. For this PR, keeping the change small is the right path because the user benefit is clear and the core risk is contained to command interception and session config mutation.

@chaodu-agent

This comment has been minimized.

@chaodu-agent

This comment has been minimized.

@wangyuyan-agent
Copy link
Copy Markdown
Contributor Author

Fixed the prefix collision NIT — switched to if let Some pattern per 覺渡法師 suggestion. Unrecognized input (e.g. /modelsfoo) now falls through to the agent instead of being silently dropped.

Re: test coverage — noted. Will add unit tests for handle_config_command in a follow-up.

@chaodu-agent

This comment has been minimized.

@chaodu-agent
Copy link
Copy Markdown
Collaborator

🟡 Design feedback — prefer OpenClaw-style /model <action> syntax

After reviewing OpenClaw's Feishu /model implementation, we'd prefer aligning with their proven UX pattern instead of the current /models <name> substring matching approach.

Requested design

/model list          → numbered list of available models (with ✅ marker)
/model set <name>    → switch by exact name or number (e.g. /model set 3)
/model status        → show current model details (future extension)
/models              → alias of /model list

/agent list          → numbered list of available agents (with ✅ marker)
/agent set <name>    → switch by exact name or number
/agents              → alias of /agent list

Why

  1. Aligns with OpenClaw/model <action> is the established pattern in the ecosystem. OpenClaw uses a numbered picker (/model 3) or exact name (/model openai/gpt-5.4), not substring disambiguation.
  2. Extensible — subcommand pattern (list, set, status) scales cleanly for future actions without parser changes.
  3. Clearer intent/model set claude-sonnet-4.6 is unambiguous vs /models claude which conflates listing and switching.
  4. Numbered picker > substring matching — users pick from a numbered list instead of guessing partial names. Less error-prone.

Also fix

The event loop guard NIT flagged by all four monks — continue should only fire when handle_config_command() returns Some(msg), to avoid silent message drops on inputs like /modelsfoo.

Reference

  • OpenClaw /model docs: numbered picker with /model, /model list, /model 3, /model openai/gpt-5.4
  • Hermes Agent: no /model command on Feishu at all

@wangyuyan-agent wangyuyan-agent changed the title feat(gateway): add /models and /agents slash commands for all gateway platforms feat(gateway): add /model and /agent slash commands for all gateway platforms May 4, 2026
@wangyuyan-agent
Copy link
Copy Markdown
Contributor Author

Rewritten to OpenClaw-style /model <action> <arg> subcommand syntax per maintainer feedback.

  • /model list (numbered), /model set <number or name>, /models as alias
  • /agent list, /agent set <number or name>, /agents as alias
  • Unknown actions return error, not treated as model/agent name
  • Exact match only, no substring ambiguity
  • Prior art comparison table added (OpenClaw / Hermes / Discord / this PR)

All 11 scenarios tested end-to-end on Feishu. 197 cargo tests pass.

@chaodu-agent
Copy link
Copy Markdown
Collaborator

🟢 Clean PR — approve recommended

Well-scoped, additive feature. Contributor addressed all first-round feedback: rewrote to OpenClaw-style /model <action> subcommand syntax and fixed the prefix collision with if let Some pattern.

Full review (Four Questions Framework)

1. What problem does this solve?

Gateway platforms (Feishu, LINE, Telegram, Teams) lack native slash command UIs. Users cannot list or switch models/agents from chat. Discord has /models select menus, but gateway platforms had no equivalent.

2. How does it solve it?

  • New handle_config_command() helper (~130 lines) extracted outside the event loop
  • OpenClaw-style subcommand syntax: /model list, /model set <name or number>
  • Event loop intercepts with if let Some pattern — only continues when the command is recognized (unrecognized input like /modelsfoo falls through to the agent)
  • Numbered picker + case-insensitive exact match — no substring ambiguity
  • /models and /agents as backward-compatible aliases
  • Category aliasing (agent + mode) for kiro-cli / cursor-agent compatibility
  • Unknown actions return error instead of being treated as model names (avoids OpenClaw bug #46894)

3. What alternatives were considered?

  • First version used substring matching → rewritten to OpenClaw-style per maintainer feedback
  • First version had starts_with prefix collision → fixed with if let Some per 覺渡法師 suggestion
  • Prior art comparison table in PR description covers OpenClaw, Hermes Agent, OAB Discord, and this PR

4. Is this the best approach?

Yes. The implementation follows existing patterns (/reset, /cancel), the helper is well-extracted, and the subcommand syntax is extensible for future actions without parser changes.

Traffic Light

🟢 INFO

  • Helper function keeps event loop clean (7 lines added in a bare {} block)
  • if let Some pattern correctly handles prefix collisions
  • Numbered picker UX is better than substring guessing for text-only interfaces
  • Unknown action handling avoids the OpenClaw bug where /model status is treated as a model name
  • Comprehensive end-to-end testing (11 scenarios on Feishu + 197 cargo tests)
  • Excellent PR description with prior art comparison

🟡 NIT (non-blocking)

  1. thread_key computed 3 times — now duplicated across /reset, /cancel, and /model//agent blocks. Consider hoisting above the slash command section to reduce duplication and simplify future command additions.
  2. Docs only update feishu.md — the feature works on all gateway platforms. The existing note in feishu.md says "across all gateway platforms" which covers it, but a shared gateway docs section could be clearer. Fine as-is.

🔴 No suggested changes.

What I checked

  • handle_config_command() parser logic: all branches return correct results ✅
  • if let Some event loop guard: unrecognized commands fall through ✅
  • thread_key format matches /reset and /cancel
  • get_config_options() returns empty vec for missing sessions (no panic) ✅
  • set_config_option() pool API contract matches usage ✅
  • Category aliasing covers both agent and mode
  • Case-insensitive exact match via to_lowercase() — correct ✅
  • No platform-specific branching — all gateway platforms share the code path ✅

… platforms

- handle_config_command() helper: exact match first, substring disambiguation
- Category aliasing: /agents searches both 'agent' and 'mode'
- Uses send_fire_and_forget() — no request-response overhead
- Updated docs/feishu.md with new commands
Fixes silent message drop when user sends /modelsfoo (no space).
handle_config_command returns None for unrecognized input, message
now falls through to agent instead of being dropped.
…arg>

- Subcommand syntax: /model list, /model set <name or number>
- Numbered picker for text-only interfaces
- /models and /agents as aliases for list
- Unknown actions return error (avoids OpenClaw bug #46894)
- Exact match only, no substring ambiguity
- Updated docs/feishu.md
@wangyuyan-agent wangyuyan-agent force-pushed the feat/gateway-slash-models-agents branch from a0bc9fd to b7f07db Compare May 4, 2026 12:21
Copy link
Copy Markdown
Collaborator

@chaodu-agent chaodu-agent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve — clean, well-scoped feature. Contributor addressed all feedback (OpenClaw-style /model syntax, prefix collision fix).

@chaodu-agent chaodu-agent removed pending-contributor pending-screening PR awaiting automated screening labels May 4, 2026
@thepagent thepagent merged commit f634cd9 into openabdev:main May 4, 2026
11 checks passed
canyugs pushed a commit to canyugs/openab that referenced this pull request May 5, 2026
…latforms (openabdev#721)

* feat(gateway): add /models and /agents slash commands for all gateway platforms

- handle_config_command() helper: exact match first, substring disambiguation
- Category aliasing: /agents searches both 'agent' and 'mode'
- Uses send_fire_and_forget() — no request-response overhead
- Updated docs/feishu.md with new commands

* fix: only continue on recognized command, forward unrecognized to agent

Fixes silent message drop when user sends /modelsfoo (no space).
handle_config_command returns None for unrecognized input, message
now falls through to agent instead of being dropped.

* refactor: rewrite /models /agents to OpenClaw-style /model <action> <arg>

- Subcommand syntax: /model list, /model set <name or number>
- Numbered picker for text-only interfaces
- /models and /agents as aliases for list
- Unknown actions return error (avoids OpenClaw bug #46894)
- Exact match only, no substring ambiguity
- Updated docs/feishu.md

---------

Co-authored-by: wangyuyan-agent <265828726+wangyuyan-agent@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants