{"slug": "provisional-voice-api-agents-with-telnyx", "title": "Provisional Voice API Agents with Telnyx", "summary": "Telnyx launched a Provisional Agents pattern that combines a reusable AI Assistant with runtime business instructions selected by the called phone number, enabling business-specific voice agents on a single communications platform. The Node.js example maps inbound calls to business configs, renders appointment-scheduling instructions, and starts the AI Assistant with runtime greetings and instructions. This approach allows developers to attach AI voice assistants to live calls without multi-vendor handoffs.", "body_md": "| name | provisional-telnyx-voice-api-agents | ||\n|---|---|---|---|\n| title | Provisional Agents with Telnyx Voice API | ||\n| description | Start one reusable Telnyx AI Assistant on Telnyx Voice API calls with runtime business instructions selected by the called phone number. | ||\n| language | nodejs | ||\n| framework | express | ||\n| telnyx_products |\n|\n||\n| channel |\n|\n\nStart one reusable Telnyx AI Assistant on Telnyx Voice API calls with runtime business instructions selected by the called phone number.\n\nThis example shows a Provisional Agents with Telnyx Voice API pattern:\n\n```\nbase Telnyx AI Assistant + Telnyx Voice API call-time business config = business-specific voice agent\n```\n\nThe server answers inbound Telnyx Voice API calls, waits for the `call.answered`\n\nwebhook, maps the called number to a business config, renders appointment-scheduling instructions, and starts the base Telnyx AI Assistant with a runtime `greeting`\n\nand `instructions`\n\n.\n\n**Answer Call**:`POST /v2/calls/{call_control_id}/actions/answer`\n\n-[API reference](https://developers.telnyx.com/api-reference/call-commands/answer-call)**Start AI Assistant**:`POST /v2/calls/{call_control_id}/actions/ai_assistant_start`\n\n-[API reference](https://developers.telnyx.com/api-reference/call-commands/start-ai-assistant)**Create Call**:`POST /v2/calls`\n\n- optional outbound test helper\n\n```\n  caller\n    |\n    v\n  telnyx number\n    |\n    v\n  voice api webhook\n    |\n    v\n  express server\n    |\n    +--> call.initiated -> answer call\n    |\n    +--> call.answered\n           |\n           +--> called number -> examples/number-routing.json\n           +--> business config -> prompt template\n           +--> ai_assistant_start with runtime instructions and greeting\n```\n\nTelnyx is an **AI Communications Infrastructure** platform that combines Voice API call control and AI Assistants on one communications platform. That lets your webhook answer a call, select context from your own application data, and attach an AI voice assistant to the same live call without handing the call across multiple vendors.\n\nCopy `.env.example`\n\nto `.env`\n\nand fill in:\n\n| Variable | Type | Example | Required | Description | Where to get it |\n|---|---|---|---|---|---|\n`TELNYX_API_KEY` |\n`string` |\n`KEY_your_telnyx_api_key_here` |\nyes |\nTelnyx API v2 key used for Voice API commands |\n|\n\n`TELNYX_PUBLIC_KEY`\n\n`string`\n\n`base64_public_key`\n\n[Webhook signing docs](https://developers.telnyx.com/docs/api/v2/overview#webhook-signing)`BASE_ASSISTANT_ID`\n\n`string`\n\n`assistant-...`\n\n**yes for live calls**[AI Assistants](https://portal.telnyx.com/#/ai/assistants)`PORT`\n\n`number`\n\n`5000`\n\n`TELNYX_CONNECTION_ID`\n\n`string`\n\n`connection-id`\n\n`npm run call`\n\n[Portal](https://portal.telnyx.com)`TELNYX_FROM_NUMBER`\n\n`string`\n\n`+15551111111`\n\n`npm run call`\n\n[Numbers](https://portal.telnyx.com/numbers/my-numbers)`TEST_TO_NUMBER`\n\n`string`\n\n`+15552222222`\n\n`npm run call`\n\nPrerequisite: Node.js 18 or newer.\n\n```\ngit clone https://github.com/team-telnyx/telnyx-code-examples.git\ncd telnyx-code-examples/provisional-telnyx-voice-api-agents-nodejs\ncp .env.example .env\nnpm install\n```\n\nCreate a generic Telnyx AI Assistant for appointment scheduling. Keep it business-agnostic: model, voice, tools, and stable behavior belong on the base assistant. Clinic names, hours, services, and greetings come from runtime config in this example.\n\nSet the base assistant id in `.env`\n\n:\n\n```\nBASE_ASSISTANT_ID=assistant-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n```\n\nPreview the generated Telnyx Voice API `ai_assistant_start`\n\npayload without making a call:\n\n```\nnpm run preview -- smile-dental\n```\n\nTry another config:\n\n```\nnpm run preview -- northside-medical\n```\n\nStart the server:\n\n```\nnpm start\n```\n\nExpose it publicly:\n\n```\nngrok http 5000\n```\n\nConfigure your Telnyx Voice API application webhook URL:\n\n```\nhttps://<id>.ngrok.io/webhooks/voice\n```\n\nAssign your Telnyx number to that Voice API application, then map the number in `examples/number-routing.json`\n\n:\n\n```\n{\n  \"+15551111111\": \"smile-dental\"\n}\n```\n\nCall the mapped number. The expected flow is:\n\n- Telnyx sends\n`call.initiated`\n\n. - The server answers the call.\n- Telnyx sends\n`call.answered`\n\n. - The server maps the called number to a business config.\n- The server starts the base Telnyx AI Assistant with runtime instructions and greeting.\n\nTelnyx Voice API outbound testing is useful when you want to force a business config using `client_state`\n\ninstead of number routing:\n\n```\nnpm run call -- smile-dental\n```\n\nThe Telnyx Voice API outbound helper places a call and encodes:\n\n```\n{ \"business_config\": \"smile-dental\" }\n```\n\nWhen the Telnyx Voice API call is answered, the webhook reads that `client_state`\n\nfirst. If there is no usable `client_state`\n\n, it falls back to called-number routing.\n\nReceives Telnyx Voice API webhooks. Telnyx calls this endpoint directly.\n\nFor local testing without Telnyx signatures, leave `TELNYX_PUBLIC_KEY`\n\nunset. For production, set `TELNYX_PUBLIC_KEY`\n\nso the server verifies webhook signatures.\n\n```\ncurl http://localhost:5000/health\n```\n\nResponse:\n\n```\n{\n  \"status\": \"ok\",\n  \"webhook\": \"/webhooks/voice\",\n  \"configs\": [\"smile-dental\", \"northside-medical\", \"brightcare-physical-therapy\"]\n}\n```\n\n| Issue | Cause | Fix |\n|---|---|---|\nWebhook returns `401 invalid signature` |\n`TELNYX_PUBLIC_KEY` is set but the request is not signed by Telnyx |\nUse a real Telnyx webhook, or unset `TELNYX_PUBLIC_KEY` for local curl testing |\nLive call returns `BASE_ASSISTANT_ID is required` |\nNo base assistant id is configured | Create a generic AI Assistant and set `BASE_ASSISTANT_ID` |\n| No business config is selected | The called number is not in `examples/number-routing.json` |\nAdd the called number in E.164 format |\n| Call rings forever | Telnyx is not reaching your webhook or the call was not answered | Check the ngrok URL, Voice API application webhook URL, and number assignment |\n`ai_assistant_start` fails |\nThe call is not answered, assistant id is invalid, or the API key lacks permissions | Confirm `call.answered` arrived, check `BASE_ASSISTANT_ID` , and verify the API key |\n\n[build-voice-ai-agent-nodejs](https://raw.githubusercontent.com/team-telnyx/telnyx-code-examples/main/build-voice-ai-agent-nodejs/README.md)- Build a voice AI agent with Telnyx Inference and Call Control[route-phone-calls-to-ai-agent-nodejs](https://raw.githubusercontent.com/team-telnyx/telnyx-code-examples/main/route-phone-calls-to-ai-agent-nodejs/README.md)- Receive and answer inbound Voice API calls[create-ai-assistant-nodejs](https://raw.githubusercontent.com/team-telnyx/telnyx-code-examples/main/create-ai-assistant-nodejs/README.md)- Create a reusable AI Assistant", "url": "https://wpnews.pro/news/provisional-voice-api-agents-with-telnyx", "canonical_source": "https://github.com/team-telnyx/telnyx-code-examples/tree/main/provisional-telnyx-voice-api-agents-nodejs", "published_at": "2026-06-26 16:05:44+00:00", "updated_at": "2026-06-26 16:34:51.287269+00:00", "lang": "en", "topics": ["ai-agents", "ai-products", "ai-tools", "ai-infrastructure", "developer-tools"], "entities": ["Telnyx", "Telnyx Voice API", "Telnyx AI Assistant", "Express", "Node.js", "ngrok"], "alternates": {"html": "https://wpnews.pro/news/provisional-voice-api-agents-with-telnyx", "markdown": "https://wpnews.pro/news/provisional-voice-api-agents-with-telnyx.md", "text": "https://wpnews.pro/news/provisional-voice-api-agents-with-telnyx.txt", "jsonld": "https://wpnews.pro/news/provisional-voice-api-agents-with-telnyx.jsonld"}}