From c6c8abbadb802dc389d8488a8847f9aa93bf9350 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Wed, 17 Jun 2026 07:11:23 -0700 Subject: [PATCH] refactor: remove agent-callable send_message tool (#47856) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(mcp): raise default tool-call timeout 120s -> 300s Port from openai/codex#28234. Long-running MCP tools (web fetches, sandboxed builds, deep-research servers) routinely exceed 120s, causing spurious timeout failures. Codex bumped its default MCP tool timeout from 120 to 300 for the same reason. - _DEFAULT_TOOL_TIMEOUT 120 -> 300 in tools/mcp_tool.py (per-server 'timeout' config override unchanged) - update test_default_timeout assertion - document the default in mcp-config-reference.md * refactor: remove agent-callable send_message tool The agent should not decide on its own to fire off cross-platform messages or reactions. Outbound platform messaging is handled outside the agent loop — cron delivery, the gateway kanban notifier (dashboard-toggled), and the `hermes send` CLI. Removes the model-tool registration only; the send engine in send_message_tool.py (_send_to_platform, _send_via_adapter, _parse_target_ref, per-platform _send_* helpers) is kept intact for those non-agent callers. Drops the now-empty 'messaging' toolset and its `hermes tools` toggle. Yuanbao DM guidance now points at the native yb_send_dm tool. --- gateway/session.py | 7 ++++--- hermes_cli/tools_config.py | 1 - tests/hermes_cli/test_tools_config.py | 10 --------- tests/tools/test_mcp_tool.py | 2 +- tools/mcp_tool.py | 4 ++-- tools/send_message_tool.py | 21 +++++++++++-------- toolsets.py | 14 ++++--------- .../docs/reference/mcp-config-reference.md | 4 ++-- 8 files changed, 25 insertions(+), 38 deletions(-) diff --git a/gateway/session.py b/gateway/session.py index ce6aad2d0db..f48b83fed0c 100644 --- a/gateway/session.py +++ b/gateway/session.py @@ -386,9 +386,10 @@ def build_session_context_prompt( lines.append("") lines.append( "**Platform notes:** You are running inside Yuanbao. " - "You CAN send private (DM) messages via the send_message tool. " - "Use target='yuanbao:direct:' for DM " - "and target='yuanbao:group:' for group chat." + "To send a private (DM) message to a user in the current group, " + "use the yb_send_dm tool (look up the recipient by name or pass " + "their user_id). Your normal reply is delivered to the group you " + "are responding in." ) # Connected platforms diff --git a/hermes_cli/tools_config.py b/hermes_cli/tools_config.py index f76c56e667f..5eec978e180 100644 --- a/hermes_cli/tools_config.py +++ b/hermes_cli/tools_config.py @@ -73,7 +73,6 @@ CONFIGURABLE_TOOLSETS = [ ("clarify", "❓ Clarifying Questions", "clarify"), ("delegation", "👥 Task Delegation", "delegate_task"), ("cronjob", "⏰ Cron Jobs", "create/list/update/pause/resume/run, with optional attached skills"), - ("messaging", "📨 Cross-Platform Messaging", "send_message"), ("homeassistant", "🏠 Home Assistant", "smart home device control"), ("spotify", "🎵 Spotify", "playback, search, playlists, library"), ("discord", "💬 Discord (read/participate)", "fetch messages, search members, create thread"), diff --git a/tests/hermes_cli/test_tools_config.py b/tests/hermes_cli/test_tools_config.py index 5b24d2b6ebd..235c7d99a28 100644 --- a/tests/hermes_cli/test_tools_config.py +++ b/tests/hermes_cli/test_tools_config.py @@ -87,10 +87,6 @@ def test_gui_toolset_label_strips_leading_emoji(): assert gui_toolset_label("Terminal & Processes") == "Terminal & Processes" -def test_configurable_toolsets_include_messaging(): - assert any(ts_key == "messaging" for ts_key, _, _ in CONFIGURABLE_TOOLSETS) - - def test_configurable_toolsets_include_context_engine(): assert any(ts_key == "context_engine" for ts_key, _, _ in CONFIGURABLE_TOOLSETS) @@ -130,12 +126,6 @@ def test_get_platform_tools_context_engine_respects_explicit_empty_selection(): assert "context_engine" not in enabled -def test_get_platform_tools_default_telegram_includes_messaging(): - enabled = _get_platform_tools({}, "telegram") - - assert "messaging" in enabled - - def test_get_platform_tools_default_whatsapp_includes_web(): enabled = _get_platform_tools({}, "whatsapp") diff --git a/tests/tools/test_mcp_tool.py b/tests/tools/test_mcp_tool.py index e9654ec74f5..c299e506d1a 100644 --- a/tests/tools/test_mcp_tool.py +++ b/tests/tools/test_mcp_tool.py @@ -1884,7 +1884,7 @@ class TestConfigurableTimeouts: server = MCPServerTask("test_srv") assert server.tool_timeout == _DEFAULT_TOOL_TIMEOUT - assert server.tool_timeout == 120 + assert server.tool_timeout == 300 def test_custom_timeout(self): """Server with timeout=180 in config gets 180.""" diff --git a/tools/mcp_tool.py b/tools/mcp_tool.py index 8b9200db9e4..db419196a47 100644 --- a/tools/mcp_tool.py +++ b/tools/mcp_tool.py @@ -17,7 +17,7 @@ Example config:: command: "npx" args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"] env: {} - timeout: 120 # per-tool-call timeout in seconds (default: 120) + timeout: 120 # per-tool-call timeout in seconds (default: 300) connect_timeout: 60 # initial connection timeout (default: 60) github: command: "npx" @@ -258,7 +258,7 @@ if _MCP_AVAILABLE and not _MCP_MESSAGE_HANDLER_SUPPORTED: # Constants # --------------------------------------------------------------------------- -_DEFAULT_TOOL_TIMEOUT = 120 # seconds for tool calls +_DEFAULT_TOOL_TIMEOUT = 300 # seconds for tool calls _DEFAULT_CONNECT_TIMEOUT = 60 # seconds for initial connection per server _MAX_RECONNECT_RETRIES = 5 _MAX_INITIAL_CONNECT_RETRIES = 3 # retries for the very first connection attempt diff --git a/tools/send_message_tool.py b/tools/send_message_tool.py index 3bbcbff8b1a..72311f87c41 100644 --- a/tools/send_message_tool.py +++ b/tools/send_message_tool.py @@ -1899,13 +1899,16 @@ async def _send_yuanbao(chat_id, message, media_files=None): # --- Registry --- -from tools.registry import registry, tool_error +from tools.registry import tool_error -registry.register( - name="send_message", - toolset="messaging", - schema=SEND_MESSAGE_SCHEMA, - handler=send_message_tool, - check_fn=_check_send_message, - emoji="📨", -) +# NOTE: ``send_message`` is intentionally NOT registered as an agent-callable +# model tool. The agent should not decide on its own to fire off cross-platform +# messages or reactions. The send engine in this module (``_send_to_platform``, +# ``_send_via_adapter``, ``_parse_target_ref``, the per-platform ``_send_*`` +# helpers) remains the shared transport used by: +# - cron delivery (cron/scheduler.py) +# - the ``hermes send`` CLI command (hermes_cli/send_cmd.py) +# - the gateway kanban notifier (dashboard-toggled, outside agent control) +# - the standalone MCP server (mcp_serve.py), which is an opt-in surface +# Those callers import the helpers directly; none of them need the registry +# entry. diff --git a/toolsets.py b/toolsets.py index 5c67bfb2114..f33be147e95 100644 --- a/toolsets.py +++ b/toolsets.py @@ -59,8 +59,6 @@ _HERMES_CORE_TOOLS = [ "execute_code", "delegate_task", # Cronjob management "cronjob", - # Cross-platform messaging (gated on gateway running via check_fn) - "send_message", # Home Assistant smart home control (gated on HASS_TOKEN via check_fn) "ha_list_entities", "ha_get_state", "ha_list_services", "ha_call_service", # Kanban multi-agent coordination — only in schema when the agent is @@ -188,13 +186,7 @@ TOOLSETS = { "includes": [] }, - "messaging": { - "description": "Cross-platform messaging: send messages to Telegram, Discord, Slack, SMS, etc.", - "tools": ["send_message"], - "includes": [] - }, - "file": { "description": "File manipulation tools: read, write, patch (with fuzzy matching), and search (content + files)", "tools": ["read_file", "write_file", "patch", "search_files"], @@ -370,8 +362,10 @@ TOOLSETS = { # ========================================================================== # Full Hermes toolsets (CLI + messaging platforms) # - # All platforms share the same core tools (including send_message, - # which is gated on gateway running via its check_fn). + # All platforms share the same core tools. Note: agents do NOT get an + # agent-callable send_message tool — outbound platform messaging is handled + # outside the agent loop (cron delivery, the gateway kanban notifier, and + # the `hermes send` CLI), not by the model deciding to send on its own. # ========================================================================== "hermes-acp": { diff --git a/website/docs/reference/mcp-config-reference.md b/website/docs/reference/mcp-config-reference.md index 44d0d4512a9..e7a35a5878b 100644 --- a/website/docs/reference/mcp-config-reference.md +++ b/website/docs/reference/mcp-config-reference.md @@ -54,8 +54,8 @@ mcp_servers: | `client_cert` | string or list | HTTP | mTLS client certificate. String = path to a PEM file containing cert + key. List `[cert, key]` = separate files. List `[cert, key, password]` = encrypted key | | `client_key` | string | HTTP | Path to the client private key, when `client_cert` is a string and the key is in a separate file | | `enabled` | bool | both | Skip the server entirely when false | -| `timeout` | number | both | Tool call timeout | -| `connect_timeout` | number | both | Initial connection timeout | +| `timeout` | number | both | Tool call timeout in seconds (default: `300`) | +| `connect_timeout` | number | both | Initial connection timeout in seconds (default: `60`) | | `supports_parallel_tool_calls` | bool | both | Allow tools from this server to run concurrently | | `tools` | mapping | both | Filtering and utility-tool policy | | `auth` | string | HTTP | Authentication method. Set to `oauth` to enable OAuth 2.1 with PKCE |