apus voicecall

voicecall is a plugin-provided command. It only appears when the voice-call plugin is installed and enabled. If apus voicecall is not recognized, install and enable the plugin on the Gateway host:

apus plugins install @openclaw/voice-call
apus plugins enable voice-call

The commands apply to a running Gateway automatically; start it if it is offline. See Voice call plugin for provider credentials and webhook configuration, and Apply changes and inspect for runtime verification.

When the Gateway is running, operational commands (call, start, continue, speak, dtmf, end, status) route to that Gateway's voice-call runtime. If no Gateway is reachable, they fall back to a standalone CLI runtime. status uses the persisted call store instead of starting that runtime.

Fallback is limited to transport-level absence. If the Gateway responds with a request or authentication error, or does not answer before the timeout, the command exits nonzero and points to apus gateway status; it does not start a second webhook server. If standalone fallback cannot bind the configured serve.port, the error identifies the likely running Gateway instead of printing a raw EADDRINUSE failure.

Subcommands

apus voicecall setup    [--json]
apus voicecall smoke    [-t <phone>] [--message <text>] [--mode <m>] [--yes] [--json]
apus voicecall call     -m <text> [-t <phone>] [--mode <m>] [--brief <text-or-json> | --brief-file <path>]
apus voicecall start    --to <phone> [--message <text>] [--mode <m>] [--brief <text-or-json> | --brief-file <path>]
apus voicecall continue --call-id <id> --message <text>
apus voicecall speak    --call-id <id> --message <text>
apus voicecall steer    --call-id <id> --message <text> [--mode say|guidance]
apus voicecall dtmf     --call-id <id> --digits <digits>
apus voicecall end      --call-id <id>
apus voicecall status   [--call-id <id>] [--json]
apus voicecall tail     [--file <path>] [--since <n>] [--poll <ms>]
apus voicecall latency  [--file <path>] [--last <n>]
apus voicecall expose   [--mode <m>] [--path <p>] [--port <port>] [--serve-path <p>]
Subcommand Description
setup Show provider and webhook readiness checks.
smoke Run readiness checks; place a live test call only with --yes.
call Initiate an outbound voice call.
start Alias for call with --to required and --message optional.
continue Speak a message and wait for the next response.
speak Speak a message without waiting for a response.
dtmf Send DTMF digits to an active call.
end Hang up an active call.
status Inspect active calls (or one by --call-id).
tail Tail persisted call records or an explicit custom JSONL log.
latency Summarize turn latency from call history or a custom JSONL log.
expose Toggle Tailscale serve/funnel for the webhook endpoint.

Setup and smoke

setup

Prints human-readable readiness checks by default. Pass --json for scripts.

apus voicecall setup
apus voicecall setup --json

smoke

Runs the same readiness checks. Places a real phone call only when both --to and --yes are present.

Flag Default Description
-t, --to <phone> (none) Phone number to call for a live smoke.
--message <text> Apus voice call smoke test. Message to speak during the smoke call.
--mode <mode> notify Call mode: notify or conversation.
--yes false Actually place the live outbound call.
--json false Print machine-readable JSON.
apus voicecall smoke
apus voicecall smoke --to "+15555550123"        # dry run
apus voicecall smoke --to "+15555550123" --yes  # live notify call

For external providers (plivo, telnyx, twilio), setup and smoke require a public webhook URL from publicUrl, a tunnel, or Tailscale exposure. A loopback or private serve fallback is rejected because carriers cannot reach it.

Call lifecycle

call

Initiate an outbound voice call.

Flag Required Default Description
-m, --message <text> yes (none) Message to speak when the call connects.
-t, --to <phone> no config toNumber E.164 phone number to call.
--mode <mode> no conversation Call mode: notify (hang up after message) or conversation (stay open).
apus voicecall call --to "+15555550123" --message "Hello"
apus voicecall call -m "Heads up" --mode notify

Use --brief for a task in plain text or a JSON object. --brief-file reads a JSON object from a file; the flags are mutually exclusive. The opening message is still spoken verbatim first. See Per-call briefs for the schema, permissions, and duration cap.

start

Alias for call with a different default flag shape.

Flag Required Default Description
--to <phone> yes (none) Phone number to call.
--message <text> no (none) Message to speak when the call connects.
--mode <mode> no conversation Call mode: notify or conversation.

continue

Speak a message and wait for a response.

Flag Required Description
--call-id <id> yes Call ID.
--message <text> yes Message to speak.

speak

Speak a message without waiting for a response.

Flag Required Description
--call-id <id> yes Call ID.
--message <text> yes Message to speak.

steer

Send a new owner instruction to an active realtime call:

apus voicecall steer --call-id "<call-id>" --message "Ask for Tuesday morning"
apus voicecall steer --call-id "<call-id>" --mode say --message "Tuesday morning works for us."

guidance is the default. say requests the exact words now. The instruction is also included in later agent consults. Messages are limited to 500 characters. The CLI uses the running Gateway's operator authorization; an unavailable Gateway is an error because a standalone process cannot steer its live bridge.

dtmf

Send DTMF digits to an active call.

Flag Required Description
--call-id <id> yes Call ID.
--digits <digits> yes DTMF digits (for example ww123456# for waits).

end

Hang up an active call.

Flag Required Description
--call-id <id> yes Call ID.

status

Inspect active calls.

Flag Default Description
--call-id <id> (none) Restrict output to one call.
--json false Print machine-readable JSON.
apus voicecall status
apus voicecall status --json
apus voicecall status --call-id <id>

Logs and metrics

tail

Tail persisted voice-call records from SQLite: print the last --since records initially, then only new snapshots (--since 0 starts with new snapshots only). With an existing custom --file whose basename is not calls.jsonl, prints the last --since nonempty complete lines on start, then streams new complete lines. Partial lines wait for a newline; file replacement or observed truncation starts a fresh stream. Slow output pipes pause reading instead of accumulating the rest of the log in memory.

Flag Default Description
--file <path> resolved from plugin store Path to calls.jsonl.
--since <n> 25 Lines to print before tailing.
--poll <ms> 250 (minimum 50) Poll interval in milliseconds.

latency

Summarize turn-latency and listen-wait metrics from SQLite or an existing custom log selected with --file. Output is JSON with recordsScanned, turnLatency, and listenWait summaries.

Custom logs are scanned incrementally without a byte cap on requested history. latency selects the last N nonempty records, skips malformed JSON, and accepts a final JSON record without a newline. It parses one selected record at a time; memory still scales with the largest selected JSON record and the requested number of metric samples.

Flag Default Description
--file <path> resolved from plugin store Path to calls.jsonl.
--last <n> 200 (minimum 1) Number of recent records to analyze.

Exposing webhooks

expose

Enable, disable, or change the Tailscale serve/funnel configuration for the voice webhook. When realtime or streaming audio is enabled, the command also exposes or clears that mode's WebSocket stream path. The external HTTPS port comes from tailscale.port (default 443); Funnel supports 443, 8443, or 10000.

Flag Default Description
--mode <mode> funnel off, serve (tailnet), or funnel (public).
--path <path> config tailscale.path or --serve-path Tailscale path to expose.
--port <port> config serve.port or 3334 Local webhook port.
--serve-path <path> config serve.path or /voice/webhook Local webhook path.
apus voicecall expose --mode serve
apus voicecall expose --mode funnel
apus voicecall expose --mode off

Only expose the webhook endpoint to networks you trust. Prefer Tailscale Serve over Funnel when possible.

Related