{"repo":"NousResearch/hermes-agent","public_id":"43466","display_label":"Strip blocked tools from delegated child agents","summary":"These issues and PRs concern a bug where delegated child agents incorrectly inherit messaging and cronjob toolsets despite those tools being blocked. The work involves fixing tool-stripping logic and removing the agent-callable send_message tool.","subsystem":"agent","counts":{"members":5,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":1,"merged_prs":2,"attempt_prs":2},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":47856},"resolution":{"state":"resolved","by":"pr-52121"},"freshness":{"state":"verified","last_verified_at":"2026-06-24T20:24:37+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_SPANNING","link_density":0.4},"fix_edges":[{"issue_number":43466,"pr_number":47856,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":43466,"pr_number":52121,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true}],"members":[{"kind":"issue","number":43466,"title":"delegate_task: _strip_blocked_tools doesn't strip 'messaging'/'cronjob', so children inherit send_message and cronjob despite DELEGATE_BLOCKED_TOOLS","url":null,"state":"closed"},{"kind":"pr","number":43474,"title":"fix(agent): strip messaging and cronjob toolsets from delegated children","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#47856","number":47856},{"kind":"pr","value":"#43466","number":43466}],"category":"implemented_elsewhere","implication":"superseded"},"merged":false},{"kind":"pr","number":43687,"title":"fix(delegate): strip messaging and cronjob toolsets from child agents","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#43474","number":43474},{"kind":"pr","value":"#43474","number":43474}],"category":"superseded_by_pr","implication":"superseded"},"merged":false,"is_fix_pr":true,"fix_tier":"suggested","fix_detail_withheld":true},{"kind":"pr","number":47856,"title":"refactor: remove agent-callable send_message tool","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["gateway/session.py","hermes_cli/tools_config.py","tests/hermes_cli/test_tools_config.py","tests/tools/test_mcp_tool.py","tools/mcp_tool.py","tools/send_message_tool.py","toolsets.py","website/docs/reference/mcp-config-reference.md"],"fix_hunks":[{"file":"gateway/session.py","hunks":["@@ -386,9 +386,10 @@ def build_session_context_prompt(\n         lines.append(\"\")\n         lines.append(\n             \"**Platform notes:** You are running inside Yuanbao. \"\n-            \"You CAN send private (DM) messages via the send_message tool. \"\n-            \"Use target='yuanbao:direct:<account_id>' for DM \"\n-            \"and target='yuanbao:group:<group_code>' for group chat.\"\n+            \"To send a private (DM) message to a user in the current group, \"\n+            \"use the yb_send_dm tool (look up the recipient by name or pass \"\n+            \"their user_id). Your normal reply is delivered to the group you \"\n+            \"are responding in.\"\n         )\n \n     # Connected platforms"]},{"file":"hermes_cli/tools_config.py","hunks":["@@ -73,7 +73,6 @@\n     (\"clarify\",         \"❓ Clarifying Questions\",      \"clarify\"),\n     (\"delegation\",      \"👥 Task Delegation\",           \"delegate_task\"),\n     (\"cronjob\",         \"⏰ Cron Jobs\",                 \"create/list/update/pause/resume/run, with optional attached skills\"),\n-    (\"messaging\",       \"📨 Cross-Platform Messaging\",  \"send_message\"),\n     (\"homeassistant\",    \"🏠 Home Assistant\",           \"smart home device control\"),\n     (\"spotify\",          \"🎵 Spotify\",                  \"playback, search, playlists, library\"),\n     (\"discord\",         \"💬 Discord (read/participate)\", \"fetch messages, search members, create thread\"),"]},{"file":"tests/hermes_cli/test_tools_config.py","hunks":["@@ -87,10 +87,6 @@ def test_gui_toolset_label_strips_leading_emoji():\n     assert gui_toolset_label(\"Terminal & Processes\") == \"Terminal & Processes\"\n \n \n-def test_configurable_toolsets_include_messaging():\n-    assert any(ts_key == \"messaging\" for ts_key, _, _ in CONFIGURABLE_TOOLSETS)\n-\n-\n def test_configurable_toolsets_include_context_engine():\n     assert any(ts_key == \"context_engine\" for ts_key, _, _ in CONFIGURABLE_TOOLSETS)\n ","@@ -130,12 +126,6 @@ def test_get_platform_tools_context_engine_respects_explicit_empty_selection():\n     assert \"context_engine\" not in enabled\n \n \n-def test_get_platform_tools_default_telegram_includes_messaging():\n-    enabled = _get_platform_tools({}, \"telegram\")\n-\n-    assert \"messaging\" in enabled\n-\n-\n def test_get_platform_tools_default_whatsapp_includes_web():\n     enabled = _get_platform_tools({}, \"whatsapp\")\n "]},{"file":"tests/tools/test_mcp_tool.py","hunks":["@@ -1884,7 +1884,7 @@ def test_default_timeout(self):\n \n         server = MCPServerTask(\"test_srv\")\n         assert server.tool_timeout == _DEFAULT_TOOL_TIMEOUT\n-        assert server.tool_timeout == 120\n+        assert server.tool_timeout == 300\n \n     def test_custom_timeout(self):\n         \"\"\"Server with timeout=180 in config gets 180.\"\"\""]},{"file":"tools/mcp_tool.py","hunks":["@@ -17,7 +17,7 @@\n         command: \"npx\"\n         args: [\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/tmp\"]\n         env: {}\n-        timeout: 120         # per-tool-call timeout in seconds (default: 120)\n+        timeout: 120         # per-tool-call timeout in seconds (default: 300)\n         connect_timeout: 60  # initial connection timeout (default: 60)\n       github:\n         command: \"npx\"","@@ -258,7 +258,7 @@ def _check_message_handler_support() -> bool:\n # Constants\n # ---------------------------------------------------------------------------\n \n-_DEFAULT_TOOL_TIMEOUT = 120      # seconds for tool calls\n+_DEFAULT_TOOL_TIMEOUT = 300      # seconds for tool calls\n _DEFAULT_CONNECT_TIMEOUT = 60    # seconds for initial connection per server\n _MAX_RECONNECT_RETRIES = 5\n _MAX_INITIAL_CONNECT_RETRIES = 3 # retries for the very first connection attempt"]},{"file":"tools/send_message_tool.py","hunks":["@@ -1899,13 +1899,16 @@ async def _send_yuanbao(chat_id, message, media_files=None):\n \n \n # --- Registry ---\n-from tools.registry import registry, tool_error\n-\n-registry.register(\n-    name=\"send_message\",\n-    toolset=\"messaging\",\n-    schema=SEND_MESSAGE_SCHEMA,\n-    handler=send_message_tool,\n-    check_fn=_check_send_message,\n-    emoji=\"📨\",\n-)\n+from tools.registry import tool_error\n+\n+# NOTE: ``send_message`` is intentionally NOT registered as an agent-callable\n+# model tool. The agent should not decide on its own to fire off cross-platform\n+# messages or reactions. The send engine in this module (``_send_to_platform``,\n+# ``_send_via_adapter``, ``_parse_target_ref``, the per-platform ``_send_*``\n+# helpers) remains the shared transport used by:\n+#   - cron delivery (cron/scheduler.py)\n+#   - the ``hermes send`` CLI command (hermes_cli/send_cmd.py)\n+#   - the gateway kanban notifier (dashboard-toggled, outside agent control)\n+#   - the standalone MCP server (mcp_serve.py), which is an opt-in surface\n+# Those callers import the helpers directly; none of them need the registry\n+# entry."]},{"file":"toolsets.py","hunks":["@@ -59,8 +59,6 @@\n     \"execute_code\", \"delegate_task\",\n     # Cronjob management\n     \"cronjob\",\n-    # Cross-platform messaging (gated on gateway running via check_fn)\n-    \"send_message\",\n     # Home Assistant smart home control (gated on HASS_TOKEN via check_fn)\n     \"ha_list_entities\", \"ha_get_state\", \"ha_list_services\", \"ha_call_service\",\n     # Kanban multi-agent coordination — only in schema when the agent is","@@ -188,13 +186,7 @@\n         \"includes\": []\n     },\n     \n-    \"messaging\": {\n-        \"description\": \"Cross-platform messaging: send messages to Telegram, Discord, Slack, SMS, etc.\",\n-        \"tools\": [\"send_message\"],\n-        \"includes\": []\n-    },\n \n-    \n     \"file\": {\n         \"description\": \"File manipulation tools: read, write, patch (with fuzzy matching), and search (content + files)\",\n         \"tools\": [\"read_file\", \"write_file\", \"patch\", \"search_files\"],","@@ -370,8 +362,10 @@\n     # ==========================================================================\n     # Full Hermes toolsets (CLI + messaging platforms)\n     #\n-    # All platforms share the same core tools (including send_message,\n-    # which is gated on gateway running via its check_fn).\n+    # All platforms share the same core tools. Note: agents do NOT get an\n+    # agent-callable send_message tool — outbound platform messaging is handled\n+    # outside the agent loop (cron delivery, the gateway kanban notifier, and\n+    # the `hermes send` CLI), not by the model deciding to send on its own.\n     # ==========================================================================\n \n     \"hermes-acp\": {"]},{"file":"website/docs/reference/mcp-config-reference.md","hunks":["@@ -54,8 +54,8 @@ mcp_servers:\n | `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 |\n | `client_key` | string | HTTP | Path to the client private key, when `client_cert` is a string and the key is in a separate file |\n | `enabled` | bool | both | Skip the server entirely when false |\n-| `timeout` | number | both | Tool call timeout |\n-| `connect_timeout` | number | both | Initial connection timeout |\n+| `timeout` | number | both | Tool call timeout in seconds (default: `300`) |\n+| `connect_timeout` | number | both | Initial connection timeout in seconds (default: `60`) |\n | `supports_parallel_tool_calls` | bool | both | Allow tools from this server to run concurrently |\n | `tools` | mapping | both | Filtering and utility-tool policy |\n | `auth` | string | HTTP | Authentication method. Set to `oauth` to enable OAuth 2.1 with PKCE |\n"]}]},{"kind":"pr","number":52121,"title":"fix(delegate): strip cronjob toolset from delegated children (#43466)","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["scripts/release.py","tests/tools/test_delegate.py","tools/delegate_tool.py"]}],"trust":{"default_tier":"verified","includes_suggested":false}}