Every event I have ever organized has the same problem. I send the invites. People say "I'll RSVP later." They don't. Then I spend three days chasing them on Slack, on email, and in person. Three days before the event, I still don't know if I'm feeding 12 people or 40.
The form I built got a 30% response rate. The Slack reminder got 50%. Phone calls — actual phone calls — got 90%+.
So the question is: why am I building forms at all? People answer the phone. They don't answer forms.
This is the problem behind the AI Event RSVP Phone Line example:
https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-event-rsvp-phone-line-python
The example is a single-file Python app that wires a Telnyx phone number to an AI Assistant. Callers dial the number, the AI picks up, collects four pieces of information — name, party size, dietary restrictions, accessibility needs — confirms everything back, and hangs up. Within about 30 seconds, a structured RSVP appears in a dashboard as a row of JSON.
No form. No app to download. No link to click. Just a phone number.
What Is an AI RSVP Phone Line?
An AI RSVP phone line is an inbound voice agent that collects structured event attendance data over a phone call.
It understands that an RSVP has four fields:
- the caller's full name
- number of guests including the caller
- dietary restrictions (vegetarian, vegan, gluten-free, allergies, or none)
- any accessibility needs
The AI collects these one at a time, in a natural conversation, confirms them back to the caller, and ends the call. After hangup, the conversation transcript is processed by a second inference call that extracts a structured JSON object — name, guests, dietary, accessibility, confirmed — and appends it to a list that the event host can view, search, export to CSV, or push into Airtable.
That difference sounds small, but it changes how you think about the RSVP workflow. You stop building forms that nobody fills out and start using the channel that already has a 90%+ answer rate.
Why the Phone Wins for RSVPs
The standard RSVP flow is broken because it puts the friction on the wrong person.
A web form asks the guest to find the link, open a browser, type their name, select a dropdown, click submit, and hope it went through. Every step is a chance to abandon. The result is a 5-20% response rate for event forms, which means the host spends days chasing the other 80%.
A phone call asks the guest to do one thing: answer the phone. They already know how to do that. The AI does the rest — asks the questions, waits for the answers, confirms the details, and hangs up. The guest never fills out a field, clicks a button, or opens a browser.
The conversion difference is not marginal. It is the difference between chasing 80% of your guest list and chasing 0% of them.
The other advantage is accessibility. A phone call works for guests who don't have a smartphone, don't have a data plan, or don't want to type on a small screen. A form doesn't.
The Architecture
The example uses two Telnyx products working together:
- Telnyx AI Assistant — the conversational brain. 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, no signature verification.
- Telnyx Conversations API — the data layer. After the call ends, the conversation transcript is available via the Conversations API. The dashboard polls this endpoint every 5 seconds, finds new conversations from the RSVP assistant, and runs a second inference call to extract the structured RSVP from the transcript.
The flow looks like this:
caller dials the RSVP number
|
v
Telnyx AI Assistant picks up
|
v
conversation loop:
STT (caller speaks) -> LLM (assistant reasons) -> TTS (assistant speaks)
|
v
caller hangs up -> conversation stored on Telnyx
|
v
dashboard polls /v2/ai/conversations every 5s
|
v
finds new conversations from the RSVP assistant
|
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. This means the demo is reliable — there is no ngrok tunnel to break, no webhook signature to verify, no Flask webhook loop to debug. Telnyx hosts everything.
Why the Dashboard Should Not Own the Call
This pattern works because the dashboard and the call are decoupled.
If the dashboard owned the call — answering, gathering speech, calling inference, speaking back — it would need a public webhook URL, a signature verification step, and a persistent process that stays alive for the duration of every call. That is fragile. A tunnel goes down, the call drops. A process restarts, the call drops. A webhook signature fails verification, the call drops.
By letting Telnyx host the call via the AI Assistant product, the dashboard becomes optional. The RSVP line works even if the dashboard is not running. The dashboard just shows what already happened.
That separation is what makes this example reliable enough to demo live. The phone number always works. The dashboard is a nice-to-have.
The System Prompt
The AI Assistant is configured with a system prompt that tells it exactly what to collect:
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.
The prompt is deliberately lowercase with no exclamation marks. This is a Telnyx AI Assistant convention — the assistant's internal text processing works more reliably with lowercase prompts, and exclamation marks can cause TTS to over-emphasize.
The prompt also enforces order. The assistant collects name first, then party size, then dietary, then accessibility. This makes the conversation predictable and the extraction reliable — the second inference call always sees the same structure.
The Extraction Prompt
After the call ends, the dashboard runs a second inference call to turn the transcript into structured 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 prompt 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, and 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.
Setting Up the Phone Number
The phone number is wired to the AI Assistant via a TeXML application. The TeXML app's voice_url points at the assistant's TeXML endpoint:
https://api.telnyx.com/v2/ai/assistants/{assistant_id}/texml
When a caller dials the number, Telnyx routes the call to the TeXML app, which returns a <Connect><AIAssistant> TeXML response, which hands the call to the AI Assistant. The assistant handles everything from there.
The phone number assignment is a single PATCH call:
requests.patch(
f"https://api.telnyx.com/v2/phone_numbers/{phone_number_id}",
headers=headers,
json={"connection_id": texml_app_id},
)
After that, inbound calls to the number route to the RSVP assistant.
The Dashboard
The dashboard is a Flask app with a single HTML page and a few JSON endpoints:
GET /— the dashboard UI (table of RSVPs, stats, event config)GET /api/state— full state for the dashboard (rsvps, log, processing status)GET /api/event— get the current event configPOST /api/event— update the event config (rewrites the assistant's prompt on Telnyx)GET /api/rsvps.csv— download all RSVPs as CSVGET /api/rsvp/<idx>/transcript— get the full call transcript for an RSVPPOST /api/clear— clear all RSVPs
The polling loop runs in a background thread. Every 5 seconds it fetches the 10 most recent conversations, checks which ones belong to the RSVP assistant, waits for in-progress calls to finish (using last_message_at to determine if the call has ended), and extracts the structured RSVP from completed conversations.
The race-condition handling matters here. A common bug is to fetch a conversation's messages before they are fully populated, get back an error or an empty transcript, and permanently blacklist that conversation. The fix is 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.
Running It
The full setup is in the README:
git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/ai-event-rsvp-phone-line-python
cp .env.example .env
pip install -r requirements.txt
python app.py
Then dial the number. The AI picks up, collects the RSVP, hangs up. Refresh the dashboard. The RSVP is there.
What This Example 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 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.
Related Links
- Code example: https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-event-rsvp-phone-line-python
- Telnyx AI Assistants: https://developers.telnyx.com/docs/ai/ai-assistants
- Telnyx Call Control: https://developers.telnyx.com/docs/voice/call-control
- Telnyx AI Inference: https://developers.telnyx.com/docs/inference
- Telnyx Conversations API: https://developers.telnyx.com/docs/ai/conversations