Bug Description
The standalone platform senders in tools/send_message_tool.py (used by both the send_message tool and cron job auto-delivery) do not apply message chunking before sending. The gateway adapters handle this correctly since they run messages through truncate_message() (defined in base.py), which splits at smart boundaries, preserves code blocks across chunks, and adds part indicators. The standalone senders bypass all of that.
Long agent responses delivered via cron jobs or the send_message tool fail when they exceed platform length limits. The API rejects the oversized payload. Errors are logged server-side but no message arrives in the chat, so from the user's perspective the delivery fails silently.
Steps to Reproduce
- Create a cron job with
deliver: origin that produces a response longer than the platform's message limit (e.g. >4096 chars for Telegram)
- Wait for the job to run
- The response is saved to disk but delivery fails. No message arrives in the chat
Alternatively: have the agent use send_message with a message body exceeding the platform limit.
Expected Behavior
Long messages should be chunked to fit within platform limits before sending, consistent with how the gateway adapters handle regular responses.
Actual Behavior
The full message is sent as a single API call. Platforms reject it and the user receives nothing.
Errors are returned in the result dict and logged, but don't surface to the chat. Specifically:
| Platform |
Limit |
Gateway adapter |
send_message_tool.py |
| Telegram |
4,096 chars |
chunking via truncate_message() |
No chunking, single API call |
| Discord |
2,000 chars |
chunking via truncate_message() |
Naive message[i:i+2000] split, breaks mid-word/code-block, no part indicators |
| Slack |
~39,000 chars |
chunking via truncate_message() |
No chunking, single API call |
| Signal |
~8,000 chars |
No chunking (delegates to daemon) |
No chunking, single RPC call |
Affected Component
Tools (terminal, file ops, web, code execution, etc.)
Messaging Platform (if gateway-related)
No response
Operating System
Alpine 3.23.3
Python Version
3.11.14
Hermes Version
Hermes Agent v0.2.0 (2026.3.12)
Relevant Logs / Traceback
ERROR cron.scheduler: Job 'job["id"]': delivery error: Telegram send failed: Message is too long
Root Cause Analysis (optional)
The gateway adapters (gateway/platforms/telegram.py, discord.py, slack.py) each call self.truncate_message() (defined in base.py:1080-1168) in their send() method before dispatching to the platform API. This method splits at natural boundaries (newlines, then spaces), preserves code block fences across chunks, and adds (1/N) indicators.
The standalone senders in tools/send_message_tool.py (_send_telegram, _send_discord, _send_slack, _send_signal) call the platform APIs directly without any of that chunking.
Discord has a naive [message[i:i+2000]] split that avoids API rejection but breaks content mid-word and mid-code-block.
Cron delivery in cron/scheduler.py:_deliver_result() calls _send_to_platform() from send_message_tool.py, so it inherits the same gap.
Proposed Fix (optional)
truncate_message() is an instance method on BasePlatformAdapter but uses no instance state. Converting it to a @staticmethod (following the existing extract_media() pattern on the same class) would allow calling it directly as BasePlatformAdapter.truncate_message(content, max_length). BasePlatformAdapter is already imported in send_message_tool.py.
The chunking can then be applied centrally in _send_to_platform() before dispatching to individual senders, using per-platform max lengths. For multi-chunk sends, each chunk is dispatched individually. Media files (Telegram only) attach to the last chunk. Discord's character split in _send_discord() would be replaced by the centralized truncate_message() call in _send_to_platform().
Are you willing to submit a PR for this?
Bug Description
The standalone platform senders in
tools/send_message_tool.py(used by both thesend_messagetool and cron job auto-delivery) do not apply message chunking before sending. The gateway adapters handle this correctly since they run messages throughtruncate_message()(defined inbase.py), which splits at smart boundaries, preserves code blocks across chunks, and adds part indicators. The standalone senders bypass all of that.Long agent responses delivered via cron jobs or the
send_messagetool fail when they exceed platform length limits. The API rejects the oversized payload. Errors are logged server-side but no message arrives in the chat, so from the user's perspective the delivery fails silently.Steps to Reproduce
deliver: originthat produces a response longer than the platform's message limit (e.g. >4096 chars for Telegram)Alternatively: have the agent use
send_messagewith a message body exceeding the platform limit.Expected Behavior
Long messages should be chunked to fit within platform limits before sending, consistent with how the gateway adapters handle regular responses.
Actual Behavior
The full message is sent as a single API call. Platforms reject it and the user receives nothing.
Errors are returned in the result dict and logged, but don't surface to the chat. Specifically:
send_message_tool.pytruncate_message()truncate_message()message[i:i+2000]split, breaks mid-word/code-block, no part indicatorstruncate_message()Affected Component
Tools (terminal, file ops, web, code execution, etc.)
Messaging Platform (if gateway-related)
No response
Operating System
Alpine 3.23.3
Python Version
3.11.14
Hermes Version
Hermes Agent v0.2.0 (2026.3.12)
Relevant Logs / Traceback
ERROR cron.scheduler: Job 'job["id"]': delivery error: Telegram send failed: Message is too longRoot Cause Analysis (optional)
The gateway adapters (
gateway/platforms/telegram.py,discord.py,slack.py) each callself.truncate_message()(defined inbase.py:1080-1168) in theirsend()method before dispatching to the platform API. This method splits at natural boundaries (newlines, then spaces), preserves code block fences across chunks, and adds(1/N)indicators.The standalone senders in
tools/send_message_tool.py(_send_telegram,_send_discord,_send_slack,_send_signal) call the platform APIs directly without any of that chunking.Discord has a naive
[message[i:i+2000]]split that avoids API rejection but breaks content mid-word and mid-code-block.Cron delivery in
cron/scheduler.py:_deliver_result()calls_send_to_platform()fromsend_message_tool.py, so it inherits the same gap.Proposed Fix (optional)
truncate_message()is an instance method onBasePlatformAdapterbut uses no instance state. Converting it to a@staticmethod(following the existingextract_media()pattern on the same class) would allow calling it directly asBasePlatformAdapter.truncate_message(content, max_length).BasePlatformAdapteris already imported insend_message_tool.py.The chunking can then be applied centrally in
_send_to_platform()before dispatching to individual senders, using per-platform max lengths. For multi-chunk sends, each chunk is dispatched individually. Media files (Telegram only) attach to the last chunk. Discord's character split in_send_discord()would be replaced by the centralized truncate_message() call in_send_to_platform().Are you willing to submit a PR for this?