Skip to main content
After this guide, a phone number rings your agent, the voice you chose answers with its greeting, and your code can call end users back. Calls need a voice definition in your project, a number bound to the agent (bought through Lua or delivered over your own SIP trunk), and a release that includes the voice. Browser calls are a separate setup; see Voice chat in the widget. Verified against lua-cli 3.33.0. Before you begin
  • A project created with lua init and signed in with lua auth configure, with orgId in its project config.
  • For your own trunk: a PBX or carrier that can send SIP to a domain you are given, from fixed IP ranges or with digest credentials.
1

Code: define and push a voice

Declare the voice with defineVoice, register it on LuaAgent.voices, and push it. The greeting is what callers hear first.
src/voices/support-line.voice.ts
Tools made with LuaVoiceTool can say(), transferToHuman(), endCall(), or handoff() to another voice; excludeTools hides on-screen tools, such as list and card senders, from calls.
2

Terminal: buy and bind a number

Run lua channels, choose Manage phone numbers, then Purchase a number. Answer N to Allow customers to text this number too? (otherwise voice-only) for a voice-only number with lower inbound latency, or Y for a number that also takes SMS (see SMS and phone numbers). Accept the bind prompt and pick the voice that answers.
The menu ends with 📞 Your agent (<agentId>) is now reachable at +<number> via voice "<name>". A number is bound to one agent; rebinding it elsewhere needs an unbind first. lua channels always asks which voice answers; a phone channel created over the REST API without voiceId uses the agent’s first voice.
3

Optional: Bring your own SIP trunk

Create a trunk with POST /developer/orgs/<orgId>/sip-trunks: region (us, eu, or ap; default us), an acl of CIDR ranges, enableDigestAuth, and tls and srtp modes (optional, always, or never; default optional). The response gives you the domain, the endpoint sip:*@<domain>.sip-<region>.vonage.com, the transports (UDP, TCP, and TLS, or TLS only when tls is always), and the port (5060, or 5061 with TLS only). The trunk is provisioning until it becomes active.Secure it with up to 16 ACL entries (POST …/acl with ip in CIDR notation; the last entry can’t be removed) or up to 200 digest users (POST …/credentials with a username of 5 to 32 alphanumeric characters and dashes; the password is returned once, and POST …/credentials/<username>/rotate issues another). Then route calls with POST …/sip-trunks/<trunkId>/agents/<agentId>, which makes that agent the trunk’s catch-all; a trunk routes to one agent. Bind a number on your trunk outside the CLI menu with POST /admin/agents/<agentId>/channels and { "type": "phone", "phone": { "msisdn": "<number>", "voiceId": "<voiceId>", "transport": "byo-sip" } } (scope channels:manage).
4

Terminal: call the line

Have the agent call you on the sandbox; the command exits once the call is dispatched. --caller-id presents a number your organization owns and is refused otherwise.
Then dial the bound number from your phone to hear the inbound path: the greeting, then the agent. lua voice --terminal talks through your microphone (requires sox), and lua voice test runs *.voice.test.ts files; see lua voice.
5

Verify

List recent calls. Each row is one voice session with its channel and duration.

Channel behavior

Outbound calls are rate limited per agent per minute; the API answers 429 when the quota is exceeded. Bound numbers and trunks are channel configuration and take effect immediately; the voice itself is code and goes live with your release.

Limits

Troubleshooting

The bind found no active voice on the agent. Push a voice with lua push voice and rerun lua channels; a number can’t be bound to an agent without one.
--caller-id (or callerId in Voice.call) names a number the agent’s organization doesn’t own, or one that is suspended or released. Use a number from List my numbers, or omit the flag.
The channel names a voice by id. After you delete or rename a voice, rebind the number and pick the current one. Voice code changes reach callers only after lua version promote.
Release the voice like any other primitive: lua push voice, then lua version create and lua version promote <n>; the agent version snapshot records the default voice, and lua version diff shows a voice change. See Release an agent to production.

Next steps

About voice

Voice definitions, voice sessions, and how a channel picks its voice.

defineVoice reference

Models, turn detection, hooks, and call-only tools.

Voice runtime reference

Voice.call for outbound calls from code.

Meetings

Send the same voice into a video meeting.