Local Development Guide

This guide covers local installation, development-only configuration, running the gateway, the monitoring interface, public endpoint testing, and common local problems.

Prerequisites

Always use a virtual environment for this project.

These local prerequisites are sufficient only for running the code and its local connector. An end-to-end WxCC test also requires a BYOVA-enabled organization, an authorized Service App, a public TLS-enabled gateway URL, an ACTIVE datasource for that exact URL, a configured gateway connector, and a Contact Center flow using Virtual Agent V2. The gateway can register and maintain the datasource automatically when lifecycle management is enabled. Use the Local Audio Connector Configuration guide for a vendor-neutral sandbox validation. For a complete AWS Lex integration, follow the BYOVA with AWS Lex guide before attempting an end-to-end call.

Install

  1. Clone the repository:

    git clone https://github.com/webex/webex-byova-gateway-python.git
    cd webex-byova-gateway-python
    
  2. Create and activate a virtual environment:

    python -m venv venv
    source venv/bin/activate
    

    On Windows:

    venv\Scripts\activate
    
  3. Install dependencies:

    python -m pip install -r requirements-dev.txt
    
  4. Generate the Python gRPC stubs:

    python -m grpc_tools.protoc \
      -I./proto \
      --python_out=src/generated \
      --grpc_python_out=src/generated \
      proto/*.proto
    

The generated *_pb2.py and *_pb2_grpc.py files are intentionally not committed.

Configure a Local-Only Run

The checked-in configuration enables gRPC JWT validation but does not contain a datasource URL. This is intentional for security: the gateway refuses to start with incomplete enabled JWT configuration.

For a local-only test that is not connected to Webex, edit config/config.yaml and set:

authentication:
  enabled: false

jwt_validation:
  enabled: false

Do not use those settings for a Webex-connected or production endpoint. For end-to-end testing, configure the registered datasource URL and keep JWT enforcement enabled as described in JWT Authentication.

The default local audio files are included in audio/, so no additional media setup is required for the local connector. See Local Audio Connector Configuration for its agent_id, audio path, DTMF behavior, and end-to-end sandbox flow.

Run the Gateway

With the virtual environment active:

python main.py

The process starts:

Press Ctrl+C to stop the gateway and allow it to clean up active conversations.

Test Voice Agents Directly in a Browser

To isolate provider audio and response timing from WxCC, run the local Voice Agent Audio Lab. It discovers supported GECX and AWS Lex targets from the same connector configuration used by the gateway. GECX keeps call-style audio open, while AWS connector-parity targets buffer and explicitly submit one utterance at a time.

The lab is separate from main.py; it does not start a BYOVA datasource or accept WxCC traffic. Run python -m tools.voice_agent_lab --gateway-config config/config.yaml. Provider credentials stay server-side and are loaded from the selected connector’s auth configuration or default cloud credential chain. A gitignored local overlay remains available for one-off targets. Install requirements-dev.txt for the lab’s local-only HTTP and WebSocket server; gateway runtime builds continue to install only requirements.txt.

Monitoring Interface

For a local run with dashboard authentication disabled, open:

For the dashboard’s Webex OAuth setup and security model, see:

The dashboard is a development and diagnostic interface. Review the Production Readiness Guide before exposing any administrative interface in production.

Test Through a Public Endpoint

BYOVA requires a publicly reachable TLS endpoint on the domain authorized for the Service App. Use company-owned cloud infrastructure for production and whenever company ownership, security review, or compliance is required.

For temporary development testing, a tunneling service may be usable if your organization permits it. Start the tunnel first so its public URL is known before gateway startup. For example, with ngrok:

ngrok config add-authtoken YOUR_AUTHTOKEN
ngrok http --upstream-protocol=http2 50051

Put the generated HTTPS URL in jwt_validation.datasource_url. Free tunnel URLs may change between runs.

To let the gateway create or reuse the matching datasource, provide the authorized Service App OAuth values and enable lifecycle management:

export WEBEX_BYODS_CLIENT_ID="your-client-id"
export WEBEX_BYODS_CLIENT_SECRET="your-client-secret"
export WEBEX_BYODS_REFRESH_TOKEN="your-refresh-token"
jwt_validation:
  enabled: true
  enforce_validation: true
  datasource_url: "https://your-current-tunnel.example"
  datasource_schema_uuid: "5397013b-7920-4ffc-807c-e8a3e0a18f43"

data_source:
  enabled: true
  fail_startup_on_error: true
  auth:
    type: "oauth_refresh"
    client_id_env: "WEBEX_BYODS_CLIENT_ID"
    client_secret_env: "WEBEX_BYODS_CLIENT_SECRET"
    refresh_token_env: "WEBEX_BYODS_REFRESH_TOKEN"

Start the gateway after saving the URL. Startup completes registration before the gRPC listener accepts traffic and prints the datasource ID to use in the Contact Center virtual-agent feature. If the tunnel URL changes, update datasource_url before restarting; the old registration is not deleted automatically.

Consumer tunnels are development-only:

See Security Configuration for a company-controlled TLS and load-balancer starting point.

Troubleshooting

The Gateway Fails With an Empty Datasource URL

If JWT validation is enabled, jwt_validation.datasource_url is required. For local-only testing, disable JWT validation. For Webex-connected testing, configure the exact registered URL. See JWT Authentication.

Datasource Registration Fails

Confirm the Service App is authorized with datasource read and write scopes, the three WEBEX_BYODS_* environment variables are visible to the gateway process, and the public domain is allowed by the Service App. If multiple registrations match the URL and schema, set WEBEX_BYODS_DATA_SOURCE_ID to the intended datasource ID. See Configuration for all lifecycle options.

Port 50051 or 8080 Is Already in Use

Find the process using the port:

lsof -i :50051
lsof -i :8080

Stop the conflicting application or change the corresponding port in config/config.yaml.

Python or Imports Cannot Be Found

Confirm the virtual environment is active:

echo "$VIRTUAL_ENV"
which python

If necessary, recreate it:

python -m venv venv
source venv/bin/activate
python -m pip install -r requirements-dev.txt

Generated Modules Cannot Be Imported

Regenerate the gRPC files:

python -m grpc_tools.protoc \
  -I./proto \
  --python_out=src/generated \
  --grpc_python_out=src/generated \
  proto/*.proto

Review Logs

The gateway logs to standard output and, when configured, logs/gateway.log. The monitoring application uses logs/web.log. Adjust logging levels in config/config.yaml; do not enable unsafe payload or audio logging with customer traffic.