Skip to content

[Feature]: Ambient agent gating — message:received hook - #31065

Closed
brimdor wants to merge 1 commit into
NousResearch:mainfrom
brimdor:feat/ambient-message-received-31061
Closed

[Feature]: Ambient agent gating — message:received hook#31065
brimdor wants to merge 1 commit into
NousResearch:mainfrom
brimdor:feat/ambient-message-received-31061

Conversation

@brimdor

@brimdor brimdor commented May 23, 2026

Copy link
Copy Markdown

Problem or Use Case

Hermes platform adapters have a binary response gate: either require_mention: true (bot only responds when @mentioned) or free_response_channels: \"*\" (bot responds to every message). There is no middle ground for an ambient, "blend-in" agent that observes all channel activity but only replies when it genuinely has something useful, funny, or insightful to add.

Users who have opened the adapter (require_mention: false, free_response_channels: \"*\") still need a way to selectively gate messages before paying for a full agent turn.

Closes #31061


Proposed Solution

Add a new message:received hook event that fires after adapter-level gates (mention check, channel allowlist) but before agent invocation.

User-installed hooks at ~/.hermes/hooks/ can return {"action": "ignore"} to silently drop a message, preventing the agent from being invoked at all.

Hook context

{
    "platform": "discord",          # platform name
    "chat_id": "123",               # channel/thread ID
    "user_id": "456",               # author ID
    "user_name": "alice",           # display name
    "message": "hello world",       # full message text
    "message_id": "789",            # message ID
    "is_bot": False,                # was sender a bot?
    "chat_name": "general",         # channel name
    "chat_topic": "...",            # channel topic (if any)
    "thread_id": "...",             # thread ID (if in thread)
    "guild_id": "101",              # guild/workspace ID
}

Usage example

Create ~/.hermes/hooks/ambient-gate/HOOOK.yaml:

name: ambient-gate
events:
  - message:received

Create ~/.hermes/hooks/ambient-gate/handler.py:

def handle(event_type: str, context: dict):
    if context.get("is_bot", False):
        return {"action": "ignore"}
    # Your smart classifier here...
    return {"action": "respond"}

Changes

File What changed Lines
gateway/run.py Emit message:received hook + gate on {"action": "ignore"} ~45
gateway/hooks.py Document new event in module docstring ~5
tests/gateway/test_hooks.py 5 new tests (ignore, respond, mixed, context keys, no handlers) ~86

Total: +138 lines, 3 files


Backward Compatibility

  • Zero impact on default behavior: no hook handlers installed → proceed normally → no change
  • No changes to require_mention / free_response_channels logic
  • No changes to run_agent.py, prompt_builder.py, or session storage
  • All existing tests pass

Feature Type

Gateway / messaging improvement


Scope

Medium (3 files, +138 lines)


Tests

$ pytest tests/gateway/test_hooks.py -v
============================== 26 passed in 0.81s ==============================

$ pytest tests/gateway/test_session_boundary_hooks.py -v
============================== 6 passed in 6.71s ================================

Contribution

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

Adds a new gateway hook event that fires after adapter-level gates
(mention check, channel allowlist) but before agent invocation.

User-installed hooks at ~/.hermes/hooks/ can return
{"action": "ignore"} to silently drop a message, preventing
the agent from being invoked at all. This enables "ambient" or
"blend-in" bots that observe all channel activity but only
respond selectively.

- gateway/run.py: emit_collect("message:received", ...) with
  full message context (platform, chat, user, thread, message text)
- gateway/hooks.py: document the new event in module docstring
- tests/gateway/test_hooks.py: 5 new tests for ignore/respond
  decisions, mixed handlers, context keys, and no-handler case

Zero impact on default behavior. Opt-in via user hooks only.

Closes NousResearch#31061
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/gateway Gateway runner, session dispatch, delivery labels May 23, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Competing implementation alongside existing open PR #3769 (which also adds message:received and message:processed hook events to BasePlatformAdapter). Closes #31061.

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the ambient-gating implementation. This is now redundant with the gateway plugin hook already on main.

  • Automated hermes-sweeper review verified gateway/run.py:8905-8944: pre_gateway_dispatch runs for each user-originated inbound event and {"action": "skip"} returns before auth and agent dispatch.
  • hermes_cli/plugins.py:166-173 defines the supported plugin hook and its skip / rewrite / allow contract.
  • website/docs/user-guide/features/hooks.md:999-1057 documents the same pre-dispatch gate and includes an ambient-message buffering example.
  • tests/gateway/test_pre_gateway_dispatch.py:63-82 covers silent skip behavior.
  • This behavior shipped in 1ef1e4c66989bf409de31bdbe94a0f18f98ac31c (feat(plugins): add pre_gateway_dispatch hook), included in v2026.4.30. The prior note about competing PR feat(gateway): add message:received and message:processed hook events #3769 was also considered.

@teknium1 teknium1 closed this Jul 13, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have sweeper:implemented-on-main Sweeper: behavior already present on current main type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Ambient / Blend-In Agent — Selective Response Gating for Gateway

3 participants