Skip to content

[Bug]: send_message tool and cron delivery skip message chunking, causing delivery failures for long messages #1552

@llbn

Description

@llbn

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

  1. Create a cron job with deliver: origin that produces a response longer than the platform's message limit (e.g. >4096 chars for Telegram)
  2. Wait for the job to run
  3. 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?

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions