Skip to main content

Telnyx plugin for Vision Agents - Voice call integration with media streaming

Project description

Telnyx Plugin

Telnyx plugin for Vision Agents enabling inbound and outbound phone calls with real-time bidirectional media streaming.

Features

  • Media Streaming: Bidirectional audio streaming via Telnyx Media Streaming
  • Call Control: Support for programmable inbound and outbound phone calls
  • Call Registry: Track active calls with metadata, stream objects, and validation tokens
  • Audio Conversion: PCMU, PCMA, and L16 RTP payload conversion
  • WebSocket Management: Handle Telnyx WebSocket media events
  • Stream Bridge: Attach a Telnyx phone participant to a Stream call

Installation

uv add "vision-agents[telnyx]"
# or directly
uv add vision-agents-plugins-telnyx

Usage

from vision_agents.plugins import telnyx

# Create a call registry to track active calls
registry = telnyx.CallRegistry()

# Register a call from your Telnyx webhook handler
call = registry.create(
    call_control_id="v2:abc123",
    webhook_data={"data": {"payload": {"from": "+15551234567"}}},
)

# Create a media stream for the WebSocket connection
stream = telnyx.MediaStream(websocket)
await stream.accept()

# Associate stream with call
call.telnyx_stream = stream

# Run the stream until Telnyx sends a stop event
await stream.run()

Examples

See examples/ for minimal inbound and outbound Telnyx phone examples.

# Outbound call
uv run plugins/telnyx/examples/outbound_call.py \
  --setup-telnyx \
  --from +15551234567 \
  --to +15557654321

# Inbound call server
uv run plugins/telnyx/examples/inbound_call.py \
  --setup-telnyx \
  --phone-number +15551234567

Telnyx phone calls require a Call Control App. The Call Control App is where Telnyx sends call webhooks such as call.initiated, call.answered, and call.hangup. It is also the connection_id used by the outbound Dial API. A forwarding-only phone-number connection is not enough for media streaming through this plugin.

With --setup-telnyx, the examples create a temporary Call Control App and delete it on normal shutdown. The inbound example also routes the Telnyx number to the temporary app and restores the previous routing on shutdown.

Without --setup-telnyx, the examples validate the common setup requirements:

  • TELNYX_CALL_CONTROL_APP_ID exists and is active
  • the Call Control App webhook URL matches https://<NGROK_URL>/telnyx/events
  • inbound phone numbers are routed to the Call Control App
  • restricted accounts verify outbound destination numbers before dialing

Components

TelnyxCall

Dataclass representing an active call session:

@dataclass
class TelnyxCall:
    call_control_id: str
    token: str
    webhook_data: Optional[dict[str, Any]]
    telnyx_stream: Optional[TelnyxMediaStream]
    stream_call: Optional[Any]
    started_at: datetime
    ended_at: Optional[datetime]

    # Convenience properties from Telnyx webhook payloads
    from_number: Optional[str]
    to_number: Optional[str]
    call_status: Optional[str]

TelnyxCallRegistry

In-memory registry for managing active calls:

registry = telnyx.CallRegistry()
registry.create(call_control_id, webhook_data=webhook_data)  # Register new call
registry.get(call_control_id)                                # Look up call
registry.require(call_control_id)                            # Look up or raise
registry.validate(call_control_id, token)                    # Validate media URL token
registry.remove(call_control_id)                             # Remove and mark ended
registry.list_active()                                       # List active calls

TelnyxMediaStream

Manages Telnyx Media Streaming WebSocket connections:

stream = telnyx.MediaStream(websocket)
await stream.accept()

# Access the audio track for publishing
stream.audio_track  # AudioStreamTrack matching the Telnyx media format

# Send audio back to Telnyx when bidirectional RTP streaming is enabled
await stream.send_audio(pcm_data)

# Run until the stream ends
await stream.run()

To send audio back to the call, start Telnyx streaming with stream_bidirectional_mode=rtp. The plugin supports PCMU and PCMA at 8 kHz, and L16 at 16 kHz.

Use attach_phone_to_call to bridge audio between a Telnyx media stream and a Stream call:

await telnyx.attach_phone_to_call(stream_call, stream, user_id="phone-user")

Audio Utilities

from vision_agents.plugins.telnyx import (
    TELNYX_DEFAULT_SAMPLE_RATE,
    TELNYX_L16_SAMPLE_RATE,
    l16_to_pcm,
    pcma_to_pcm,
    pcm_to_l16,
    pcm_to_pcma,
    pcm_to_pcmu,
    pcm_to_telnyx_payload,
    pcmu_to_pcm,
    telnyx_payload_to_pcm,
)

pcm = pcmu_to_pcm(payload)
payload = pcm_to_pcmu(pcm)

Configuration

Parameter Description Default
TELNYX_DEFAULT_SAMPLE_RATE Telnyx PCMU and PCMA sample rate 8000
TELNYX_L16_SAMPLE_RATE Telnyx L16 bidirectional sample rate 16000

Environment Variables

  • TELNYX_API_KEY: Your Telnyx API key for Call Control API requests.
  • TELNYX_PHONE_NUMBER: Telnyx caller ID or inbound number, in E.164 format. You can also pass this as --from or --phone-number.
  • NGROK_URL: Public HTTPS hostname that forwards to your local example server. The examples can also auto-detect a local ngrok tunnel.
  • TELNYX_CALL_CONTROL_APP_ID: Existing Call Control App ID. Required only when running without --setup-telnyx.
  • TELNYX_PHONE_NUMBER_ID: Telnyx phone number resource ID. Required for inbound only when running without --setup-telnyx.

Dependencies

  • vision-agents
  • numpy
  • fastapi

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

vision_agents_plugins_telnyx-0.6.5.tar.gz (11.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

vision_agents_plugins_telnyx-0.6.5-py3-none-any.whl (13.5 kB view details)

Uploaded Python 3

File details

Details for the file vision_agents_plugins_telnyx-0.6.5.tar.gz.

File metadata

  • Download URL: vision_agents_plugins_telnyx-0.6.5.tar.gz
  • Upload date:
  • Size: 11.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for vision_agents_plugins_telnyx-0.6.5.tar.gz
Algorithm Hash digest
SHA256 ccc09287fe6104d1dfe14ccf8533b9aa8d3c6e0a7729fd75fe4abadc2808cf23
MD5 653003423497f304b18598cbc810996a
BLAKE2b-256 f0c7d2137528a80db7120ab73aebcc68753687059899f6997136b282b4d03994

See more details on using hashes here.

File details

Details for the file vision_agents_plugins_telnyx-0.6.5-py3-none-any.whl.

File metadata

  • Download URL: vision_agents_plugins_telnyx-0.6.5-py3-none-any.whl
  • Upload date:
  • Size: 13.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for vision_agents_plugins_telnyx-0.6.5-py3-none-any.whl
Algorithm Hash digest
SHA256 b5270cbe66b5ef3367b0f4d09150bbf03baf0c6edd1a0defc414f0bd03ade1d2
MD5 7d16291e7f60c21b6190a554b9ae2791
BLAKE2b-256 363a0086b5963f962ff1b80bf17ec42ff55650f96975ac96bdec1c9579c4c0b0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page