Build one AI agent that emails, texts, and calls customers with one shared memory. A Python tutorial using one Telnyx API key.
Takeaways
This tutorial builds one AI agent that emails, texts, and calls your customer in the same conversation, and remembers every message across all three channels.
A 6am flight cancellation sets off a scramble. The traveler wants rebooking options, a written record, and quick answers while they commute. The same conversation might need a detailed email, a short text, and a phone call, all within an hour.
Customers already live across channels. According to a recent CX Trends report, 74% of consumers now expect customer service to be available around the clock, and 76% say they would choose a company that lets them keep everything in one thread instead of restarting on every channel.
Most teams answer by bolting three separate bots onto three channels. The email autoresponder knows nothing about the SMS thread. The SMS thread knows nothing about the call. The customer feels the gap and repeats their story every time.
This tutorial takes a different approach: one AI agent that emails, texts, and calls customers with shared memory across all three, built in about 700 lines of Python behind a single Telnyx API key.
An omnichannel AI agent is a single AI system that reaches a customer across email, SMS, and voice while keeping one conversation memory across every channel. It decides which channel fits each message, writes the content, and references what it already said elsewhere.
Omnichannel is the word that matters. Multichannel means you offer many channels. Omnichannel means the customer's context follows them between those channels. The difference shows up in how the agent behaves:
| Multichannel setup | Omnichannel agent |
|---|---|
| One bot per channel | One agent across channels |
| No shared history | One conversation memory for all channels |
| Customer repeats their story | Agent references earlier messages |
| Channel choice made by the customer | Agent picks the right channel per message |
Forrester makes the same case in its omnichannel customer service research: customers use every channel available to them, and brands need one connected approach rather than channel silos.
The app is a small Python service, built with a web framework called Flask, that runs a customer service AI agent for a fictional demo company, TelnyxDemo Corp. You hand it a customer scenario in plain language, and it plans the outreach itself:
The default demo scenario is a billing dispute: a customer disputes a $147.50 charge, and the agent emails an acknowledgment, texts a timeline confirmation, and calls only if the resolution needs one.
The same three tools fit any business. Point them at your own scenarios:
Travel app
Rebooking options by email after a cancelled flight, day-of alerts by SMS, a call when a change needs an immediate decision.
Restaurant app
Reservation confirmations by email, waitlist updates by SMS, a call when a table opens on short notice.
Appointments
Prep instructions by email a week out, a day-before reminder by SMS, a morning-of call if the customer hasn't confirmed.
A browser dashboard shows the agent's activity feed and channel timeline in real time, and the full code is open source.
Five things, and you likely have an account already if you build on Telnyx:
| Item | Where in the Portal | What the app uses it for |
|---|---|---|
| API key | API Keys section | Authorizes inference, email, SMS, and calls |
| Phone number | Numbers section | From number for SMS and calls |
| Messaging Profile ID | Messaging section | Routes outbound SMS |
| Call Control Connection ID | Voice, Call Control Applications | Places outbound calls |
| Email sending address | Email section | From address for email |
A shared sending domain is available for testing, so you can send email before you verify your own domain.
Three pieces make it work:
Three things govern every outreach the agent plans: the tools it can call, the channel guidance in its system prompt, and the conversation history it carries into each decision.
Tool calling sounds more technical than it is. The agent gets a small toolbox with four tools: send_email, send_sms, make_call, and resolve_issue. Each tool carries a short description that tells the agent when to reach for it. The SMS tool introduces itself like this:
{ "name": "send_sms", "description": "Send a short SMS text message to the customer. Use for quick status updates, confirmations, or time-sensitive notifications." }
The system prompt adds channel guidance, straight from app.py:
- Email: Formal acknowledgments, detailed explanations, records that need a paper trail - SMS: Quick status updates, confirmations, time-sensitive alerts - Voice call: Complex resolution, urgent escalation, personal touch for upset customers
For the demo's billing dispute, it even spells out the order of operations: email first to acknowledge the issue and outline next steps, SMS to confirm the email arrived with a timeline, and a call only if the resolution is complex.
Then the agent works like anyone with a to-do list: read the situation, do the next right thing, check the result, repeat until the job is done. There is no script to follow and no timeline to hardcode. Each pass is one request to Telnyx Inference:
resp = requests.post( "https://api.telnyx.com/v2/ai/chat/completions", headers={"Authorization": f"Bearer {TELNYX_API_KEY}"}, json={"model": AI_MODEL, "messages": messages, "tools": TOOLS}, )
The model looks at the scenario, the tools, and the conversation history, then decides its next move on its own. Every action comes back as a result it can react to, and it only stops when the issue is handled. The last move is always resolve_issue, with a short summary of what it did.
Every message the agent sends or receives is stored with its channel:
cur.execute( "INSERT INTO conversations " "(customer_id, channel, role, content, timestamp) " "VALUES (?, ?, ?, ?, ?)", (customer_id, channel, role, content, datetime.now(timezone.utc).isoformat()), )
Before the next run, the history is loaded and formatted into the prompt, so the model sees one timeline: what was emailed, what was texted, what was said on the call.
That memory is what separates an agent from three bots. The agent can say "as we emailed you this morning" in a text, and "following up on our email and text" on a call, and every line lands like it comes from one person. If the email and the SMS disagree, the customer notices, and every mismatch costs a little trust.
The billing dispute is only the demo default. Swap the scenario text for your own business and the agent plans the channel mix. A travel app handling a cancelled flight runs like this:
A cancelled flight, as the agent works it
| Step | Channel | What the customer gets |
|---|---|---|
| 1 | "We've rebooked your Oct 14 flight", with the new itinerary, fare difference, and a reference number. | |
| 2, minutes later | SMS | "Hi Sarah, we emailed you new options for your cancelled Oct 14 flight. Reply here if none of them work and we'll call you." |
| 3, if departure is under 24 hours | Voice call | "Hi Sarah, this is about your Oct 14 flight. We emailed rebooking options and texted you a summary. I'm calling to confirm which option works for you." |
Every message references the ones before it. The customer gets one coherent conversation across three channels.
Other travel workflows, same pattern
| Scenario | SMS | Voice call | |
|---|---|---|---|
| Pre-trip reminders | Prep instructions and documents | Day-before reminder | Morning-of confirmation if unanswered |
| Itinerary change | Updated booking details | The one action the customer must take | If the change costs the customer money |
A restaurant runs the same playbook
| Scenario | SMS | Voice call | |
|---|---|---|---|
| New reservation | Booking confirmation with the guest's details | Day-of reminder with the address | Only if the booking needs to change |
| Large party, short on tables | The new arrangements in writing | A quick heads-up that the seating moved | To apologize personally and confirm the new time |
The agent decides the mix. You write the scenario in plain language: "Customer's LHR to AMS flight on Oct 14 was cancelled." The agent plans the rest.
git clone https://github.com/team-telnyx/telnyx-code-examples.git cd telnyx-code-examples/omnichannel-ai-agent-python
pip install -r requirements.txt
cp .env.example .env
TELNYX_API_KEY=your_telnyx_api_key
TELNYX_FROM_NUMBER=+15551234567
[email protected]
CONNECTION_ID=your_connection_id
AI_MODEL=meta-llama/Llama-3.3-70B-Instructpython app.py
The dashboard runs at localhost:5000 with two panels: agent activity on the left, and the channel timeline on the right.
python demo/demo_server.py and the entire flow is simulated, so you can watch the agent plan its outreach before you wire a single key. Right now the demo does the talking: it reaches out, but it doesn't listen for replies yet. Three upgrades turn it into something you can run for real customers:
1. Let customers talk back
The code already knows how to receive a reply on all three channels (message.received, email.received, call.answered). Give it a public web address where Telnyx can deliver them, and the agent can listen, not just send.
2. Try a different model
Change one line in your .env file to use any model in the Telnyx Inference catalog. The rest of the app stays exactly the same.
3. Plug in your CRM
The demo keeps its memory in a simple local database. Swap that part for your customer system, and every conversation lives where your team already works.
For the full pattern of handling replies, events, and status updates from every channel in one place, see event-driven architecture for multi-channel communications.
The same pattern works far beyond travel: appointment reminders, billing disputes, order updates, and renewal outreach all follow the same email, SMS, call pattern.
One API key for inference, email, SMS, and voice. One conversation memory across every channel.

Related articles
Why your voice AI agent is slow on phone calls, and how to fix it
The 11 best conversational AI platforms in 2026
How to evaluate Voice AI the way real conversations work

WhatsApp Business API: Pricing, Setup and Limits Guide for 2026

WhatsApp Business Messaging for Retail: Setup and Pricing

Voice AI Agents Compared on Latency: 2026 Benchmarks
