hermes-plivo-phone-gateway
Plivo voice channel for Hermes Agent. Real-time phone conversations with the agent over Plivo, inbound and outbound.
| Capability | Detail |
|---|---|
| Inbound calls | Any Hermes agent becomes reachable on a phone number |
| Outbound calls | The agent dials out and talks to whoever answers |
| Barge-in | The agent stops speaking the moment it is interrupted |
| Keypad input | DTMF digits reach the agent as text |
| Call end | Silence, a call-length limit, a hangup, or the agent ending the call |
| Provisioning | Plivo is configured automatically on every start, including a public URL |
Speech-to-text, the model turn and text-to-speech are Hermes settings, shared with every other channel. The plugin handles telephony and barge-in.
Requirements
| Hermes Agent | With the gateway and its voice extra, which carries the speech-detection model. Python 3.11 or later |
| Plivo | An account and a voice-enabled number |
ffmpeg |
Only when PLIVO_VOICE_STREAMING_TTS is false, which is the default |
cloudflared is fetched automatically when no public URL is configured.
Installation
1. Install
pip install hermes-plivo-phone-gateway
hermes-plivo-tools is installed alongside it and provides outbound calling.
2. Enable
hermes plugins enable plivo_voice-platform
hermes plugins list
The name includes the -platform suffix. Hermes strips it to derive the channel name
plivo_voice, and rejects the short form.
3. Add credentials
In ~/.hermes/.env:
PLIVO_AUTH_ID=MAxxxxxxxxxxxxxxxxxx
PLIVO_AUTH_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
PLIVO_PHONE_NUMBER=+14155550100
hermes gateway setup lists these three. Additional optional settings live in the same file
and are listed under Configuration. A pip-installed plugin does not appear in
the hermes config screens.
4. Start the gateway
hermes gateway run # foreground
hermes gateway install # or as a supervised service
The number can be reached once the log reads:
[plivo_voice] READY. Call +141****0100 to talk to the agent.
A temporary tunnel can take up to 2 minutes. Setting PLIVO_VOICE_PUBLIC_URL removes the
delay. Numbers are masked in Hermes logs.
5. Verify
python -m hermes_plivo_voice.doctor
Checks credentials, the Plivo API, the registered answer URL, text-to-speech, speech detection and the caller allowlist, and reports which of them would stop a call working.
Outbound calls
hermes-plivo-tools is installed as a dependency and only needs enabling:
hermes plugins enable plivo-tools
Enabling adds make_call, send_sms and lookup_number. The plugin answers the outbound
call itself, and whoever picks up talks to the agent exactly as an inbound caller would.
Call +14155550100 and ask what time the meeting starts.
A call is refused rather than placed when the plugin's answer URL is not responding, or when Plivo rejects the credentials.
Configuration
Read from ~/.hermes/.env. Speech providers are configured in ~/.hermes/config.yaml under
stt and tts, documented in Hermes'
voice mode guide.
Required
| Variable | Purpose |
|---|---|
PLIVO_AUTH_ID |
Plivo auth ID |
PLIVO_AUTH_TOKEN |
Plivo auth token. Also verifies callback signatures |
PLIVO_PHONE_NUMBER |
The answering number, E.164 |
Optional
| Variable | Default | Purpose |
|---|---|---|
PLIVO_VOICE_PUBLIC_URL |
unset | Public HTTPS base Plivo reaches the plugin on, and it must forward WebSocket upgrades as well as HTTP. Required for deployment. A temporary tunnel is opened when unset |
PLIVO_VOICE_STREAMING_TTS |
false |
true speaks the reply as it is generated. Reduces time to first audio from 27 seconds to about 3, and removes the ffmpeg requirement. Needs a streaming-capable provider |
PLIVO_VOICE_ALLOWED_USERS |
empty | Comma-separated numbers allowed to call the agent, digits only. Empty admits every caller. Inbound only, and it does not grant outbound |
PLIVO_VOICE_ALLOWED_DESTINATIONS |
empty | Comma-separated numbers the agent is allowed to call, digits only. Empty refuses every outbound call. Independent of the inbound list |
PLIVO_VOICE_IDLE_TIMEOUT |
60 |
Seconds of caller silence before hangup. 0 disables |
PLIVO_VOICE_MAX_CALL_SECONDS |
600 |
Maximum call length. 0 disables |
PLIVO_VOICE_MAX_CONCURRENT_CALLS |
20 |
Simultaneous calls. 0 disables. Callers beyond the limit hear a short message |
PLIVO_VOICE_AUTO_WIRE |
true |
false leaves the Plivo application and number untouched, to be configured by hand. The log prints the answer URL to use |
PLIVO_VOICE_WS_PORT |
8791 |
Local port for the HTTP and WebSocket server |
PLIVO_VOICE_SYSTEM_PROMPT |
built-in | Replaces the per-turn instruction keeping replies speakable |
PLIVO_VOICE_SILERO_MODEL |
auto | Path to a Silero ONNX model, when the bundled copy is unreachable |
PLIVO_VOICE_INSECURE_NO_SIGNATURE |
false |
true accepts unverified callbacks. Development only |
PLIVO_VOICE_RAW_DUMP |
unset | Path to append raw inbound audio to. Unencrypted |
Audio rates, speech-detection thresholds and interruption sensitivity are not configurable.
Tool scope
platform_toolsets in ~/.hermes/config.yaml limits the toolsets a caller can reach. The
key is plivo_voice, the plugin name without the -platform suffix.
platform_toolsets:
plivo_voice:
- plivo_send_sms
- plivo_make_call
- plivo_lookup_number
- web
- memory
Without an entry a caller reaches every toolset except the ones Hermes ships switched off
and anything under agent.disabled_toolsets. A plugin's toolsets are enabled by default, so
the Plivo tools are reachable either way. Saving a toolset list for a platform through
hermes tools reverses that for plugin toolsets, because from then on one absent from the
saved list counts as switched off. The startup log names the toolsets a caller can reach.
Exclude any tool the agent can call but cannot complete. It calls the tool regardless, and the failure and retry are dead air on the line.
Security
- Answer callbacks are signature-verified against every signature header Plivo sends
- Each call mints a short-lived token carried in the audio WebSocket URL
- Plivo applications and numbers the plugin did not create are never modified
PLIVO_VOICE_ALLOWED_USERSfilters who may call the agent, andPLIVO_VOICE_ALLOWED_DESTINATIONSfilters who the agent may call. The two lists are independent, so a number in one is not permitted by the other- An empty inbound list admits every caller, while an empty outbound list refuses every call. Outbound spends money and rings a stranger, where an unexpected inbound call only spends tokens
- The caller's number is not verified, so anyone who knows an allowed number can dial in as that number
PLIVO_VOICE_INSECURE_NO_SIGNATUREandPLIVO_VOICE_RAW_DUMPboth weaken the above
Troubleshooting
Run python -m hermes_plivo_voice.doctor first.
| Symptom | Cause |
|---|---|
Plugin 'plivo_voice' is not installed or bundled |
The enable name needs the -platform suffix |
No Plivo settings in hermes config |
Expected for a pip-installed plugin. Edit ~/.hermes/.env |
READY never appears |
DNS propagation on a fresh tunnel, up to 3 minutes. A warning instead means the hostname does not resolve locally, which does not affect Plivo |
| Agent will not call a number | The number is absent from PLIVO_VOICE_ALLOWED_DESTINATIONS, which is empty by default and is not granted by the inbound list |
Agent has no make_call |
The tools plugin is not enabled as plivo-tools |
| Outbound call refused before Plivo is contacted | The plugin's answer URL is not responding, or Plivo rejected the credentials |
| Long spoken replies | Reply length is requested in the prompt, not enforced. Interrupt by speaking |
Uninstalling
Plivo keeps sending calls to a number until it is detached. Undo the Plivo side before removing the plugin:
python -m hermes_plivo_voice.unwire
pip uninstall hermes-plivo-phone-gateway
Tests
python -m unittest discover -s tests
ruff check .
tests/ also holds scripts driving a synthetic call through a live gateway. See
tests/README.md.
Limitations
- One Plivo number answers through one application, leaving the voice and SMS plugins unable to share a number
- Reply length is requested in the per-turn prompt, not enforced
- Speech providers are global Hermes settings, and changing one affects every channel
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hermes_plivo_phone_gateway-0.2.0.tar.gz.
File metadata
- Download URL: hermes_plivo_phone_gateway-0.2.0.tar.gz
- Upload date:
- Size: 135.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c601c95572be0908c49ed7790da34c4356260d3c8ce9cd27c168cc8bd345d202
|
|
| MD5 |
c4946878121bc37930ac8811d5ae9ab9
|
|
| BLAKE2b-256 |
44a8290df068c8cd31b77d1aaac62b5f9504e61885330de0b9553d6d85031ac7
|
Provenance
The following attestation bundles were made for hermes_plivo_phone_gateway-0.2.0.tar.gz:
Publisher:
publish.yml on plivo-dev/hermes-plivo-phone-gateway
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hermes_plivo_phone_gateway-0.2.0.tar.gz -
Subject digest:
c601c95572be0908c49ed7790da34c4356260d3c8ce9cd27c168cc8bd345d202 - Sigstore transparency entry: 2747952192
- Sigstore integration time:
-
Permalink:
plivo-dev/hermes-plivo-phone-gateway@cca88f2bced7b7a679330e375a28ed04aacb4f56 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/plivo-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cca88f2bced7b7a679330e375a28ed04aacb4f56 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hermes_plivo_phone_gateway-0.2.0-py3-none-any.whl.
File metadata
- Download URL: hermes_plivo_phone_gateway-0.2.0-py3-none-any.whl
- Upload date:
- Size: 66.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
49e3cf8d31b853a325c5358cc607765c1e62b290202e747c1291abe09fd55777
|
|
| MD5 |
4ef2b981c3afedd15db4383814b7269e
|
|
| BLAKE2b-256 |
c814ee368414bf69a956740dd2e189eaa71178ebd874da23fc87a594879f7eba
|
Provenance
The following attestation bundles were made for hermes_plivo_phone_gateway-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on plivo-dev/hermes-plivo-phone-gateway
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hermes_plivo_phone_gateway-0.2.0-py3-none-any.whl -
Subject digest:
49e3cf8d31b853a325c5358cc607765c1e62b290202e747c1291abe09fd55777 - Sigstore transparency entry: 2747952215
- Sigstore integration time:
-
Permalink:
plivo-dev/hermes-plivo-phone-gateway@cca88f2bced7b7a679330e375a28ed04aacb4f56 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/plivo-dev
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cca88f2bced7b7a679330e375a28ed04aacb4f56 -
Trigger Event:
push
-
Statement type: