Skip to main content
Assign each of your agents a phone number, drop them in a registry, and the gateway dispatches every inbound WhatsApp/SMS message to the right agent.
from praisonaiagents import Agent
from praisonai_bot.bots import AgentRegistry

support = Agent(name="support", instructions="Help customers with product issues.")
sales   = Agent(name="sales",   instructions="Answer pricing and demo questions.")

registry = AgentRegistry(default_agent=support)
registry.assign("+1 (415) 555-0123", support)
registry.assign("+442071838750",    sales)

# The gateway calls this for every inbound message
agent = registry.resolve("+14155550123")  # → support
Users experience it as three separate helplines backed by one gateway:
User textsNumberRouted toReply
Alice: “my order hasn’t arrived”+1 415 555 0123support agentShipment lookup
Bob: “what does the Pro plan cost?”+44 20 7183 8750sales agentPricing answer
Priya: brand-new numbernever seen beforetriage default agent”Who are you trying to reach?”

Quick Start

1

Enable with a single agent

One number, one agent. Normalisation means the formatting you assign with does not have to match the inbound format.
from praisonaiagents import Agent
from praisonai_bot.bots import AgentRegistry

agent = Agent(name="support", instructions="Be helpful.")

registry = AgentRegistry()
registry.assign("+14155550123", agent)

registry.resolve("+1 (415) 555-0123")  # → agent  (normalisation matches)
2

Multiple agents, multiple numbers

Add a default_agent so unknown numbers still get answered.
from praisonaiagents import Agent
from praisonai_bot.bots import AgentRegistry

support = Agent(name="support", instructions="Product help.")
sales   = Agent(name="sales",   instructions="Pricing and demos.")
triage  = Agent(name="triage",  instructions="Greet new callers and route them.")

registry = AgentRegistry(default_agent=triage)
registry.assign("+14155550123", support)
registry.assign("+442071838750", sales)

registry.resolve("+14155550123")     # → support
registry.resolve("+61 400 123 456")  # → triage (fallback)
3

Wire it into a WhatsApp bot

A real gateway calls registry.resolve(inbound_number) on every message, then hands the chat to the chosen agent. See WhatsApp Bot for the full bot setup.
from praisonai_bot.bots import AgentRegistry

registry = AgentRegistry(default_agent=triage)
registry.assign("+14155550123", support)
registry.assign("+442071838750", sales)

async def on_inbound(webhook):
    # `to_number` is the WhatsApp business number the user messaged
    agent = registry.resolve(webhook["to_number"])
    reply = await agent.chat(webhook["text"])
    return reply

How It Works

The gateway resolves the destination number to an agent, runs the chat, and replies on the same channel.
StepWhat happens
WebhookThe inbound message carries the business number the user texted (to_number)
Resolveregistry.resolve(to_number) returns the assigned agent, the default_agent, or None
ChatThe gateway runs the chosen agent with the user’s text
ReplyThe response is sent back on the same channel

Number Normalisation

"+1 (415) 555-0123" and "+14155550123" resolve to the same agent because normalize_number strips every non-digit and preserves a single leading +. Blank, non-string, or digit-free inputs normalise to None.
InputNormalised key
"+1 (415) 555-0123""+14155550123"
"+44 20 7183 8750""+442071838750"
"14155550123" (no leading +)"14155550123"
"", " ", None, non-stringNone

API Reference

AgentRegistry(default_agent=None)

In-memory phone-number → agent routing table. No I/O, no dependencies. Not thread-safe.
OptionTypeDefaultDescription
default_agentAny | NoneNoneFallback returned by resolve() when the inbound number is unknown or blank. When None, unknown numbers resolve to None.
Methods
MethodSignatureReturnsDescription
assignassign(number: str, agent: Any) -> strNormalised key (str)Assign number to agent. Re-assigning replaces the previous agent. Raises ValueError if number normalises to empty.
unassignunassign(number: str) -> boolboolRemove any agent for number. Returns True if a mapping was removed, else False.
resolveresolve(number: Optional[str]) -> Optional[Any]Agent or NoneReturn the agent assigned to number, else default_agent, else None.
numbersnumbers() -> List[str]List[str]All assigned (normalised) numbers.
__contains__number in registryboolMembership test using the normalised key.
__len__len(registry)intNumber of assigned numbers.
__iter__for key, agent in registryIterator[Tuple[str, Any]]Iterate (normalised_number, agent) pairs.

normalize_number(number)

normalize_number(number: Optional[str]) -> Optional[str] returns the canonical key, or None when blank / non-string / no digits.
  • Strips whitespace and formatting characters (spaces, dashes, parens, dots).
  • Preserves a single leading +.

AgentRegistry vs ChannelDirectory

Pick by message direction: AgentRegistry routes inbound by phone number; ChannelDirectory routes outbound by target name.

Common Patterns

Fallback agent — set a default_agent so unknown numbers are never left unanswered.
from praisonaiagents import Agent
from praisonai_bot.bots import AgentRegistry

triage = Agent(name="triage", instructions="Greet new callers and route them.")
registry = AgentRegistry(default_agent=triage)

registry.resolve("+61 400 123 456")  # → triage (no assignment yet)
Dynamic re-assignment — remap or drop a number at runtime.
registry.assign("+14155550123", sales)   # move that number to sales
registry.unassign("+442071838750")       # take sales off that number
"+14155550123" in registry               # → True
len(registry)                            # → 1
list(registry)                           # → [("+14155550123", <Agent name='sales'>)]

Best Practices

Store numbers as +<country><digits> (E.164). Normalisation still handles human-typed variants like "+1 (415) 555-0123", but E.164 is unambiguous and matches what most webhooks send.
The registry holds references to already-constructed agents and does no I/O. Create it once at startup and consult it on every inbound message.
Set AgentRegistry(default_agent=triage) if you never want to leave an inbound message unanswered. Without it, unknown numbers resolve to None and the caller must handle that case.
Construct it before your gateway starts and treat it as read-mostly. If you mutate it from multiple threads, add your own lock.

WhatsApp Bot

Connect an agent to WhatsApp — Cloud API or Web mode.

Channels Gateway

Route agents across Telegram, Discord, Slack, and WhatsApp.

Messaging Bots

All supported messaging platforms in one place.

Platform-Aware Agents

Outbound routing with ChannelDirectory and ReachableTarget.