Skip to content

feat(whatsapp): add configurable human cascade delivery - #58703

Open
devatnull wants to merge 3 commits into
NousResearch:mainfrom
devatnull:feat/whatsapp-human-cascade-v2
Open

feat(whatsapp): add configurable human cascade delivery#58703
devatnull wants to merge 3 commits into
NousResearch:mainfrom
devatnull:feat/whatsapp-human-cascade-v2

Conversation

@devatnull

@devatnull devatnull commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add configurable human-style WhatsApp cascade delivery for suitable prose replies
  • split readable paragraph-style replies into a small number of natural WhatsApp bubbles
  • keep structured output, code blocks, copy-sensitive text, approval gates, links/action context, and group chats atomic by default
  • preserve bridge multi-message ID tracking with snake_case raw_response["message_ids"]
  • keep gateway/status/stream-preview chrome single-unit via metadata["delivery_style"] = "single"

Stack

This PR is stacked on #58929 (fix(gateway): preserve final delivery on non-editable streams). Once #58929 lands, this PR can be rebased to show only the WhatsApp adapter cascade layer.

Why

WhatsApp is a chat UI, not a markdown document viewer. Large prose replies are hard to read as one wall of text, but blindly splitting every blank line is dangerous for approvals, commands, configs, logs, code, and copy/paste content. This keeps the behavior WhatsApp-specific and conservative.

Behavior

Cascade is gated by:

  • platform: WhatsApp only
  • chat type: DMs by default; groups require platform-extra opt-in
  • response shape: substantive prose with paragraph boundaries
  • safety: approval gates, code/copy-sensitive payloads, links/action context, and structured output stay atomic
  • platform extras: enable/disable cascade, max bubbles, total/lead/bubble length thresholds, merged-tail cap, group behavior, and inter-bubble delays
  • metadata override: delivery_style="single" forces atomic delivery; delivery_style="cascade" can force cascade for explicit adapter callers

Test plan

  • python3 -m pytest tests/gateway/test_whatsapp_formatting.py tests/gateway/test_gateway_status_delivery_style.py tests/gateway/test_run_progress_topics.py::test_proxy_non_editable_streaming_uses_final_delivery_only tests/gateway/test_run_progress_topics.py::test_run_agent_non_editable_streaming_uses_final_delivery_only tests/gateway/test_stream_consumer_thread_routing.py::TestInitialReplyToId -q
  • scripts/run_tests.sh tests/gateway/test_whatsapp_formatting.py tests/gateway/test_gateway_status_delivery_style.py tests/gateway/test_run_progress_topics.py tests/gateway/test_stream_consumer_thread_routing.py -q
  • python3 -m py_compile plugins/platforms/whatsapp/adapter.py gateway/run.py gateway/stream_consumer.py tests/gateway/test_whatsapp_formatting.py tests/gateway/test_gateway_status_delivery_style.py tests/gateway/test_run_progress_topics.py tests/gateway/test_stream_consumer_thread_routing.py
  • git diff --check origin/main...HEAD
  • added-lines private/secret pattern scan against the combined diff

Copilot AI review requested due to automatic review settings July 5, 2026 07:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a WhatsApp-specific, configurable “human cascade” delivery style so longer prose replies can be split into a small number of natural chat bubbles while keeping structured/copy-sensitive sections (code blocks, lists/reports, approval gates, links/tails) atomic. This integrates with gateway streaming/status paths so interim/progress messages do not accidentally cascade.

Changes:

  • Implement WhatsApp adapter heuristics/config for human-cascade paragraph splitting, atomic section protection, and jittered inter-bubble delays.
  • Ensure non-final streaming sends and gateway status/progress sends force single-message delivery style.
  • Add extensive WhatsApp formatting tests plus targeted tests for stream/status metadata behavior.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
plugins/platforms/whatsapp/adapter.py Implements configurable human-cascade splitting and send-path changes (IDs, delays).
gateway/stream_consumer.py Forces non-final stream metadata to single delivery style to prevent cascades.
gateway/run.py Forces gateway status/progress sends to single delivery style.
tests/gateway/test_whatsapp_formatting.py Adds comprehensive unit tests for cascade vs atomic behavior across content shapes.
tests/gateway/test_stream_consumer.py Adds tests ensuring non-final/“commentary” sends force single delivery style.
tests/gateway/test_gateway_status_delivery_style.py Adds tests ensuring status/progress sends force single delivery style.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +466 to +471
self._human_cascade_min_total_chars = self._coerce_int_extra(
"human_cascade_min_total_chars", 300
)
self._human_cascade_min_lead_chars = self._coerce_int_extra(
"human_cascade_min_lead_chars", 40
)
Comment thread gateway/stream_consumer.py Outdated
Comment on lines +237 to +243
if not final:
# Stream previews, tool-boundary text, and interim commentary are
# status/progress UI, not the final assistant reply. Messaging
# adapters that support natural multi-bubble delivery (WhatsApp)
# must keep these as one unit so scratch/status text never fans out
# into a cascade.
meta.setdefault("delivery_style", "single")
Comment thread gateway/run.py Outdated
Comment on lines +475 to +478
metadata = dict(metadata or {})
# Status/thinking/progress bubbles are gateway chrome, not the final answer.
# Keep them single-unit on platforms with natural cascade support.
metadata.setdefault("delivery_style", "single")
@alt-glitch alt-glitch added type/feature New feature or request comp/gateway Gateway runner, session dispatch, delivery platform/whatsapp WhatsApp Business adapter sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages P3 Low — cosmetic, nice to have labels Jul 5, 2026
@devatnull
devatnull force-pushed the feat/whatsapp-human-cascade-v2 branch 3 times, most recently from 12762b1 to 4db1058 Compare July 5, 2026 15:35
@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 15, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for separating the WhatsApp adapter behavior from the gateway delivery safeguards. The proxy-path premise is current: gateway/run.py:17023-17055 still creates a stream consumer for a non-editable adapter, whereas the direct path already skips it at gateway/run.py:18352-18354.

Problems

  • plugins/platforms/whatsapp/adapter.py:451-490 adds default-enabled, user-configurable human_cascade_* behavior, but this PR has no documentation change. The existing WhatsApp guide says progressive edited streaming is supported at website/docs/user-guide/messaging/whatsapp.md:187-193; that conflicts with the new SUPPORTS_MESSAGE_EDITING = False at adapter.py:388-392. The guide also does not document the cascade opt-out or tuning keys.

Suggested changes

  • Update the WhatsApp guide with final-only delivery semantics and a gateway.platforms.whatsapp.extra cascade configuration example, including the disable switch and DM/group defaults.

This is an automated hermes-sweeper review.

# payloads still fall back to truncate_message(). Config lives in
# gateway.platforms.whatsapp.extra.* so no new user-facing env knobs are
# required for this adapter-level behavior.
self._human_cascade_messages = self._coerce_bool_extra(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These default-enabled human_cascade_* controls need user documentation. Please update website/docs/user-guide/messaging/whatsapp.md with the gateway.platforms.whatsapp.extra keys, the opt-out, and the changed final-only delivery behavior introduced by SUPPORTS_MESSAGE_EDITING = False.

@devatnull
devatnull force-pushed the feat/whatsapp-human-cascade-v2 branch from 4db1058 to 1ff14ba Compare July 16, 2026 10:03
@devatnull
devatnull force-pushed the feat/whatsapp-human-cascade-v2 branch from 1ff14ba to f173cfb Compare July 16, 2026 10:04

@GottZ GottZ left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was generated by AI during triage.

Summary

Two PRs address the same WhatsApp delivery problem: #54455 introduced configurable paragraph-based cascade delivery plus gateway safeguards, while #58703 carries a revised implementation with configuration documentation, final-only delivery semantics, message-ID handling, and expanded regression coverage. No recorded verify verdict or best-fix determination selects either PR.

Related pull requests

  • #54455 [closed] duplicate — (+1089/-12) — closed precursor and substantial duplicate of #58703: the diff implements WhatsApp prose cascading, atomic handling for structured or action-sensitive content, single-unit status/preview delivery, and extensive tests. It remains relevant because its contributor explicitly closed the old branch to rebuild the changes cleanly, and #58703 contains the substantially overlapping replacement implementation.
  • #58703 related — (+895/-15) — keep-open salvage candidate, not a verified best fix: the diff implements configurable WhatsApp cascade heuristics, final-only behavior for the non-editable adapter, single-unit gateway chrome, normalized multi-message ID tracking, tests, and user documentation. The contributor keep_open review identified missing documentation and a conflict with the guide; the current diff explicitly addresses that objection in website/docs/user-guide/messaging/whatsapp.md by documenting final-only delivery, opt-out and tuning keys, and DM/group defaults.

Duplicates

#54455 and #58703 substantially duplicate the same WhatsApp human-cascade implementation; #54455 is the closed precursor, while #58703 contains the updated version and documentation.

Suggested consolidation

Keep #58703 open with a salvage path: retain the WhatsApp adapter cascade behavior, configuration documentation, message-ID compatibility, and focused formatting/status tests, while separating or reducing the broader gateway non-editable-streaming changes if needed for reviewability. This is consistent with the contributor keep_open review after its documented objection was addressed, but it is not a merge recommendation because no verify best_fix was recorded. Keep #54455 closed as the superseded duplicate of #58703.

Complex graph

flowchart LR
    classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
    classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
    classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
    classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
    classDef best stroke-width:3px,stroke:#b45309
    classDef target stroke-width:3px,stroke:#4338ca
    subgraph Dup54455 ["PRs duplicating each other"]
        P54455["PR #54455 (closed)"]
        P58703["PR #58703 (open)"]
    end
    class P54455 closed
    class P58703 open
    class P58703 target
    click P54455 "https://github.com/NousResearch/hermes-agent/pull/54455"
    click P58703 "https://github.com/NousResearch/hermes-agent/pull/58703"
Loading

Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label).

Cross-PR triage: Reviewed 2 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 109 kB of PR diffs, 4 kB of issue/PR text, 6 kB of discussion (4 comments), 0 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

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 platform/whatsapp WhatsApp Business adapter sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants