Skip to content

[Spike]: WhatsApp message-template + long-content strategy (blocks #438) #440

Description

@initializ-mk

Spike (time-boxed investigation, no shipping code) — blocks the WhatsApp adapter implementation in #438.

Context

The WhatsApp Cloud API rejects free-form text outside a 24-hour customer-service window opened by a user-initiated inbound message, and requires a pre-approved message template (type: "template" with name, language, components) for proactive/business-initiated sends. The WhatsApp adapter in #438 is outbound-only with no inbound in v1, so there is effectively no open window for scheduled/proactive delivery → SendResponse must send a template message.

This has no analog in the Telegram/Slack adapters (which send free text unconditionally and chunk/upload long content via markdown.SplitMessage). We need the template + long-content strategy settled before writing whatsapp.go, because it dictates the config schema, the SendResponse payload builder, and the tests.

Goal

Produce a written decision (comment or short design note on this issue) that answers the questions below concretely enough that #438 can be implemented without further design debate.

Questions to answer

  1. Template selection.

    • Fixed default template (name + language) in whatsapp-config.yaml, or per-schedule override (extend ScheduleConfig)? Recommend one for v1.
    • What's the components/parameter shape? Most likely: one body template with a single {{1}} parameter carrying the agent's response summary. Confirm against a real approved-template example.
    • Language policy: single configured language.code (e.g. en_US), or derive it? v1 default.
  2. Long-content handling (the agent's response can be long markdown; WhatsApp body parameters have length limits — the Telegram/Slack SplitMessage/file-upload path does not apply).

    • Truncate the summary into the body parameter (and rely on a2a.Message.Summary when present, as Telegram/Slack already prefer)?
    • Or send a media/document message (upload → type: document) for long reports?
    • Or split across multiple template sends? (Likely undesirable — each is billable and rate-limited.)
    • Decide the v1 behavior + a hard character cap.
  3. Parameter safety. WhatsApp rejects template body parameters containing newlines, tabs, or >4 consecutive spaces. Define the sanitization step (collapse whitespace, strip newlines) the SendResponse builder must apply, and where it lives (in markdown.ToWhatsApp or the send path).

  4. Freeform fallback (scope check). Is allow_freeform (send type: text when a window is known open) worth any v1 investment, given there's no inbound to open a window? Recommend include/defer. If deferred, note it's a v2 concern tied to the inbound-webhook question in [Feature]: WhatsApp channel adapter (outbound-only, like Telegram/Slack) #438.

  5. Config schema. Given the above, specify the exact whatsapp-config.yaml settings: keys the adapter reads in Init (e.g. phone_number_id, access_token_env, api_version, template_name, template_language, max_body_chars), so [Feature]: WhatsApp channel adapter (outbound-only, like Telegram/Slack) #438's config template and Init validation are locked.

  6. Provider constraints to record. Pin the Meta Graph API version, note the template approval lead time (templates must be pre-approved in Meta Business Manager — a human/ops dependency, not code), and the per-number send rate limits that bound scheduled-delivery throughput.

Deliverable

A decision note on this issue covering (1)–(6), plus a sample type: template request body (the exact JSON SendResponse will POST to graph.facebook.com/<ver>/<phoneID>/messages) that the #438 implementation and its tests can be built against.

Out of scope

Parent

Part of #438 (WhatsApp channel adapter, outbound-only). Resolves open questions #1 and #2 there.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions