Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions audio-streaming-skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ Check the credit first. Then place the call the way the user chose in step 3. Th
- **The user calls in:** ask them to call the number, in full. For an Indian number, from an Indian phone: Indian calls stay within India.
- **Plivo calls the user:**
1. Ask in plain text: "Which phone should I call? Use a mobile in <the number's country>, for example <its format, such as +91 98XXX XXXXX for India>." Pass it to the CLI in `+<country code>...` form.
2. Preview `plivo voice calls make --from <number> --to <phone> --answer-url <answer URL> --answer-method <method> --dry-run` with the app's answer URL and method (`calls make` defaults to GET).
2. Preview `plivo voice calls make --from <number> --to <phone> --answer-url <answer URL> --answer-method <method> --dry-run` with the app's answer URL and method (without `--answer-method`, `calls make` uses GET before v1.3.1 and POST from v1.3.1).
3. Ask "Call <masked phone> now? When it rings, answer and talk for 10 seconds. You should hear yourself repeated." (header Call) · Call me / Not now. For the OpenAI or your own voice agent, the last sentence becomes "Talk to your voice agent as you would to a person." On yes, run it with `--yes`. The `request_uuid` it returns means only that Plivo accepted the request; it is also the call's UUID (seen on every test call).
4. A 403 `Calls to this destination region are barred` means the account's geo permissions block that country: Voice, Geo Permissions in the console. Professional accounts can allow only India and the US; other countries need Enterprise. Offer that, or the user calls in.
5. `calls make` sets no time limit. If the call is still up after about 2 minutes (`plivo voice calls get <request_uuid> --live -o json` returns it; before v1.2.1, `plivo api GET /Call/<request_uuid>/ --query status=live -o json`), preview `plivo voice calls hangup <request_uuid> --yes --dry-run`, ask, then run it without `--dry-run`.
Expand Down Expand Up @@ -520,7 +520,7 @@ The voice agent sends:

Stream status callbacks: the troubleshooting and best-practices pages and the console debug logs use the `Event` values `StartStream`, `StopStream`, `DroppedStream` and `DegradedStream`; the guide and the reference describe `started`, `stopped` and `failed`. Log the raw value. Common fields: `CallUUID`, `StreamID`, `Timestamp`, `From`, `To`, `Direction`. Acknowledge with a 200 (any body). Symptoms and error strings (`connection_failed`, `authentication_failed`, `invalid_content_type`, `buffer_overflow`): `plivo docs show voice-agents/audio-streaming/troubleshooting/troubleshooting` (<https://plivo.com/docs/voice-agents/audio-streaming/troubleshooting/troubleshooting>).

To start a stream over REST instead of XML: `plivo voice calls streams start <call_uuid> --url wss://... --bidirectional --content-type "audio/x-mulaw;rate=8000"`. Quote the content type (a bare `;` ends the shell command) and always pass it (the CLI default is `audio/x-l16;rate=16000`). Its `--stream-status-callback` sends `stream_status_callback_url`, a field the API does not document, so for status callbacks use `plivo api POST /Call/<call_uuid>/Stream/ --body '{"service_url":"wss://...","bidirectional":true,"content_type":"audio/x-mulaw;rate=8000","status_callback_url":"https://..."}' --dry-run`, then `--yes`.
To start a stream over REST instead of XML: `plivo voice calls streams start <call_uuid> --url wss://... --bidirectional --content-type "audio/x-mulaw;rate=8000"`. Quote the content type (a bare `;` ends the shell command) and always pass it (the CLI default is `audio/x-l16;rate=16000`). For status callbacks add `--stream-status-callback https://...`: from v1.3.1 it sends `status_callback_url`. Older versions send `stream_status_callback_url`, a field the API does not document, so there use `plivo api POST /Call/<call_uuid>/Stream/` with `status_callback_url` in the body.

Plivo moves raw audio only: STT, the model and the voice are yours, and Plivo TTS exists only as `<Speak>` before or after the stream. A streamed call is billed as the underlying call; quote no prices.

Expand Down
20 changes: 10 additions & 10 deletions cli-skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ Not on PATH: `brew install plivo/tap/plivo`, then `plivo --version`. Without Hom

- **Auth.** Browser login (`plivo login`) is the only credential source: the CLI reads no `PLIVO_AUTH_ID` or `PLIVO_AUTH_TOKEN` and has no flag for them. Do not run `plivo login` yourself; if `plivo auth whoami` exits 2, ask the human to run it in their own terminal. Never print, echo, export or store an auth token, including one the user pastes. `--profile <name>` selects another saved profile.
- **Preview, then confirm.** Run any change with `--dry-run` first: it prints the request on stderr and exits 0 without sending a write. Spend and destructive commands then need `--yes`: run that as a separate command, only once the human has approved that spend or deletion. Other writes (creates, updates, live-call verbs such as `play`, `speak` and `transfer`) have no `--yes` gate and act as soon as they run.
- Spend commands (`calls make`, `messaging * send`, `numbers buy|cnam`, `masking sessions create`, 10DLC `brands|campaigns create`, `verify sessions create`, `multiparty participant add`, mutating `plivo api` verbs) preview with `--dry-run` alone.
- Destructive commands (`numbers release`, `calls hangup`, `conferences hangup`, `calls streams stop`, `powerpacks numbers remove`, and every `delete`, `kick` and `end`) preview with `--dry-run` alone from v1.2.1. Older versions refuse that with exit 5, although the hint suggests it; preview them there with `--yes --dry-run` (`--dry-run` wins). For `sip * delete`, `--dry-run` (with `--force` for an in-use object) also names what it would detach; in v1.2.0, run it without `--yes` instead: it names them, then refuses.
- Spend commands (`calls make`, `messaging * send`, `numbers buy|cnam`, `masking sessions create`, 10DLC `brands|campaigns create` and `campaigns update` (v1.3.1+), `verify sessions create`, `multiparty participant add`, mutating `plivo api` verbs) preview with `--dry-run` alone.
- Destructive commands (`numbers release`, `calls hangup`, `conferences hangup`, `conferences stop-record` (v1.3.1+), `calls streams stop`, `powerpacks numbers remove`, and every `delete`, `kick` and `end`) preview with `--dry-run` alone from v1.2.1. Older versions refuse that with exit 5, although the hint suggests it; preview them there with `--yes --dry-run` (`--dry-run` wins). For `sip * delete`, `--dry-run` (with `--force` for an in-use object) also names what it would detach; in v1.2.0, run it without `--yes` instead: it names them, then refuses.
- `plivo lookup` is billed per lookup and has no `--yes` gate: ask first.
- `--dry-run` only holds back Plivo API writes. Commands that change local state or talk to something else ignore it and act for real: `login`, `logout`, `auth use`, `auth remove`, `config set`, `config telemetry`, `upgrade` (installs; use `upgrade --check`) and `voice streams test` (connects to the WebSocket; no call); before v1.2.0 also `feedback` (submits). `skill install --dry-run` is the exception, and from v1.2.0 so are `skill update` and `feedback`: they write and send nothing.
- **Output.** Pass `-o json`. Reads and creates print `{"data": <API response verbatim>}` on stdout; list rows are at `data.objects`, paging at `data.meta`. From v1.2.0, `-o jsonl|yaml|csv` and `--query '<JMESPath>'` (over the whole envelope, e.g. `--query 'data.objects[].number'`; implies `-o json`) reshape it; `plivo api` keeps its own `--query key=value`, which adds URL parameters. From v1.2.1 every write prints a result too: the API's response or, where the API sends none (deletes, hangups, releases, stops, kicks), the ID and what was done, e.g. `{"data": {"call_uuid": "<id>", "hung_up": true}}`. Older versions print nothing on stdout for many writes (`numbers update|release`, `calls hangup|transfer`, `account applications update`, `multiparty participant add`): check the exit code, read the result back with a `get`, and never retry a spend command because stdout was empty.
- From v1.3.1 every command honours `--dry-run`: `login`, `logout`, `auth use|remove`, `config set|telemetry`, `upgrade`, `voice streams test` and `docs` say what they would do and act on nothing (`docs` fetches nothing), and `ask -i` refuses it. Before v1.3.1 it only holds back Plivo API writes, and those commands act for real: `upgrade` installs (use `upgrade --check`), `voice streams test` connects to the WebSocket (no call), and before v1.2.0 `feedback` submits. `skill install --dry-run` writes nothing, nor, from v1.2.0, do `skill update` and `feedback`.
- **Output.** Pass `-o json`. Reads and creates print `{"data": <API response verbatim>}` on stdout; list rows are at `data.objects`, paging at `data.meta`. From v1.2.0, `-o jsonl|yaml|csv` and `--query '<JMESPath>'` (over the whole envelope, e.g. `--query 'data.objects[].number'`; implies `-o json`) reshape it; `plivo api` keeps its own `--query key=value`, which adds URL parameters. From v1.3.1 every format prints auth tokens and passwords in a response as `[REDACTED]`, except `account subaccounts create` (it hands over the new token) and `agents`; never add `--show-secrets`, which prints them. From v1.2.1 every write prints a result too: the API's response or, where the API sends none (deletes, hangups, releases, stops, kicks), the ID and what was done, e.g. `{"data": {"call_uuid": "<id>", "hung_up": true}}`. Older versions print nothing on stdout for many writes (`numbers update|release`, `calls hangup|transfer`, `account applications update`, `multiparty participant add`): check the exit code, read the result back with a `get`, and never retry a spend command because stdout was empty.
- **Lists.** A page holds at most 20 rows. From v1.2.0: `--limit` is 1-20 (more is refused); `--all` reads every page (not with `--offset`) but stops after 100 pages (2,000 rows at `--limit 20`) and sets `data.meta.truncated: true`, so check that before treating a list as complete; an unknown filter value (`--direction`, `--status`, `--type`) is refused before any request. From v1.2.1, `data.meta.next` is null once every row is read, and a page still rate limited after a minute of retries ends `--all` early: the rows read so far print with `truncated: true` and the exit code is 4. From v1.2.0, `voice calls list`, `voice recordings list` and `messaging sms|mms|whatsapp list` take `--since`/`--until` like `sip calls list` (UTC; `--from-date`/`--to-date` are the same flags; `--until` needs `--since`, and from v1.2.1 must be after it); voice call and message ranges start within the last 90 days, and voice call and recording ranges span at most 31.
- **Errors** go to stderr as `{"error": {"code", "message", "hint", "retryable", "status_code"}}` with a non-zero exit. Switch on `code` (exit codes below), never on message text.
- **No prompts.** Never run bare `plivo feedback` or `plivo ask -i`, and pass `-y` to `voice streams forward`. To report a CLI bug (v1.2.0+), `plivo feedback --bug --dry-run` prints the report (a comment plus the last failed command's path and codes, never its arguments) and sends nothing; add `--yes` only once the human has seen it. `export PLIVO_FEEDBACK_PROMPT=0 CI=1 PLIVO_NO_UPDATE_CHECK=1` silences the rating prompt and the update hint.
Expand Down Expand Up @@ -109,13 +109,13 @@ voice calls | conferences | endpoints | multiparty | recordings | streams
- Message lists have no number filter: the API ignored `--from` and `--to`, and from v1.2.1 they are refused. Narrow with `--since`, then filter: `--all --query "data.objects[?to_number=='<digits>']"`.
- Recipients: separate several with `<`, quoted (a bare `<` is a shell redirect): `--dst "+14155551111<+14155552222"`. Commas do not work. `numbers` commands take the number as digits without `+`.
- `messaging whatsapp send` sends free text, which WhatsApp allows only within 24 hours of the user's last message. To open a conversation, send a template with `plivo api POST /Message/` and a `template` body.
- `voice calls make`: omit `--machine-detection` to turn detection off; the `none` that help lists is rejected by the API.
- `voice calls streams start`: quote `--content-type "audio/x-mulaw;rate=8000"` (`;` ends a shell command). `--stream-status-callback` sends `stream_status_callback_url`, while the API documents `status_callback_url`: when the callback matters, start the stream with `plivo api POST /Call/<call_uuid>/Stream/`.
- `voice calls make`: omit `--machine-detection` to turn detection off; it takes `true` or `hangup`. The `none` that help lists before v1.3.1 is rejected by the API, and from v1.3.1 by the CLI.
- `voice calls streams start`: quote `--content-type "audio/x-mulaw;rate=8000"` (`;` ends a shell command). From v1.3.1 `--stream-status-callback` sends the documented `status_callback_url`. Older versions send `stream_status_callback_url`, which the API does not document: there, when the callback matters, start the stream with `plivo api POST /Call/<call_uuid>/Stream/`.
- `voice multiparty create` is retired and hidden: an MPC starts when its first participant is added, with `voice multiparty participant add <name> --from <number> --to <number>`.
- `voice streams forward` points the app's answer URL, and so every number on that app, at a tunnel while it runs, then restores it on exit. Use a dedicated test app. Preview with `--dry-run` (it shows the URL it would replace) and get approval. Then run it in the background with `-y -o table` and wait for its `Ready` line; in JSON mode it prints nothing, not even the tunnel URL, until it exits. Stop it with SIGINT or SIGTERM: SIGKILL skips the restore. From v1.2.1, when the tunnel process exits it restores the URL and exits 3 (`NETWORK_ERROR`); before that it does not notice, so restart it.
- `account applications update` has no `--fallback-answer-url`: set it with `plivo api POST /Application/<app_id>/`. `account applications delete` also deletes the app's endpoints, with or without `--cascade`: the API cascades by default.
- `sip`: quote `--uri "host;transport=tcp"`. Passwords go only through `--password-stdin`; to preview a password change, pass `--username` too. The API rejects `sip:` and `sips:` URIs: write `host[:port];transport=…` (from v1.3.1 the CLI rewrites them and says so). Deleting a URI deletes the trunks that use it as their primary URI; from v1.3.1 the result lists `trunks_deleted` and `trunks_kept`. Route a number to an inbound trunk with `numbers update <number> --trunk-id <trunk_id>`.
- `plivo api` reports every HTTP error as `UPSTREAM_ERROR` (exit 3) with the real status in `status_code`: switch on that. Its `--dry-run`, `--explain` and `--log-level debug` print the request body unredacted, so never send a secret through it. `/Message/` expands to `/v1/Account/<auth_id>/Message/`; a `/v1/...` path is used as-is.
- `voice streams forward` points the app's answer URL, and so every number on that app, at a tunnel while it runs, then restores it on exit. Use a dedicated test app. Preview with `--dry-run` (it shows the URL it would replace) and get approval. Then run it in the background with `-y -o table` and wait for its `Ready` line; in JSON mode it prints nothing, not even the tunnel URL, until it exits. Stop it with SIGINT or SIGTERM: SIGKILL skips the restore (from v1.3.1 the next forward on that app restores it and, on macOS and Linux, stops the tunnel left running). From v1.2.1, when the tunnel process exits it restores the URL and exits 3 (`NETWORK_ERROR`); before that it does not notice, so restart it.
- `account applications update` has no `--fallback-answer-url`: set it with `plivo api POST /Application/<app_id>/`. `account applications delete` also deletes the app's endpoints: the API cascades by default. From v1.3.1, `--cascade=false` keeps them, detached or on the app `--new-endpoint-application <app_id>` names; older versions delete them with or without `--cascade`.
- `sip`: quote `--uri "host;transport=tcp"`. Passwords go only through `--password-stdin`; to preview a password change, pass `--username` too. The API rejects `sip:` and `sips:` URIs and a user part (`user@host`): write `host[:port];transport=…` (from v1.3.1 the CLI rewrites a scheme and says so, and refuses a user part). Deleting a URI deletes the trunks that use it as their primary URI; from v1.3.1 the result lists `trunks_deleted` and `trunks_kept`. Route a number to an inbound trunk with `numbers update <number> --trunk-id <trunk_id>`.
- `plivo api` gives an HTTP error the code and exit code a typed command would (a 404 is `RESOURCE_NOT_FOUND`, exit 1) from v1.3.1; before that every one is `UPSTREAM_ERROR` (exit 3). Both put the status in `status_code` and the API's body in `context.upstream`: switch on `status_code`. End every path with a slash (`/Call/<call_uuid>/`): without one the API redirects and the request fails (from v1.3.1 the CLI follows no redirect and reports the 3xx). Its `--dry-run`, `--explain` and `--log-level debug` print the request body unredacted, so never send a secret through it. From v1.3.1 its output hides auth tokens and passwords as other commands do, except on `/AgentFlow` paths. `/Message/` expands to `/v1/Account/<auth_id>/Message/`; a `/v1/...` path is used as-is.
- `plivo ask` and the `diagnose` commands share a small per-account rate limit: on `RATE_LIMITED`, wait as long as the message says. From v1.2.0, `diagnose -o json` prints one result with fixed fields under `data` (`what_happened`, `likely_cause`, `timeline`, `next_steps`, `hangup_cause_code`, `hangup_source`, `confidence`, `answer`; from v1.3.1 `confidence` is null when the answer gave none) and `-o jsonl` the event stream that `-o json` printed before; an analysis that fails or stops early exits 3. From v1.2.1, `--timeout <seconds>` (from v1.3.1 also a duration such as `90s`) bounds their stream (exit 3, `UPSTREAM_TIMEOUT`; without it there is no limit), and an `ask` answer cut off before its end exits 3.
- `docs show` prints a JSON envelope when piped: add `-o table`, or use `jq -r .data.body`. `docs search` rows are at `data`, not `data.objects`.

Expand Down
Loading
Loading