Skip to content

feat(slack): add --no-assistant flag to manifest generation - #51416

Closed
victor-kyriazakos wants to merge 1 commit into
NousResearch:mainfrom
victor-kyriazakos:feat/slack-manifest-no-assistant
Closed

feat(slack): add --no-assistant flag to manifest generation#51416
victor-kyriazakos wants to merge 1 commit into
NousResearch:mainfrom
victor-kyriazakos:feat/slack-manifest-no-assistant

Conversation

@victor-kyriazakos

Copy link
Copy Markdown
Contributor

Summary

hermes slack manifest always emits a manifest that opts the app into Slack's AI Assistant container — the assistant_view feature, the assistant:write scope, and the assistant_thread_started / assistant_thread_context_changed events. There is currently no flag to turn this off; the only workaround is hand-editing the generated JSON.

With assistant mode on, Slack renders DMs as the right-hand Assistant split-pane, where every exchange is a thread and bare slash commands (/help, /new, …) are not delivered as normal command events — they only dispatch when the bot is @mentioned. Users hitting this report "slash commands only work when I tag the bot, even in DMs" and "DMs always spawn a thread I can't send commands to."

This PR adds --no-assistant to hermes slack manifest, emitting a flat-DM manifest that omits those three pieces. DMs then render as a normal chat and slash commands dispatch inline.

Behaviour

  • Default unchanged — assistant mode stays on; existing manifests/tests unaffected.
  • --no-assistant — drops assistant_view, assistant:write, and the two assistant_thread_* events.
  • The regular messaging surface is preserved in both modes: Messages tab, the 50 slash commands, Socket Mode, and the channel + DM scopes/events (channels:*, groups:*, message.channels, message.groups, message.im, app_mention).

Usage

hermes slack manifest --no-assistant            # flat-DM manifest to stdout
hermes slack manifest --no-assistant --write    # write to $HERMES_HOME/slack-manifest.json

Tests

tests/hermes_cli/test_slack_cli.py:

  • existing assistant-mode assertion retained (default behaviour);
  • --no-assistant omits all three assistant pieces;
  • --no-assistant preserves the core messaging surface (Messages tab, slashes, Socket Mode, channel/DM scopes + events);
  • argparse wiring: flag defaults to no_assistant=False, --no-assistant sets it True.

All 7 tests pass; ruff check clean on the changed files.

By default `hermes slack manifest` opts the app into Slack's AI Assistant
container (assistant_view feature + assistant:write scope +
assistant_thread_* events). Slack then renders DMs as the right-hand
Assistant split-pane, where every exchange is a thread and bare slash
commands (/help, /new, ...) are not delivered as normal command events —
they only work when the bot is @mentioned. There was no way to opt out
short of hand-editing the generated JSON.

Add --no-assistant to emit a flat-DM manifest that omits those three
pieces, so DMs render as a normal chat and slash commands dispatch
inline. The regular messaging surface (Messages tab, slash commands,
Socket Mode, channel + DM scopes/events) is preserved in both modes.

Default behaviour is unchanged (assistant mode still on).

Tests: cover both manifest modes and the argparse wiring.
@alt-glitch alt-glitch added type/feature New feature or request comp/cli CLI entry point, hermes_cli/, setup wizard platform/slack Slack app adapter P3 Low — cosmetic, nice to have labels Jun 23, 2026

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Summary

Verdict: Approved

Add --no-assistant flag to Slack manifest generation.

Looks Good

  • Clean feature addition with clear documentation
  • Properly handles the assistant_view feature, scopes, and events
  • Default behavior preserved (include_assistant=True)
  • Well-structured manifest building with conditional assistant pieces
  • Tests verify both modes (with and without assistant)

Reviewed by Hermes Agent

@teknium1

Copy link
Copy Markdown
Contributor

Merged via #51487 — your commit was cherry-picked onto current main with your authorship preserved (rebase-merge, commit da80ac0). Verified the premise on main, kept assistant-on as the default (the adapter relies on assistant mode for the "is thinking…" status and pre-message session/memory scoping), and confirmed both manifest modes E2E. Thanks @victor-kyriazakos!

@victor-kyriazakos

Copy link
Copy Markdown
Contributor Author

Thanks for the careful review — agreed on the headline: keep assistant-on as the default, --no-assistant stays opt-in. Flipping the default would be an unrequested UX change for every existing Slack user, and this flag is for the narrow case (flat-DM where bare slash commands must dispatch inline).

On the two specific concerns, after tracing the code + verifying against a live flat-DM install, I'd refine the framing:

1. "is thinking…" indicator → "falls back to reactions." This is narrower than it reads. There are three independent indicators with different dependencies:

  • Interim assistant status messages ("Organizing…", "Processing…" next to the bot name) — interim_assistant_messages in gateway/run.py, posted/edited via plain chat.update. The code comment notes these are "intentionally independent from tool progress and token streaming." They need only chat:write and render identically with or without assistant:write. This is the indicator users actually see during processing, and it's unaffected by --no-assistant.
  • Native assistant_threads.setStatus "is thinking…" footer (slack.py:1294) — the only genuinely assistant-API-bound one. Its own docstring says it accepts assistant:write or chat:write; in practice it still renders inside a real thread context in flat-DM mode.
  • 👀 reaction (on_processing_start, slack.py:1720) — needs only reactions:write; the lowest-tier fallback.

So flat-DM does not collapse the thinking indicator down to a bare emoji reaction — the primary status text is scope-independent. (Screenshots from a live --no-assistant DM confirm "Organizing…/Processing…" rendering normally.)

2. Pre-message session/memory scoping via assistant_thread_started. Real, but it's a timing optimization, not a scoping guarantee. _handle_assistant_thread_lifecycle_event_seed_assistant_thread_session (slack.py:2141) just calls get_or_create_session at thread-open so the row exists before the first message. Session identity/isolation is derived deterministically by build_session_key (session.py:617) from each message's source regardless — so without the event, the first message creates the same session key on arrival. I grepped the tree: context_channel_id is referenced only inside slack.py (no memory consumer reads it), and no memory path depends on the assistant event. Net effect of --no-assistant: the session row is created on first message instead of at thread-open (a few hundred ms later) — no mis-scoping, no cross-contamination, transcript/memory identical.

TL;DR: default stays assistant-on (agreed); the only things truly tied to assistant mode are the native setStatus label and the session pre-seed, neither of which is a user-visible break — which is exactly why this is the right shape as an opt-in flag rather than a default flip.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have platform/slack Slack app adapter type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants