Skip to content

[Gap] PSTN parity: Twilio+Realtime lives in api/call.py, not Bot registry — vs OpenClaw voice-call plugin #1326

@Dhivya-Bharathy

Description

@Dhivya-Bharathy

[Gap] PSTN parity: Twilio+Realtime lives in api/call.py, not Bot registry — vs OpenClaw voice-call plugin

Executive summary

Field Content
OpenClaw reference Voice Call plugin — telephony via Plivo or Twilio, documented as an installable assistant capability with CLI voicecall in their docs index.
PraisonAI reality Messaging bots are first-class in praisonai.bots (_registry.py). PSTN exists mainly as a standalone Twilio + OpenAI Realtime sample in praisonai/api/call.py, not registered as a bot platform next to Telegram/Discord. Plivo does not appear in src/praisonai Python sources (no PSTN provider choice matching OpenClaw’s doc).
Gap type Product / integration fragmentation — not “no Twilio string anywhere”; the gap is parity with OpenClaw’s unified voice-call plugin story (provider options, Gateway/BotOS alignment, discoverability).
Severity Product / parity. Affects: checklist comparisons, “call my assistant” RFPs.

1. OpenClaw target (reference only)

OpenClaw documents a voice call capability with Plivo or Twilio as providers. That is positioned as part of their plugin ecosystem, not an unrelated demo script.


2. Where messaging channels live (canonical bot surface)

File: src/praisonai/praisonai/bots/_registry.py

Built-in platforms are explicit string keys → lazy (module, class) tuples:

_BUILTIN_PLATFORMS: Dict[str, tuple] = {
    "telegram": ("praisonai.bots.telegram", "TelegramBot"),
    "discord": ("praisonai.bots.discord", "DiscordBot"),
    "slack": ("praisonai.bots.slack", "SlackBot"),
    "whatsapp": ("praisonai.bots.whatsapp", "WhatsAppBot"),
    "email": ("praisonai.bots.email", "EmailBot"),
    "agentmail": ("praisonai.bots.agentmail", "AgentMailBot"),
}

Runtime extension exists via register_platform() (_registry.py:39–46) — but there is no built-in "twilio", "voice", "pstn", or "plivo" key in _BUILTIN_PLATFORMS.

Takeaway: Evaluators who compare “channels” on OpenClaw vs Praison will not find PSTN listed alongside Telegram/Slack in the same registry table.


3. Twilio PSTN + Realtime — separate FastAPI module (api/call.py)

File: src/praisonai/praisonai/api/call.py

This module implements incoming Twilio voiceWebSocket media streamOpenAI Realtime API (wss://api.openai.com/v1/realtime?...).

Imports:

from twilio.twiml.voice_response import VoiceResponse, Connect

Incoming call handler (TwiML):

@app.api_route("/", methods=["GET", "POST"])
async def handle_incoming_call(request: Request):
    """Handle incoming call and return TwiML response to connect to Media Stream."""
    response = VoiceResponse()
    ...
    connect.stream(url=f'wss://{host}/media-stream')

Media bridge:

@app.websocket("/media-stream")
async def handle_media_stream(websocket: WebSocket):
    """Handle WebSocket connections between Twilio and OpenAI."""
    ...
    async with websockets.connect(
        'wss://api.openai.com/v1/realtime?model=gpt-4o-realtime-preview-2024-10-01',

Takeaway: This is a self-contained FastAPI app pattern (uvicorn-oriented), not the same architectural slot as OpenClaw’s voice-call plugin documentation (plugin install, CLI, Gateway-centric narrative). It also does not add Plivo or a second provider in-repo.


4. CLI praisonai call — different code path

File: src/praisonai/praisonai/cli/commands/call.py

The Typer call command delegates to PraisonAI().main() with argv ['call', ...] — it does not import or start api/call.py’s FastAPI server in this file.

    from praisonai.cli.main import PraisonAI
    ...
        praison = PraisonAI()
        praison.main()

Takeaway: Operators may assume praisonai call is the Twilio PSTN server; wiring is not documented here as a single obvious path. Gap vs OpenClaw: one documented voicecall / plugin story vs multiple entry concepts (CLI call, api/call.py demo).


5. Architecture comparison (Mermaid)

OpenClaw (conceptual — plugin doc)

flowchart LR
  subgraph OC["OpenClaw voice-call (documented)"]
    P[Voice plugin]
    T[Twilio / Plivo]
    G[Gateway / assistant]
    G --> P --> T
  end
Loading

PraisonAI (this repo — simplified)

flowchart TB
  subgraph Bots["praisonai.bots._registry"]
    TG[telegram]
    DC[discord]
    SL[slack]
    WA[whatsapp]
    EM[email]
  end
  subgraph PSTN["api/call.py (standalone)"]
    TW[Twilio TwiML + WS]
    OA[OpenAI Realtime]
    TW --> OA
  end
  Bots -.-x PSTN
Loading

The dashed “missing link” is intentional: registry does not list PSTN; api/call.py is not a registered platform key.


6. Repository checks (Plivo / telephony keywords)

  • plivo: no matches under src/praisonai/**/*.py (search at authoring time).
  • twilio: present in api/call.py (TwiML / voice).
  • Bot package docstring still lists Telegram, Discord, Slack, WhatsApp (+ orchestrator) — not PSTN:
Provides messaging bot runtimes for Telegram, Discord, Slack, and WhatsApp,
plus the user-friendly Bot and BotOS orchestrator classes.

7. Sequence (incoming call — api/call.py only)

sequenceDiagram
  participant PSTN as Twilio PSTN
  participant API as FastAPI api/call.py
  participant OAI as OpenAI Realtime

  PSTN->>API: POST / (TwiML request)
  API->>PSTN: TwiML + stream wss://.../media-stream
  PSTN->>API: WebSocket /media-stream
  API->>OAI: wss://api.openai.com/v1/realtime
  OAI-->>API: audio / events
  API-->>PSTN: media events
Loading

This path does not appear in the BotOS platform resolution flow (resolve_adapter in _registry.py).


8. Suggested engineering directions

  1. Wontfix: Document that PSTN is demo/experimental via api/call.py; messaging bots are the supported channel matrix.
  2. Unify: Register a twilio_voice (or similar) adapter in _registry.py + docs + tests; optional Plivo adapter for OpenClaw-style provider choice.
  3. Product: Single “praisonai serve voice” (or plugin) that matches Gateway/serve auth and observability.

9. Acceptance criteria

  • Decision: unified voice-call product | keep demo-only | wontfix.
  • If unify: one documented entrypoint + registry or serve integration + security (caller trust).
  • If Plivo required for parity: implementation or explicit “Twilio only” positioning.

10. Out of scope

  • WhatsApp voice notes vs PSTN.
  • OpenAI Realtime feature completeness — unless tied to product voice-call scope.

Appendix — files cited

Path Role
src/praisonai/praisonai/bots/_registry.py Built-in platform keys; register_platform
src/praisonai/praisonai/bots/__init__.py Lazy exports; package description
src/praisonai/praisonai/api/call.py Twilio + OpenAI Realtime FastAPI
src/praisonai/praisonai/cli/commands/call.py CLI praisonai callPraisonAI().main()

Evidence from PraisonAI src/praisonai/; re-verify after refactors.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationsecurity

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions