Skip to main content
Status: In Development · Playground demo coming soon. The recipe below is complete and runnable today; only the hosted playground showcase is pending.
A business with multiple WABA numbers (say, one for sales, one for support, one for VIPs) where a customer who pings any of them sees a coherent agent that knows the full relationship. Memory lives at the business level; the WABA number is metadata, not identity.

What you’ll build

A multi-WABA setup where:
  • One business owns N WABA numbers (sales, support, account management, regional lines)
  • Customer memory is shared across all numbers: same user_id, same customer_id
  • Source WABA is preserved in metadata so you can still segment by which line the customer came in on
  • Persona per WABA: the sales agent and the support agent can have different system prompts but the same memory
Est. build time: 60-75 minutes (similar to single-WABA + a router).

When to use this recipe

Build this if:
  • One business runs multiple WhatsApp numbers for different functions
  • A customer who texts your sales line should be recognized when they later text your support line
  • You want each number to act like a specialist (different persona) but with full shared customer history
  • You’re okay with the customer phone being the cross-number identifier (they’re using one phone to reach you)

Architecture at a glance

The customer always gets a reply on the number they texted. Internally, all numbers see the same memory.

Stack

Prerequisites

  • A Synap API key. See Authentication
  • Multiple WABA numbers under one Meta Business Manager (so they share one webhook)
  • A System User token with whatsapp_business_messaging scope, valid across all WABAs
  • Python: Python 3.11+
  • TypeScript: Node 18+ and Python 3.11+ on the host
If your WABA numbers are spread across separate Meta Businesses, you’ll need separate webhooks and access tokens. The routing pattern below still works, you just maintain a token map keyed by phone_number_id.

Install

Build it

1. The persona registry

One config block defines all the numbers and their personas.

2. Shared scoping

The customer’s phone is the user_id. The business is the customer_id. The WABA number is in metadata.
  • customer_id = "<your-business>": single, across all WABAs
  • user_id = <customer phone>
  • conversation_id = <customer phone>: rolling, shared across WABAs
This is the whole point of the recipe: same identity, same memory, regardless of which number they used.
conversation_id, user_id, and customer_id must be valid UUIDs. Since these key off the customer phone, derive a deterministic UUID from it with uuid.uuid5(...) (Python) rather than passing the raw phone string. The same phone always maps to the same UUID, preserving the shared-identity behavior.

3. The unified webhook

Meta sends every inbound to the same webhook URL with phone_number_id indicating which WABA received it.

4. The persona-aware agent

Each persona has its own system prompt. They all share the same memory pool.

5. Source-aware retrieval (optional)

Sometimes a persona wants to look at only its own history (e.g., the support agent reviewing prior support tickets specifically). Filter by metadata:

Run & verify

Sales WABA (yesterday)
Support WABA (today)
The support agent picked up the sales-line conversation from yesterday: no engineering required to bridge the two numbers. It’s just shared memory.

Customize / extend

  • Regional WABAs sharing memory → use the same pattern, with source_waba: "us" / "eu" etc. Add a language preference memory and the persona auto-greets in the right language.
  • Outbound campaigns per persona → combine with Single-WABA Campaign + Inbound, but scoped per source_waba.
  • Cross-persona handoff → if the sales agent decides the customer is really a support issue, write a memory note and have the next inbound on the support line lean into it.
  • B2B multi-tenant → if the same business has multiple corporate customers, layer in Patterns → Multi-Tenant SaaS by pushing tenant ID into customer_id.

Troubleshooting

Persona ignores cross-line history
  • Confirm customer_id is the same across all personas (it should be the business ID, not the WABA ID).
  • If you accidentally set customer_id = waba_id, you’ve created separate memory pools. Fix by re-keying.
Customer gets replied to on the wrong number
  • Make sure wa_for(phone_number_id) uses the right access token / sender ID. Sending from the wrong WABA looks deeply weird to the customer.
Source-WABA metadata missing on some turns
  • Audit the webhook parsing. phone_number_id lives at the entry level in the WhatsApp webhook payload, not on every individual message.
Memory shows wrong persona’s name on past turns
  • The direction: "outbound" documents tag persona name. If you renamed a persona, the historical tag stays. That’s fine, it’s an audit trail, not a routing key.