<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: anusha</title>
    <description>The latest articles on DEV Community by anusha (@botoclock).</description>
    <link>https://dev.to/botoclock</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4004284%2Fc7c15289-9b22-479c-b291-b944235c5687.jpg</url>
      <title>DEV Community: anusha</title>
      <link>https://dev.to/botoclock</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/botoclock"/>
    <language>en</language>
    <item>
      <title>I Built a One-Curl Audio Translator with Telnyx AI Inference</title>
      <dc:creator>anusha</dc:creator>
      <pubDate>Tue, 14 Jul 2026 22:06:14 +0000</pubDate>
      <link>https://dev.to/botoclock/i-built-a-one-curl-audio-translator-with-telnyx-ai-inference-39f9</link>
      <guid>https://dev.to/botoclock/i-built-a-one-curl-audio-translator-with-telnyx-ai-inference-39f9</guid>
      <description>&lt;p&gt;Localizing a podcast, translating a recorded meeting, or dubbing a lecture used to require three different services stitched together. The Telnyx AI Inference API exposes STT, chat completions, and TTS on the same private backbone, which means a single Flask app can run the whole pipeline.&lt;/p&gt;

&lt;p&gt;The Telnyx code example is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-content-translator-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-content-translator-python&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is a Python Flask app you can clone and run in a few minutes. No phone number, no webhook tunnel, no background job runner.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Flow
&lt;/h2&gt;

&lt;p&gt;You POST an audio file plus a target language. The app calls Telnyx STT to transcribe the audio in the source language, calls AI Inference to translate the transcript with a TTS-friendly system prompt, and calls Telnyx TTS to render the translated text into audio. Long transcripts are chunked at sentence boundaries so the TTS model never gets an input larger than it supports, and the chunks are concatenated into one mp3.&lt;/p&gt;

&lt;p&gt;The response includes the job id, both transcripts, and a URL you can curl to download the dubbed audio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Like This Example
&lt;/h2&gt;

&lt;p&gt;It is small enough to demo live, but it covers the parts that often get cut from an audio translation demo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File upload with multipart form data and a writable temp file&lt;/li&gt;
&lt;li&gt;Three Telnyx AI endpoints chained together with per-stage error handling&lt;/li&gt;
&lt;li&gt;Long-transcript chunking at sentence boundaries&lt;/li&gt;
&lt;li&gt;Response shape handling for TTS endpoints that can return raw audio, JSON with base64, or JSON with a fetch URL&lt;/li&gt;
&lt;li&gt;Temp file cleanup so the upload does not leak disk space&lt;/li&gt;
&lt;li&gt;Auto language detection (or pinned language) depending on whether you trust STT's detection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The design choice I care most about is per-stage error handling. If the TTS call fails on chunk 3 of 8, the app returns &lt;code&gt;200 partial&lt;/code&gt; with the transcripts still intact, rather than throwing away the STT and translation work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run It Locally
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/team-telnyx/telnyx-code-examples.git
&lt;span class="nb"&gt;cd &lt;/span&gt;telnyx-code-examples/ai-content-translator-python
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
python app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Translate a Spanish clip into English:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:5000/translate &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nv"&gt;audio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;@spanish-sample.mp3 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;es &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nv"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;en
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Download the dubbed audio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-OJ&lt;/span&gt; http://localhost:5000/translate/&amp;lt;job_id&amp;gt;/audio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read the full transcripts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:5000/translate/&amp;lt;job_id&amp;gt; | python3 &lt;span class="nt"&gt;-m&lt;/span&gt; json.tool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What To Demo
&lt;/h2&gt;

&lt;p&gt;I would keep the demo short:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Show the &lt;code&gt;/languages&lt;/code&gt; endpoint to call out the supported set.&lt;/li&gt;
&lt;li&gt;POST a Spanish audio file with &lt;code&gt;target=en&lt;/code&gt; and walk through the response shape (job_id, transcript previews, audio_url).&lt;/li&gt;
&lt;li&gt;Play the downloaded dubbed mp3.&lt;/li&gt;
&lt;li&gt;Show &lt;code&gt;GET /translate/&amp;lt;job_id&amp;gt;&lt;/code&gt; for the full transcripts.&lt;/li&gt;
&lt;li&gt;(Optional) POST with &lt;code&gt;source=auto&lt;/code&gt; to show language detection.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That gives viewers the full loop without getting lost in implementation details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where To Take It Next
&lt;/h2&gt;

&lt;p&gt;The demo keeps translation jobs in memory for one hour. Production would replace the in-memory &lt;code&gt;jobs&lt;/code&gt; dict with object storage (S3, GCS) for the audio blobs and a database (Postgres) for the metadata, run STT / translate / TTS in a queue, return &lt;code&gt;202 Accepted&lt;/code&gt; for long jobs, add API key auth, and cap upload size and audio length up front.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Code example: &lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-content-translator-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-content-translator-python&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx AI Inference docs: &lt;a href="https://developers.telnyx.com/docs/inference" rel="noopener noreferrer"&gt;https://developers.telnyx.com/docs/inference&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx Developer Docs: &lt;a href="https://developers.telnyx.com" rel="noopener noreferrer"&gt;https://developers.telnyx.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx Portal: &lt;a href="https://portal.telnyx.com" rel="noopener noreferrer"&gt;https://portal.telnyx.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>telnyx</category>
      <category>ai</category>
      <category>devrel</category>
    </item>
    <item>
      <title>I Built an AI Subscription Cancel-Save Agent That Does Not Manipulate You</title>
      <dc:creator>anusha</dc:creator>
      <pubDate>Tue, 14 Jul 2026 22:03:54 +0000</pubDate>
      <link>https://dev.to/botoclock/i-built-an-ai-subscription-cancel-save-agent-that-does-not-manipulate-you-3gbd</link>
      <guid>https://dev.to/botoclock/i-built-an-ai-subscription-cancel-save-agent-that-does-not-manipulate-you-3gbd</guid>
      <description>&lt;p&gt;Cancel-save flows are easy to over-engineer into manipulative dark patterns, and easy to under-engineer into "your subscription has been cancelled, goodbye" experiences that lose revenue. A good cancel-save agent does three things: classifies the reason, offers one relevant save option, and respects a direct cancellation request.&lt;/p&gt;

&lt;p&gt;The Telnyx code example is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-subscription-cancel-save-retention-agent-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-subscription-cancel-save-retention-agent-python&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is a Python Flask app that combines Telnyx Voice, AI Inference, and Messaging into a small demo you can clone and run in a few minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Flow
&lt;/h2&gt;

&lt;p&gt;A customer calls in saying they want to cancel. The Flask app receives the webhook, verifies the customer by caller ID, and asks why they want to cancel. AI Inference returns the reason (&lt;code&gt;too_expensive&lt;/code&gt;, &lt;code&gt;not_using&lt;/code&gt;, &lt;code&gt;missing_feature&lt;/code&gt;, &lt;code&gt;support_issue&lt;/code&gt;, &lt;code&gt;competitor_switch&lt;/code&gt;, &lt;code&gt;temporary_pause&lt;/code&gt;, &lt;code&gt;other&lt;/code&gt;) and the sentiment. Hardcoded urgent phrases (&lt;code&gt;lawyer&lt;/code&gt;, &lt;code&gt;sue&lt;/code&gt;, &lt;code&gt;fraud&lt;/code&gt;, &lt;code&gt;chargeback&lt;/code&gt;) and direct cancel phrases (&lt;code&gt;cancel now&lt;/code&gt;, &lt;code&gt;please cancel my subscription&lt;/code&gt;) short-circuit before any offer.&lt;/p&gt;

&lt;p&gt;Otherwise, the agent offers one save option from the OFFER_POLICY mapping. A "yes" applies the save or pauses the subscription. A "no" or "cancel" ends the call with a graceful cancellation. An ambiguous yes/no gets exactly one clarifying prompt — the agent never loops.&lt;/p&gt;

&lt;p&gt;The case is recorded with the outcome (&lt;code&gt;saved&lt;/code&gt;, &lt;code&gt;cancelled&lt;/code&gt;, &lt;code&gt;paused&lt;/code&gt;, &lt;code&gt;transferred&lt;/code&gt;, &lt;code&gt;needs_followup&lt;/code&gt;), and the customer record is updated. Hangups before resolution are recorded as &lt;code&gt;needs_followup&lt;/code&gt; so reps can call back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Like This Example
&lt;/h2&gt;

&lt;p&gt;It is small enough to demo live, but it covers the parts that often get cut from a "Hello World" voice AI demo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single-prompt AI Inference classification that returns structured JSON&lt;/li&gt;
&lt;li&gt;An offer policy that maps reason to one offer and one default outcome&lt;/li&gt;
&lt;li&gt;Hardcoded overrides for urgent phrases and direct cancel so the agent does not rely on the LLM to get safety right&lt;/li&gt;
&lt;li&gt;One clarifying prompt on ambiguous yes/no so the conversation does not loop&lt;/li&gt;
&lt;li&gt;Idempotent webhook handling so retries do not double-log cases&lt;/li&gt;
&lt;li&gt;Hangup tracking so open cases never disappear&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The design choice I care most about is non-manipulation. The agent does not push back on a direct cancellation, and it offers one save option — not five — when the customer is open to one. That maps to how good customer-success teams actually operate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run It Locally
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/team-telnyx/telnyx-code-examples.git
&lt;span class="nb"&gt;cd &lt;/span&gt;telnyx-code-examples/ai-subscription-cancel-save-retention-agent-python
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
python app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expose the webhook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ngrok http 5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the Telnyx Portal, set the Voice API app webhook URL to &lt;code&gt;https://&amp;lt;ngrok-id&amp;gt;.ngrok-free.app/webhooks/voice&lt;/code&gt;. Seed a customer with &lt;code&gt;POST /customers&lt;/code&gt;, then call the Telnyx number from the customer's phone.&lt;/p&gt;

&lt;h2&gt;
  
  
  What To Demo
&lt;/h2&gt;

&lt;p&gt;I would keep the demo short and show three flows back-to-back:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Customer says "I want to cancel, it's too expensive" then accepts the 25% off offer. Case ends &lt;code&gt;saved&lt;/code&gt;, customer status &lt;code&gt;active&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Customer says "I want to cancel, it's too expensive" then declines. Case ends &lt;code&gt;cancelled&lt;/code&gt;, customer status &lt;code&gt;cancelled&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Customer says "I want a lawyer this is fraud." Case ends &lt;code&gt;transferred&lt;/code&gt;, call moves to the human escalation number.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That gives viewers the full loop without getting lost in implementation details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where To Take It Next
&lt;/h2&gt;

&lt;p&gt;The demo uses in-memory state, which is fine for learning. Production would wire the customer and case stores into your billing system (Stripe, Recurly, Chargebee) so a &lt;code&gt;saved&lt;/code&gt; outcome actually applies the discount and a &lt;code&gt;paused&lt;/code&gt; outcome defers the next invoice. Add consent recording (&lt;code&gt;record_channels: "dual"&lt;/code&gt;) for compliance audits, and replace the caller-ID match with a one-time code flow for real verification.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Code example: &lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-subscription-cancel-save-retention-agent-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-subscription-cancel-save-retention-agent-python&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx Voice docs: &lt;a href="https://developers.telnyx.com/docs/voice/call-control" rel="noopener noreferrer"&gt;https://developers.telnyx.com/docs/voice/call-control&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx AI Inference docs: &lt;a href="https://developers.telnyx.com/docs/inference" rel="noopener noreferrer"&gt;https://developers.telnyx.com/docs/inference&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx Messaging docs: &lt;a href="https://developers.telnyx.com/docs/messaging" rel="noopener noreferrer"&gt;https://developers.telnyx.com/docs/messaging&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx Portal: &lt;a href="https://portal.telnyx.com" rel="noopener noreferrer"&gt;https://portal.telnyx.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>telnyx</category>
      <category>ai</category>
      <category>devrel</category>
    </item>
    <item>
      <title>I Built a Hotel Concierge Line with Telnyx Voice, SMS, and Slack</title>
      <dc:creator>anusha</dc:creator>
      <pubDate>Tue, 14 Jul 2026 21:45:33 +0000</pubDate>
      <link>https://dev.to/botoclock/i-built-a-hotel-concierge-line-with-telnyx-voice-sms-and-slack-50g4</link>
      <guid>https://dev.to/botoclock/i-built-a-hotel-concierge-line-with-telnyx-voice-sms-and-slack-50g4</guid>
      <description>&lt;p&gt;Hotel guests do not care whether the front desk is staffed. They want to text or call one number and have their room service, housekeeping, concierge, or maintenance request handled. A concierge line is a good test case for voice AI because the workflow is familiar and the volume is real.&lt;/p&gt;

&lt;p&gt;The Telnyx code example is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/hotel-guest-services-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/hotel-guest-services-python&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is a Python Flask app that combines Telnyx Voice, AI Inference, Messaging, and Slack into a small demo you can clone and run in a few minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Flow
&lt;/h2&gt;

&lt;p&gt;A guest calls or texts the Telnyx number. The Flask app receives the webhook, looks up the room by caller ID, and either greets the guest by name or asks for the room number. Each request is sent to Telnyx AI Inference, which classifies it into &lt;code&gt;room_service&lt;/code&gt;, &lt;code&gt;housekeeping&lt;/code&gt;, &lt;code&gt;concierge&lt;/code&gt;, or &lt;code&gt;maintenance&lt;/code&gt;. Urgent phrases (&lt;code&gt;fire&lt;/code&gt;, &lt;code&gt;flood&lt;/code&gt;, &lt;code&gt;leak&lt;/code&gt;, &lt;code&gt;locked out&lt;/code&gt;, &lt;code&gt;gas&lt;/code&gt;, &lt;code&gt;medical&lt;/code&gt;) override the LLM and route the request as &lt;code&gt;urgent&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The request is appended to a log, the guest gets an SMS confirmation, and staff get a Slack alert with the right emoji for the department. When staff mark the request complete, the guest gets another SMS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Like This Example
&lt;/h2&gt;

&lt;p&gt;It is small enough to demo live, but it covers the parts that often get cut from a "Hello World" voice AI demo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Caller-ID-based room lookup, with a regex-based fallback for unknown callers&lt;/li&gt;
&lt;li&gt;A constrained JSON system prompt so the LLM returns structured output you can trust&lt;/li&gt;
&lt;li&gt;An urgent-phrase override that does not depend on the LLM getting it right&lt;/li&gt;
&lt;li&gt;Slack alerts that match the department&lt;/li&gt;
&lt;li&gt;Idempotent webhook handling so retries do not double-log requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That makes it useful as a starting template for any single-vertical phone service where one phone number handles a small set of structured requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run It Locally
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/team-telnyx/telnyx-code-examples.git
&lt;span class="nb"&gt;cd &lt;/span&gt;telnyx-code-examples/hotel-guest-services-python
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
python app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expose the webhook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ngrok http 5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the Telnyx Portal, set the Voice API app webhook URL to &lt;code&gt;https://&amp;lt;ngrok-id&amp;gt;.ngrok-free.app/webhooks/voice&lt;/code&gt; and the Messaging Profile inbound webhook URL to &lt;code&gt;https://&amp;lt;ngrok-id&amp;gt;.ngrok-free.app/webhooks/sms&lt;/code&gt;. Call or text the Telnyx number to test.&lt;/p&gt;

&lt;h2&gt;
  
  
  What To Demo
&lt;/h2&gt;

&lt;p&gt;I would keep the demo short:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Call from a phone matching room 205. Say "Can I order a club sandwich and a sparkling water please?"&lt;/li&gt;
&lt;li&gt;Show the open request in &lt;code&gt;curl http://localhost:5000/requests&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Show the Slack alert in the staff channel.&lt;/li&gt;
&lt;li&gt;Mark it complete with &lt;code&gt;curl -X POST http://localhost:5000/requests/0/complete&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Show the fulfilment SMS on the guest phone.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then call from an unknown number, say "Room 205 please", and make a second request to show the unknown-caller path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where To Take It Next
&lt;/h2&gt;

&lt;p&gt;The demo uses in-memory state, which is fine for learning. Production would replace &lt;code&gt;ROOMS&lt;/code&gt; and &lt;code&gt;service_requests&lt;/code&gt; with your PMS database (Opera, Mews, Cloudbeds), persist call state and event IDs to Redis, queue Slack and SMS side effects, add call recording for QA, and map urgent requests to a real paging system instead of Slack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Code example: &lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/hotel-guest-services-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/hotel-guest-services-python&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx Voice docs: &lt;a href="https://developers.telnyx.com/docs/voice/call-control" rel="noopener noreferrer"&gt;https://developers.telnyx.com/docs/voice/call-control&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx AI Inference docs: &lt;a href="https://developers.telnyx.com/docs/inference" rel="noopener noreferrer"&gt;https://developers.telnyx.com/docs/inference&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx Messaging docs: &lt;a href="https://developers.telnyx.com/docs/messaging" rel="noopener noreferrer"&gt;https://developers.telnyx.com/docs/messaging&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx Portal: &lt;a href="https://portal.telnyx.com" rel="noopener noreferrer"&gt;https://portal.telnyx.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>telnyx</category>
      <category>ai</category>
      <category>devrel</category>
    </item>
    <item>
      <title>I Built an AI That Calls Candidates and Scores Them So Recruiters Don't Have To</title>
      <dc:creator>anusha</dc:creator>
      <pubDate>Fri, 10 Jul 2026 20:44:38 +0000</pubDate>
      <link>https://dev.to/botoclock/i-built-an-ai-that-calls-candidates-and-scores-them-so-recruiters-dont-have-to-3863</link>
      <guid>https://dev.to/botoclock/i-built-an-ai-that-calls-candidates-and-scores-them-so-recruiters-dont-have-to-3863</guid>
      <description>&lt;p&gt;The first-round phone screen is the most boring part of hiring.&lt;/p&gt;

&lt;p&gt;A recruiter calls a candidate. Asks the same five questions. Takes notes. Decides whether to advance them. Does it again. And again. 200 times for one role.&lt;/p&gt;

&lt;p&gt;That's a full week of screening calls before a single second-round interview.&lt;/p&gt;

&lt;p&gt;So I built an AI that does that first call instead.&lt;/p&gt;

&lt;p&gt;The AI calls the candidate. Conducts a 5-question screen. Hangs up. Produces a scorecard with scores, a recommendation, strengths, concerns, and a summary.&lt;/p&gt;

&lt;p&gt;The candidate experience is just a phone call. They answer, talk to a friendly AI interviewer for two minutes, and hang up. No app, no form, no scheduling.&lt;/p&gt;

&lt;p&gt;The recruiter's experience is a dashboard. They enter the candidate's name and phone number, click one button, and wait. A scorecard appears within 5 seconds of the call ending.&lt;/p&gt;

&lt;p&gt;The code is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-hiring-phone-screen-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-hiring-phone-screen-python&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem With First-Round Screens
&lt;/h2&gt;

&lt;p&gt;First-round screens are not hard. They are repetitive.&lt;/p&gt;

&lt;p&gt;The same five questions. The same evaluation criteria. The same note-taking format. The same pass/hold/advance decision.&lt;/p&gt;

&lt;p&gt;A recruiter doing first-round screens at 20 minutes each, for 200 applicants, spends 66 hours on calls before anyone advances. That's a week of work that produces the same structured output every time: name, background, skills, timeline, recommendation.&lt;/p&gt;

&lt;p&gt;The first-round screen is also the part of hiring where the human adds the least value. The recruiter isn't evaluating technical depth. They're filtering for communication, basic fit, and interest. That's exactly the kind of structured conversation an AI can run consistently.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;The architecture has three pieces, and none of them are complicated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One: trigger the call.&lt;/strong&gt; The dashboard sends one API call to Telnyx scheduled events. The AI Assistant calls the candidate from a configured phone number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two: the call.&lt;/strong&gt; Telnyx hosts the entire conversation. The AI Assistant (Voice Ultra Katie, powered by gpt-4o) greets the candidate, asks the five questions one at a time, listens, responds, and ends the call. No webhooks. No ngrok. No local call handling. Telnyx does the speech-to-text, the inference, and the text-to-speech in one managed product.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three: the scorecard.&lt;/strong&gt; The dashboard polls the Telnyx conversations API every few seconds. When it detects a finished screen conversation, it runs a second inference pass on the transcript to extract a structured scorecard: overall score, communication, technical depth, culture fit, recommendation (advance/hold/pass), key strengths, concerns, and a summary.&lt;/p&gt;

&lt;p&gt;The scorecard appears in the dashboard within 5 seconds of the candidate hanging up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why AI Assistant Instead of Call Control
&lt;/h2&gt;

&lt;p&gt;The original example in the Telnyx repo uses Call Control webhooks. That means you build the state machine yourself: answer the call, speak a greeting, gather speech, call inference, speak the response, gather again, repeat until done, hang up. You also need ngrok to expose your local server for webhooks.&lt;/p&gt;

&lt;p&gt;I rebuilt it with the AI Assistant product instead. Telnyx hosts the entire call loop. You trigger the call, poll for the transcript, and process the result. Three API calls instead of a webhook state machine.&lt;/p&gt;

&lt;p&gt;That tradeoff makes sense for this use case. The screening conversation is structured and predictable. You don't need fine-grained control over the call flow. You need the AI to ask five questions, listen, and hang up. That's what AI Assistants are built for.&lt;/p&gt;

&lt;p&gt;If you needed custom call flow logic — DTMF menus, transfers, hold detection — you'd use Call Control. For a structured conversation with a known beginning and end, AI Assistants are simpler.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Scorecard
&lt;/h2&gt;

&lt;p&gt;The scorecard is the output. It's what the recruiter reads instead of taking the call themselves.&lt;/p&gt;

&lt;p&gt;Each scorecard has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Overall score&lt;/strong&gt; (1-10)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Communication, technical depth, culture fit&lt;/strong&gt; (each 1-10)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recommendation&lt;/strong&gt; — advance, hold, or pass&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key strengths&lt;/strong&gt; — green chips ("strong communicator," "led multi-month infrastructure project")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concerns&lt;/strong&gt; — red chips ("salary range above band")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Summary&lt;/strong&gt; — one paragraph the AI writes from the transcript&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The scoring is a single inference call. The transcript goes in, the JSON comes out. Is it a validated rubric? No. It's an LLM's assessment of a conversation. But it's consistent — every candidate gets scored the same way, on the same criteria, from the same transcript.&lt;/p&gt;

&lt;p&gt;For a real hiring pipeline, you'd want to calibrate the scoring prompt against historical data. For a demo, it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where This Actually Works
&lt;/h2&gt;

&lt;p&gt;This pattern works for high-volume, surface-level screening. Hourly roles, retail, seasonal hiring, call centers. Any role where the first-round screen is a filter, not a deep assessment.&lt;/p&gt;

&lt;p&gt;It does not work for senior roles. The five questions are intentionally surface-level. They filter for communication and basic fit, not for engineering ability. A staff engineer would ace them in 30 seconds and you'd learn nothing.&lt;/p&gt;

&lt;p&gt;It also doesn't replace human judgment. The recruiter reads the scorecard and decides whether to agree with the recommendation. The AI does the call. The human makes the decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/team-telnyx/telnyx-code-examples.git
&lt;span class="nb"&gt;cd &lt;/span&gt;telnyx-code-examples/ai-hiring-phone-screen-python
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
python app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need a Telnyx account, a phone number, and an API key. The example includes a bootstrap script that provisions everything automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bigger Pattern
&lt;/h2&gt;

&lt;p&gt;The interesting thing about this build isn't the hiring use case. It's the shape of the workflow.&lt;/p&gt;

&lt;p&gt;An outbound call. A structured conversation. A structured output.&lt;/p&gt;

&lt;p&gt;Replace "hiring screen" with "patient intake," "lead qualification," "customer feedback survey," "policy renewal check," or "appointment confirmation." The architecture is the same. The phone is the highest-conversion channel we already have — people answer calls. AI makes it scalable.&lt;/p&gt;

&lt;p&gt;The first-round screen is just the most obvious place to start.&lt;/p&gt;

</description>
      <category>telnyx</category>
      <category>ai</category>
      <category>devrel</category>
    </item>
    <item>
      <title>How I Built an AI Voicemail System in 118 Lines (And What Surprised Me)</title>
      <dc:creator>anusha</dc:creator>
      <pubDate>Fri, 10 Jul 2026 17:15:29 +0000</pubDate>
      <link>https://dev.to/botoclock/how-i-built-an-ai-voicemail-system-in-118-lines-and-what-surprised-me-383i</link>
      <guid>https://dev.to/botoclock/how-i-built-an-ai-voicemail-system-in-118-lines-and-what-surprised-me-383i</guid>
      <description>&lt;p&gt;Last weekend I got mad at voicemail. Not at any individual voicemail — at the entire concept. Someone calls, leaves a 30-second message, and then I have to remember to check it. By the time I do, the urgent ones are old news and the spam ones have wasted my attention. So I built an AI that listens for me.&lt;/p&gt;

&lt;p&gt;This post is about the build — what I chose, what I got wrong, and the two specific decisions that turned a flaky demo into something I'm actually comfortable shipping.&lt;/p&gt;

&lt;p&gt;The canonical code example is in the Telnyx code examples repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-voicemail-transcription-forwarding-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-voicemail-transcription-forwarding-python&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Picking the example
&lt;/h2&gt;

&lt;p&gt;Telnyx has a public repo of around 480 code examples. The vast majority are too complex for a six-minute demo. I needed something that was small enough to teach the pattern, real enough to be useful, and visual enough to work on camera.&lt;/p&gt;

&lt;p&gt;I picked &lt;code&gt;ai-voicemail-transcription-forwarding-python&lt;/code&gt; because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;It uses a recognizable, painful workflow.&lt;/strong&gt; Everyone hates voicemail. No one has to be sold on why this matters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's small.&lt;/strong&gt; Around 280 lines of real code after fixes. That's two screens of scrolling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It has a clear "wow" moment.&lt;/strong&gt; A phone call becomes an SMS with a priority emoji. That's the kind of thing you can show in five seconds and people get it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It hits three Telnyx products in one app&lt;/strong&gt; — voice, SMS, and AI Inference.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The first surprise: it didn't actually work
&lt;/h2&gt;

&lt;p&gt;I cloned the example, filled in my API key, and the AI part worked great. Then I tested the SMS delivery. It failed. Every time.&lt;/p&gt;

&lt;p&gt;The bug: the &lt;code&gt;send_sms&lt;/code&gt; function was passing the &lt;strong&gt;caller's&lt;/strong&gt; phone number as the &lt;code&gt;from&lt;/code&gt; field. The owner's number was set as &lt;code&gt;to&lt;/code&gt;. So the API was saying "send an SMS from this random number I don't own, to this number." Telnyx (correctly) rejects that.&lt;/p&gt;

&lt;p&gt;This was in the upstream &lt;code&gt;team-telnyx/telnyx-code-examples&lt;/code&gt; repo. It's listed as "production-ready." It is not production-ready. It would never have sent a single SMS in production.&lt;/p&gt;

&lt;p&gt;I dug through the rest of the code and found twelve issues total. The takeaway was the same: &lt;strong&gt;read example code skeptically, even from authoritative sources.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The SDK method names were wrong
&lt;/h2&gt;

&lt;p&gt;This one took me a while. The upstream example used &lt;code&gt;client.calls.actions.record_start()&lt;/code&gt; and &lt;code&gt;client.calls.actions.transcription_start()&lt;/code&gt;. Neither of those methods exist in the current Telnyx SDK. The actual names are &lt;code&gt;start_recording()&lt;/code&gt; and &lt;code&gt;start_transcription()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Even worse: &lt;code&gt;start_recording()&lt;/code&gt; has a built-in &lt;code&gt;transcription&lt;/code&gt; parameter. You can do recording + transcription in one call instead of two. The upstream example was doing it the hard way AND using wrong method names.&lt;/p&gt;

&lt;p&gt;Then there was the &lt;code&gt;language_code&lt;/code&gt; parameter on the &lt;code&gt;speak()&lt;/code&gt; call. The SDK uses &lt;code&gt;language&lt;/code&gt;, not &lt;code&gt;language_code&lt;/code&gt;. The speak returned 200 but then a &lt;code&gt;call.speak.failed&lt;/code&gt; webhook arrived with a 400 "not well-formed" error. The greeting never played.&lt;/p&gt;

&lt;h2&gt;
  
  
  The transcription arrives after hangup
&lt;/h2&gt;

&lt;p&gt;This was the sneakiest bug. I assumed the transcription would stream in chunks via &lt;code&gt;call.transcription&lt;/code&gt; webhooks while the caller was speaking. That's how the upstream example was written.&lt;/p&gt;

&lt;p&gt;In reality, the transcription arrives as a single &lt;code&gt;call.recording.transcription.saved&lt;/code&gt; webhook AFTER the caller hangs up, with the full text in a &lt;code&gt;transcription_text&lt;/code&gt; field. Different event name, different payload structure, different timing.&lt;/p&gt;

&lt;p&gt;The fix: the app now waits for the transcription on hangup instead of processing immediately. If the transcript arrives after the session is popped, it recreates the session and processes it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real production gotcha: Kimi reasoning eats your token budget
&lt;/h2&gt;

&lt;p&gt;The first version used &lt;code&gt;max_tokens=300&lt;/code&gt; for the LLM call. It worked in my unit tests. It failed in production. The AI Inference call returned, but the JSON got truncated mid-word, like &lt;code&gt;{"priority":"urgent","summary":"Sarah reports&lt;/code&gt;. Why?&lt;/p&gt;

&lt;p&gt;Because the model — &lt;code&gt;moonshotai/Kimi-K2.6&lt;/code&gt; — has reasoning tokens. When you ask it to think step-by-step, the reasoning comes out of the same token budget as the answer. With &lt;code&gt;max_tokens=300&lt;/code&gt;, my answer was getting cut off after the first ~50 tokens of actual JSON because Kimi had burned 250 tokens reasoning about whether it should return JSON.&lt;/p&gt;

&lt;p&gt;The fix was bumping &lt;code&gt;max_tokens&lt;/code&gt; to 1500. &lt;strong&gt;Rule of thumb: when using reasoning models, budget 5-10x more tokens than the visible output needs.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The voice quality problem
&lt;/h2&gt;

&lt;p&gt;The upstream example used &lt;code&gt;voice="female"&lt;/code&gt; which is the basic TTS tier. It sounded robotic. I upgraded to &lt;code&gt;AWS.Polly.Joanna-Neural&lt;/code&gt; with &lt;code&gt;service_level="premium"&lt;/code&gt; — a natural, human-like voice. One parameter change, dramatic quality difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do differently
&lt;/h2&gt;

&lt;p&gt;A few things I'd change if I was starting over:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Skip Flask, use a single-file approach with stdlib.&lt;/strong&gt; The app is small enough that Flask is overkill.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use a real prompt framework.&lt;/strong&gt; I hardcoded the prompt as a string. For a real product I'd want a prompt file with version control, A/B testing, eval set.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a recording-storage step.&lt;/strong&gt; The carrier records the voicemail to an MP3. I don't subscribe to the &lt;code&gt;call.recording.saved&lt;/code&gt; webhook, so the audio is just sitting in Telnyx's storage with no way to retrieve it from my app.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The thing I'm still figuring out
&lt;/h2&gt;

&lt;p&gt;The hardest part wasn't the code. It was figuring out what the AI should actually decide. "Urgent vs normal vs spam" feels obvious, but the edge cases are where the value is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A voicemail from your spouse saying "don't forget to pick up milk" — normal or spam?&lt;/li&gt;
&lt;li&gt;A sales call that says "I just wanted to introduce myself" — spam or normal?&lt;/li&gt;
&lt;li&gt;A "happy birthday" message with no other content — what category?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I haven't solved this. The next iteration would be a small eval set — twenty voicemails with my labels — and a prompt I tune against it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;This is the first of three apps I'm building for a YouTube series. The next one is an AI language tutor — call a phone number, practice a foreign language with an AI that adapts to your level. Same skeleton. By the third video, the audience will have seen the pattern three times and should be able to build anything on top of it.&lt;/p&gt;

&lt;p&gt;If you want to build the voicemail yourself, the &lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-voicemail-transcription-forwarding-python" rel="noopener noreferrer"&gt;repo&lt;/a&gt; has the full code. The state machine itself fits in one screen — the rest is error handling, logging, and JSON parsing defenses. Should take you 30 minutes including the inevitable debugging.&lt;/p&gt;

</description>
      <category>telnyx</category>
      <category>ai</category>
      <category>devrel</category>
    </item>
    <item>
      <title>I Built an RSVP Phone Line Because Nobody Fills Out Forms</title>
      <dc:creator>anusha</dc:creator>
      <pubDate>Fri, 10 Jul 2026 16:31:29 +0000</pubDate>
      <link>https://dev.to/botoclock/i-built-an-rsvp-phone-line-because-nobody-fills-out-forms-4c3i</link>
      <guid>https://dev.to/botoclock/i-built-an-rsvp-phone-line-because-nobody-fills-out-forms-4c3i</guid>
      <description>&lt;p&gt;Every event I have organized has the same problem. I send the invites. People say they will RSVP later. They don't. Three days before the event, I still don't know if I'm feeding 12 people or 40.&lt;/p&gt;

&lt;p&gt;I built a form. It got a 30% response rate. I sent a Slack reminder. It got 50%. I called people on the phone. It got 90%+.&lt;/p&gt;

&lt;p&gt;So I stopped building forms and built a phone number instead.&lt;/p&gt;

&lt;p&gt;The code is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-event-rsvp-phone-line-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-event-rsvp-phone-line-python&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea
&lt;/h2&gt;

&lt;p&gt;An RSVP line is just a phone number. You dial it. An AI agent picks up, asks for your name, your party size, your dietary restrictions, and any accessibility needs. It confirms everything back to you. You hang up. Within 30 seconds, your RSVP shows up in a dashboard as a row of structured JSON.&lt;/p&gt;

&lt;p&gt;No form. No app to download. No link to click. Just a phone number.&lt;/p&gt;

&lt;p&gt;The phone wins for RSVPs because it puts the friction on the wrong side. A web form asks the guest to find the link, open a browser, type their name, select a dropdown, click submit, and hope it worked. Every step is a chance to abandon. A phone call asks the guest to do one thing: answer the phone. They already know how to do that.&lt;/p&gt;

&lt;p&gt;The conversion difference is not marginal. It is the difference between chasing 80% of your guest list and chasing 0% of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;Two Telnyx products do the work.&lt;/p&gt;

&lt;p&gt;The first is the Telnyx AI Assistant. It is a managed AI assistant with a system prompt, a greeting, a voice, and telephony settings. Telnyx hosts the entire call — speech-to-text, LLM reasoning, text-to-speech. No webhook loop, no ngrok tunnel, no signature verification. The assistant just talks to the caller.&lt;/p&gt;

&lt;p&gt;The second is the Telnyx Conversations API. After the call ends, the conversation transcript is available via this API. A small Flask dashboard polls it every 5 seconds, finds new conversations from the RSVP assistant, and runs a second inference call to extract a structured RSVP — name, guests, dietary, accessibility, confirmed — from the transcript.&lt;/p&gt;

&lt;p&gt;The flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;caller dials the RSVP number
        |
        v
Telnyx AI Assistant picks up (Voice Ultra Katie, gpt-4o)
        |
        v
conversation: STT -&amp;gt; LLM -&amp;gt; TTS, looped
        |
        v
caller hangs up -&amp;gt; conversation stored on Telnyx
        |
        v
dashboard polls Conversations API every 5s
        |
        v
second inference call extracts structured RSVP JSON
        |
        v
RSVP appears in the dashboard table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key design choice is that the dashboard does not participate in the call. Telnyx owns the call lifecycle. The dashboard is a read-only polling client that pulls transcripts and extracts structured data. The RSVP line works even if the dashboard is not running. The dashboard just shows what already happened.&lt;/p&gt;

&lt;p&gt;That separation is what makes this reliable enough to demo live. No tunnel to break. No webhook signature to verify. No Flask loop to debug. Telnyx hosts everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Prompt That Does the Work
&lt;/h2&gt;

&lt;p&gt;The assistant's system prompt is deliberately simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;you are the rsvp line for the gala on saturday july 26th at 7:00 pm
at the grand ballroom 123 market st san francisco.
dress code is black tie.

collect these details one at a time in order:
1) the caller's full name
2) number of guests including the caller
3) dietary restrictions (vegetarian vegan gluten-free allergies or none)
4) any accessibility needs

be warm friendly and excited.
keep each reply to one or two sentences.
confirm all details with the caller before ending.

when all details are collected and the caller confirms,
say a warm goodbye and wish them a great evening.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lowercase. No exclamation marks. This is a Telnyx AI Assistant convention — lowercase prompts process more reliably and exclamation marks cause TTS to over-emphasize.&lt;/p&gt;

&lt;p&gt;The prompt enforces order. Name first, then party size, then dietary, then accessibility. This makes the conversation predictable and the extraction reliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Extraction Step
&lt;/h2&gt;

&lt;p&gt;After the call ends, the dashboard runs a second inference call to turn the transcript into JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Extract a structured RSVP from the call transcript below.
Return ONLY valid JSON with these exact fields:
- name (string or null)
- guests (integer or null)
- dietary (list of strings, empty list if none)
- accessibility (string or null)
- confirmed (boolean — true only if the caller explicitly confirmed the details)

Do not include any explanation or markdown. JSON only.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the key to the whole workflow. The conversation is free-form natural language. The extraction is rigid structured data. The two are separated by design. The conversation does not need to produce JSON. The extraction does not need to hold a conversation.&lt;/p&gt;

&lt;p&gt;This separation makes the system robust to prompt drift. If the assistant rephrases a question, the extraction still works because it is looking at the full transcript, not a single response.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Race Condition I Had to Fix
&lt;/h2&gt;

&lt;p&gt;The first version of the dashboard had a bug. The polling loop fetched conversations, then fetched their messages. If the messages endpoint returned an error (because the conversation was still in progress, or the messages were not fully populated yet), the code added the conversation ID to a "seen" set and never retried it.&lt;/p&gt;

&lt;p&gt;That meant a call that was in progress when the poller ran would never be picked up, even after it ended. The conversation was permanently blacklisted by a transient failure.&lt;/p&gt;

&lt;p&gt;The fix was to only blacklist a conversation after confirming it does not belong to the assistant, or after the call has ended with too-short content. Transient failures and in-progress calls are retried on the next poll cycle.&lt;/p&gt;

&lt;p&gt;There was also a timezone bug. The poller used &lt;code&gt;time.mktime()&lt;/code&gt; to parse the conversation's &lt;code&gt;last_message_at&lt;/code&gt; timestamp, but Telnyx timestamps are in UTC (the &lt;code&gt;Z&lt;/code&gt; suffix). &lt;code&gt;time.mktime()&lt;/code&gt; interprets as local time, so every conversation appeared to be 7 hours in the future, and the "is this call old enough to process?" check always returned false. The fix was to use &lt;code&gt;calendar.timegm()&lt;/code&gt; which interprets as UTC.&lt;/p&gt;

&lt;p&gt;These are the kinds of bugs that only show up in production. The example in the repo has both fixes applied.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Is Not
&lt;/h2&gt;

&lt;p&gt;This is not a full event management platform. It is a single example showing how to use a Telnyx AI Assistant as an inbound data-collection agent. The RSVPs are stored in memory. There is no authentication. There is no multi-event support. There is no SMS confirmation.&lt;/p&gt;

&lt;p&gt;But the shape is right. Swap the in-memory list for Postgres. Add SMS confirmation via Telnyx Messaging. Add per-event TeXML apps with dynamic prompt templates. Add A/B-tested greetings. The architecture scales because the call and the dashboard are decoupled.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Point
&lt;/h2&gt;

&lt;p&gt;The point is the pattern. A phone number, an AI assistant, a polling dashboard. No forms. No friction. Just the channel that already has a 90%+ answer rate.&lt;/p&gt;

&lt;p&gt;Nobody should fill out an Eventbrite form for a 12-person dinner.&lt;/p&gt;

&lt;p&gt;The code is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-event-rsvp-phone-line-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-event-rsvp-phone-line-python&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clone it, set your Telnyx API key, run it. The phone number is the RSVP line. The dashboard is the guest list. That's it.&lt;/p&gt;

</description>
      <category>telnyx</category>
      <category>ai</category>
      <category>devrel</category>
    </item>
    <item>
      <title>I Built a Phone Number That Controls Simulated Facility Equipment</title>
      <dc:creator>anusha</dc:creator>
      <pubDate>Wed, 01 Jul 2026 23:34:32 +0000</pubDate>
      <link>https://dev.to/botoclock/i-built-a-phone-number-that-controls-simulated-facility-equipment-1c74</link>
      <guid>https://dev.to/botoclock/i-built-a-phone-number-that-controls-simulated-facility-equipment-1c74</guid>
      <description>&lt;p&gt;Most voice AI examples are conversational. A user talks to an assistant, the assistant responds, and the demo ends there.&lt;/p&gt;

&lt;p&gt;I wanted something more tactile: call a phone number, say a command, and see a system change.&lt;/p&gt;

&lt;p&gt;So this example turns a Telnyx phone number into a voice-controlled facility command line. You call in and say things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unlock the loading dock gate
turn on the warehouse lights
check the freezer alarm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The app listens, maps the spoken request to a simulated IoT device, updates state, logs the command, and speaks back the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Basic Flow
&lt;/h2&gt;

&lt;p&gt;The app is a small Python Flask service.&lt;/p&gt;

&lt;p&gt;When someone calls the Telnyx number:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Telnyx sends a Call Control webhook to Flask.&lt;/li&gt;
&lt;li&gt;The app answers the call.&lt;/li&gt;
&lt;li&gt;Telnyx AI gather captures the caller's spoken command.&lt;/li&gt;
&lt;li&gt;The app parses the command into a device and action.&lt;/li&gt;
&lt;li&gt;The app updates simulated device state.&lt;/li&gt;
&lt;li&gt;Telnyx speaks a short confirmation.&lt;/li&gt;
&lt;li&gt;The command appears in an audit log.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The important part is that the result is visible. You can keep &lt;code&gt;/devices&lt;/code&gt; open during the demo and refresh it after each command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use a Local Parser in the Live Call
&lt;/h2&gt;

&lt;p&gt;The app includes a Telnyx AI Inference path for parsing commands through the local HTTP API. That is useful for showing how the pattern can handle broader natural language.&lt;/p&gt;

&lt;p&gt;For the live phone call, responsiveness matters more. After Telnyx AI gather captures the command, the app uses a deterministic parser for known demo phrases. That avoids a second AI call and makes the phone experience feel faster.&lt;/p&gt;

&lt;p&gt;This is a useful production lesson: not every part of a voice AI system needs to be generative. Use AI where it adds flexibility, and use deterministic logic where latency and reliability matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Could Become
&lt;/h2&gt;

&lt;p&gt;The current app uses simulated devices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;loading dock gate&lt;/li&gt;
&lt;li&gt;warehouse lights&lt;/li&gt;
&lt;li&gt;freezer alarm&lt;/li&gt;
&lt;li&gt;backup generator&lt;/li&gt;
&lt;li&gt;irrigation pump&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In production, the same pattern could connect to real systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;building access control&lt;/li&gt;
&lt;li&gt;field equipment&lt;/li&gt;
&lt;li&gt;fleet devices&lt;/li&gt;
&lt;li&gt;industrial alerts&lt;/li&gt;
&lt;li&gt;facilities operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For risky actions, you would add caller authentication, allowlists, and confirmation steps. You would also store command logs in a database and keep webhook signature verification enabled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo Script
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;/devices&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Call the number.&lt;/p&gt;

&lt;p&gt;Say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unlock the loading dock gate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Refresh &lt;code&gt;/devices&lt;/code&gt; and show the gate is unlocked.&lt;/p&gt;

&lt;p&gt;Then say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;turn on the warehouse lights
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Refresh again and show the lights are on.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;/commands&lt;/code&gt; to show the audit log.&lt;/p&gt;

&lt;p&gt;That is the full story: voice input, command parsing, state change, spoken confirmation, and an audit trail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Telnyx Call Control: &lt;a href="https://developers.telnyx.com/docs/voice/call-control" rel="noopener noreferrer"&gt;https://developers.telnyx.com/docs/voice/call-control&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx AI Inference: &lt;a href="https://developers.telnyx.com/docs/inference" rel="noopener noreferrer"&gt;https://developers.telnyx.com/docs/inference&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx IoT: &lt;a href="https://telnyx.com/products/iot-sim-card" rel="noopener noreferrer"&gt;https://telnyx.com/products/iot-sim-card&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>telnyx</category>
      <category>ai</category>
      <category>devrel</category>
    </item>
    <item>
      <title>I Built a Web Chatbot with a Telnyx AI Assistant</title>
      <dc:creator>anusha</dc:creator>
      <pubDate>Tue, 30 Jun 2026 20:19:15 +0000</pubDate>
      <link>https://dev.to/botoclock/i-built-a-web-chatbot-with-a-telnyx-ai-assistant-4kjc</link>
      <guid>https://dev.to/botoclock/i-built-a-web-chatbot-with-a-telnyx-ai-assistant-4kjc</guid>
      <description>&lt;p&gt;Most AI assistant demos jump straight to voice. Voice is great, but a web chat is often the cleanest place to start.&lt;/p&gt;

&lt;p&gt;You can prove the core idea quickly: configure an assistant in the Portal, send it user messages through the API, and render the response in your own interface.&lt;/p&gt;

&lt;p&gt;The Telnyx code example for this is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/chat-with-ai-assistant-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/chat-with-ai-assistant-python&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea
&lt;/h2&gt;

&lt;p&gt;The assistant lives in Telnyx. The UI lives in your app.&lt;/p&gt;

&lt;p&gt;That split is useful. Product teams can tune the assistant instructions in the Telnyx Mission Control Portal, while developers keep full control over the frontend, authentication, routing, styling, logging, and product-specific behavior.&lt;/p&gt;

&lt;p&gt;For this demo, I used the assistant as a Telnyx Chatbot. It answers questions like what Telnyx does, what a Frankenstack is, and how AI Assistants fit into programmable communications.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Flow
&lt;/h2&gt;

&lt;p&gt;The app is a small Flask server with a browser UI.&lt;/p&gt;

&lt;p&gt;When the page loads, the backend creates a Telnyx conversation. When the user sends a message, the backend sends that message to the Assistant Chat API. The assistant response comes back as text and the UI renders it in the chat window.&lt;/p&gt;

&lt;p&gt;The important part is that the API key stays on the server. The browser only talks to the Flask app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Demo Works
&lt;/h2&gt;

&lt;p&gt;This is a good first AI Assistant project because there is no phone number setup, no webhook tunnel, and no call-control state machine. You can focus on the assistant lifecycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create conversation
send message
render response
continue conversation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That makes it easier to explain the difference between a Portal-managed assistant and a raw model completion. The assistant has configuration, instructions, conversation context, and product-level settings. Your app just decides where and how that assistant shows up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/team-telnyx/telnyx-code-examples.git
&lt;span class="nb"&gt;cd &lt;/span&gt;telnyx-code-examples/chat-with-ai-assistant-python
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
python app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TELNYX_API_KEY=your_telnyx_api_key
AI_ASSISTANT_ID=your_ai_assistant_id
PORT=5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the local app and ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is Telnyx?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is a Frankenstack?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those two questions make the demo easy to understand. Telnyx is the integrated communications and AI platform; a Frankenstack is what happens when teams stitch together separate vendors for telephony, speech-to-text, LLMs, text-to-speech, messaging, analytics, and workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Would Add Next
&lt;/h2&gt;

&lt;p&gt;For a real product, I would add user accounts, persistent conversation history, analytics, rate limits, and a handoff path to a human or support workflow. If the same assistant also powers voice or messaging, I would keep the assistant's core instructions consistent and let each channel handle its own UX.&lt;/p&gt;

&lt;p&gt;That is the nice part of this pattern: one assistant can power multiple user experiences, and the app decides how the experience feels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Code example: &lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/chat-with-ai-assistant-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/chat-with-ai-assistant-python&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx AI Assistants: &lt;a href="https://telnyx.com/ai-assistants" rel="noopener noreferrer"&gt;https://telnyx.com/ai-assistants&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx developer docs: &lt;a href="https://developers.telnyx.com/docs/overview" rel="noopener noreferrer"&gt;https://developers.telnyx.com/docs/overview&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>telnyx</category>
      <category>ai</category>
      <category>devrel</category>
    </item>
    <item>
      <title>I Built a Restaurant Reservation Voice Agent with Telnyx</title>
      <dc:creator>anusha</dc:creator>
      <pubDate>Tue, 30 Jun 2026 18:57:07 +0000</pubDate>
      <link>https://dev.to/botoclock/i-built-a-restaurant-reservation-voice-agent-with-telnyx-go5</link>
      <guid>https://dev.to/botoclock/i-built-a-restaurant-reservation-voice-agent-with-telnyx-go5</guid>
      <description>&lt;p&gt;Restaurant calls are a good test case for voice ai because the workflow is familiar: answer the phone, ask a few questions, confirm the booking, and send a text message.&lt;/p&gt;

&lt;p&gt;The Telnyx code example for this is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-restaurant-reservation-voice-agent-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-restaurant-reservation-voice-agent-python&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is a Python Flask app that combines Voice AI, AI Inference, and SMS/MMS in one small demo.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Flow
&lt;/h2&gt;

&lt;p&gt;The caller dials a Telnyx number. Telnyx sends the call event to a webhook. The app answers, speaks a greeting, gathers speech, sends the caller's words to Telnyx AI Inference, speaks the response back, and repeats until the reservation is complete.&lt;/p&gt;

&lt;p&gt;When the booking is confirmed, the app sends an SMS confirmation.&lt;/p&gt;

&lt;p&gt;That is the interesting part: this is not just a chatbot. It is a phone workflow with voice input, ai reasoning, spoken output, and a messaging follow-up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Like This Example
&lt;/h2&gt;

&lt;p&gt;It is simple enough to demo quickly, but it still maps to real developer questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how do i answer an inbound phone call with code?&lt;/li&gt;
&lt;li&gt;how do i collect speech from a caller?&lt;/li&gt;
&lt;li&gt;how do i use ai to decide what to say next?&lt;/li&gt;
&lt;li&gt;how do i send an sms after a call?&lt;/li&gt;
&lt;li&gt;how do i inspect what happened after the demo?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;/reservations&lt;/code&gt; endpoint is useful because it gives the audience something visible after the call. The SMS confirmation gives the demo a clear finish.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run It Locally
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/team-telnyx/telnyx-code-examples.git
&lt;span class="nb"&gt;cd &lt;/span&gt;telnyx-code-examples/ai-restaurant-reservation-voice-agent-python
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
python app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then expose the webhook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ngrok http 5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the Telnyx Portal, point your Voice API application webhook to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://&amp;lt;ngrok-id&amp;gt;.ngrok-free.app/webhooks/voice
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assign a Telnyx number to that Voice API application and call the number.&lt;/p&gt;

&lt;h2&gt;
  
  
  What To Demo
&lt;/h2&gt;

&lt;p&gt;I would keep the demo short:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Show the Voice API app webhook.&lt;/li&gt;
&lt;li&gt;Call the number.&lt;/li&gt;
&lt;li&gt;Book a table.&lt;/li&gt;
&lt;li&gt;Show the SMS confirmation.&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;/reservations&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That gives viewers the full loop without getting lost in implementation details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where To Take It Next
&lt;/h2&gt;

&lt;p&gt;The demo uses in-memory state, which is perfect for learning. The next production steps are database storage, availability checks, webhook verification, and a real reservation system integration.&lt;/p&gt;

&lt;p&gt;The important thing is that the skeleton is already there: voice in, ai decision, voice out, and SMS follow-up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Code example: &lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-restaurant-reservation-voice-agent-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-restaurant-reservation-voice-agent-python&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx Voice docs: &lt;a href="https://developers.telnyx.com/docs/voice" rel="noopener noreferrer"&gt;https://developers.telnyx.com/docs/voice&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx AI Inference docs: &lt;a href="https://developers.telnyx.com/docs/inference" rel="noopener noreferrer"&gt;https://developers.telnyx.com/docs/inference&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telnyx Messaging docs: &lt;a href="https://developers.telnyx.com/docs/messaging" rel="noopener noreferrer"&gt;https://developers.telnyx.com/docs/messaging&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>telnyx</category>
      <category>ai</category>
      <category>devrel</category>
    </item>
    <item>
      <title>Building Voice AI Workflows with Branches Instead of One Giant Prompt</title>
      <dc:creator>anusha</dc:creator>
      <pubDate>Fri, 26 Jun 2026 16:54:07 +0000</pubDate>
      <link>https://dev.to/botoclock/building-voice-ai-workflows-with-branches-instead-of-one-giant-prompt-384c</link>
      <guid>https://dev.to/botoclock/building-voice-ai-workflows-with-branches-instead-of-one-giant-prompt-384c</guid>
      <description>&lt;p&gt;I built a Telnyx Conversational Workflows example for auto insurance claim intake.&lt;/p&gt;

&lt;p&gt;The main idea is simple: when a voice agent has to do a lot, one big prompt can get hard to manage.&lt;/p&gt;

&lt;p&gt;For intake calls, there are usually a bunch of paths to handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing information&lt;/li&gt;
&lt;li&gt;safety checks&lt;/li&gt;
&lt;li&gt;fallback paths&lt;/li&gt;
&lt;li&gt;priority follow-up&lt;/li&gt;
&lt;li&gt;backend tool calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This example models the call as a workflow instead of putting everything into one prompt.&lt;/p&gt;

&lt;p&gt;The workflow handles the conversation path. A small Node.js/Express backend exposes tool endpoints for structured actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POST /tools/create-claim-intake&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /tools/log-claim-intake-fallback&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /tools/flag-priority-follow-up&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /health&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I like this pattern because it makes the flow easier to inspect. You can see the nodes, branches, and tool calls instead of trying to debug everything from prompt behavior.&lt;/p&gt;

&lt;p&gt;Run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/team-telnyx/telnyx-code-examples.git
&lt;span class="nb"&gt;cd &lt;/span&gt;telnyx-code-examples/build-conversational-workflow-nodejs
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm &lt;span class="nb"&gt;test
&lt;/span&gt;node server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Code example:&lt;/p&gt;

&lt;p&gt;[&lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/build-conversational-workflow-nodejs" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/build-conversational-workflow-nodejs&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>voiceai</category>
      <category>ai</category>
      <category>node</category>
      <category>telnyx</category>
    </item>
    <item>
      <title>Building a Reusable Voice Agent with Runtime Configuration</title>
      <dc:creator>anusha</dc:creator>
      <pubDate>Fri, 26 Jun 2026 16:38:56 +0000</pubDate>
      <link>https://dev.to/botoclock/building-a-reusable-voice-agent-with-runtime-configuration-3175</link>
      <guid>https://dev.to/botoclock/building-a-reusable-voice-agent-with-runtime-configuration-3175</guid>
      <description>&lt;p&gt;I built a small Telnyx Voice example around a pattern I keep running into: one voice agent, multiple business contexts.&lt;br&gt;
For appointment scheduling, a dental office, medical clinic, and physical therapy practice often need the same basic call flow. The assistant still answers the call, collects appointment details, and confirms the next step.&lt;/p&gt;

&lt;p&gt;What changes is the business context: name, hours, services, tone, and greeting.&lt;/p&gt;

&lt;p&gt;Instead of creating a separate assistant for every business, this example uses one reusable base assistant and applies runtime instructions when the call starts.&lt;/p&gt;

&lt;p&gt;The flow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Caller dials a Telnyx number.&lt;/li&gt;
&lt;li&gt;The webhook checks which number was called.&lt;/li&gt;
&lt;li&gt;The number maps to a business config.&lt;/li&gt;
&lt;li&gt;The server renders the right instructions and greeting.&lt;/li&gt;
&lt;li&gt;Telnyx starts the assistant with that runtime context.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That makes it easier to reuse one assistant pattern across multiple businesses without copying the whole assistant setup.&lt;/p&gt;

&lt;p&gt;Run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/team-telnyx/telnyx-code-examples.git
&lt;span class="nb"&gt;cd &lt;/span&gt;telnyx-code-examples/provisional-telnyx-voice-api-agents-nodejs
npm &lt;span class="nb"&gt;install
cp&lt;/span&gt; .env.example .env
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also preview a generated payload:&lt;br&gt;
&lt;code&gt;npm run preview -- smile-dental&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Code example:&lt;br&gt;
[&lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/provisional-telnyx-voice-api-agents-nodejs" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/provisional-telnyx-voice-api-agents-nodejs&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>voiceai</category>
      <category>ai</category>
      <category>node</category>
      <category>telnyx</category>
    </item>
    <item>
      <title>Outbound Voice Agent that Drops Out on Hold and Rejoins When a Human Answers</title>
      <dc:creator>anusha</dc:creator>
      <pubDate>Fri, 26 Jun 2026 16:11:34 +0000</pubDate>
      <link>https://dev.to/botoclock/outbound-voice-agent-that-drops-out-on-hold-and-rejoins-when-a-human-answers-4l73</link>
      <guid>https://dev.to/botoclock/outbound-voice-agent-that-drops-out-on-hold-and-rejoins-when-a-human-answers-4l73</guid>
      <description>&lt;p&gt;Outbound hold agent with Telnyx Voice&lt;/p&gt;

&lt;p&gt;This Python example shows how to handle outbound calls where the agent has to wait on hold. It places an outbound call, uses an assistant for IVR/menu navigation, pauses during hold, and resumes when a human representative answers.&lt;/p&gt;

&lt;p&gt;[&lt;a href="https://github.com/team-telnyx/telnyx-code-examples/tree/main/outbound-hold-agent-python" rel="noopener noreferrer"&gt;https://github.com/team-telnyx/telnyx-code-examples/tree/main/outbound-hold-agent-python&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;Check out the full example here.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>voiceai</category>
      <category>agents</category>
      <category>api</category>
    </item>
  </channel>
</rss>
