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.
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%+.
So I stopped building forms and built a phone number instead.
The code is here:
https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-event-rsvp-phone-line-python
The Idea
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.
No form. No app to download. No link to click. Just a phone number.
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.
The conversion difference is not marginal. It is the difference between chasing 80% of your guest list and chasing 0% of them.
The Architecture
Two Telnyx products do the work.
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.
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.
The flow:
caller dials the RSVP number
|
v
Telnyx AI Assistant picks up (Voice Ultra Katie, gpt-4o)
|
v
conversation: STT -> LLM -> TTS, looped
|
v
caller hangs up -> 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
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.
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.
The Prompt That Does the Work
The assistant's system prompt is deliberately simple:
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.
Lowercase. No exclamation marks. This is a Telnyx AI Assistant convention — lowercase prompts process more reliably and exclamation marks cause TTS to over-emphasize.
The prompt enforces order. Name first, then party size, then dietary, then accessibility. This makes the conversation predictable and the extraction reliable.
The Extraction Step
After the call ends, the dashboard runs a second inference call to turn the transcript into JSON:
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.
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.
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.
The Race Condition I Had to Fix
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.
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.
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.
There was also a timezone bug. The poller used time.mktime() to parse the conversation's last_message_at timestamp, but Telnyx timestamps are in UTC (the Z suffix). time.mktime() 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 calendar.timegm() which interprets as UTC.
These are the kinds of bugs that only show up in production. The example in the repo has both fixes applied.
What This Is Not
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.
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.
The Point
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.
Nobody should fill out an Eventbrite form for a 12-person dinner.
The code is here:
https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-event-rsvp-phone-line-python
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.
Top comments (0)