{"slug": "ai-agent-that-carries-context-across-email-voice-and-sms", "title": "AI Agent That Carries Context Across Email, Voice, and SMS", "summary": "Telnyx published a Python and Flask sample application that carries customer context across email, SMS, and voice using four Telnyx APIs — Email, Messaging, Call Control, and AI Inference — from a single API key. The agent resolves customer identity across channels via a SQLite identity registry mapping email to phone number, so a customer who emails and then calls is greeted with context such as \"I see you contacted us about changing your booking. Are you calling about the same request?\" The sample handles webhook events including email.received, call.initiated, call.answered, call.gather.ended, and message.received.", "body_md": "| name | omnichannel-context-carrying | \n|---|---|\n| title | Omnichannel Context-Carrying Agent | \n| description | AI agent that carries customer context across email, voice, and SMS so customers never repeat themselves. Demonstrates cross-channel identity resolution with Telnyx Inference, Email, Messaging, and Call Control APIs. | \n| language | python | \n| framework | flask | \n| telnyx_products |  | \n| channel |  | \n\n| Email | Messaging | Voice | Call Control | AI Inference | \n\n| email | sms | voice | \n\nAI agent that carries customer context across email, voice, and SMS so customers never repeat themselves. When a customer calls after emailing, the AI greets them with: \"I see you contacted us about changing your booking. Are you calling about the same request?\"\n\nTelnyx is an **AI Communications Infrastructure** platform — email, messaging, voice, and AI on one private, global network. This sample uses four Telnyx APIs (Email, Messaging, Call Control, AI Inference) from a single API key to demonstrate seamless cross-channel context carrying with customer identity resolution.\n\n- **Send Email** :`POST /v2/emails` —[API reference](https://developers.telnyx.com/api/email/send-email)\n- **Send Message** :`POST /v2/messages` —[API reference](https://developers.telnyx.com/api/messaging/send-message)\n- **Create Call** :`POST /v2/calls` —[API reference](https://developers.telnyx.com/api/call-control/create-call)\n- **Answer Call** :`POST /v2/calls/{call_control_id}/actions/answer` —[API reference](https://developers.telnyx.com/api/call-control/answer-call)\n- **Speak** :`POST /v2/calls/{call_control_id}/actions/speak` —[API reference](https://developers.telnyx.com/api/call-control/speak)\n- **Gather Speech** :`POST /v2/calls/{call_control_id}/actions/gather` —[API reference](https://developers.telnyx.com/api/call-control/gather)\n- **AI Inference** :`POST /v2/ai/chat/completions` —[API reference](https://developers.telnyx.com/docs/inference/chat-completions)\n\nThis app handles these webhook events:\n\n- `email.received` — Inbound email triggers AI reply flow\n- `call.initiated` — Incoming call triggers identity lookup and answer\n- `call.answered` — AI generates contextual greeting from cross-channel history\n- `call.speak.ended` — TTS playback finished, begins speech gathering\n- `call.gather.ended` — Customer speech captured, AI processes with full context\n- `call.hangup` — Call ended\n- `message.received` — Inbound SMS triggers AI reply with cross-channel context\n\n```\n         Customer contacts on any channel\n              │         │         │\n          Email in   Call in   SMS in\n              │         │         │\n              ▼         ▼         ▼\n        ┌─────────────────────────────┐\n        │         Flask app.py        │\n        │                             │\n        │  ┌───────────────────────┐  │\n        │  │  Customer Identity    │  │\n        │  │  Registry (SQLite)    │  │\n        │  │  email ↔ phone ↔ id   │  │\n        │  └───────────┬───────────┘  │\n        │              │              │\n        │  ┌───────────▼───────────┐  │\n        │  │  Cross-Channel        │  │\n        │  │  Context Store        │  │\n        │  │  (SQLite)             │  │\n        │  └───────────┬───────────┘  │\n        │              │              │\n        │  ┌───────────▼───────────┐  │\n        │  │  Telnyx AI Inference  │  │\n        │  │  (context-aware       │  │\n        │  │   greeting + reply)   │  │\n        │  └───────────┬───────────┘  │\n        │              │              │\n        │     ┌────────┼────────┐     │\n        │     │        │        │     │\n        │  Email API  SMS API  Voice  │\n        └─────────────────────────────┘\n              │        │        │\n              ▼        ▼        ▼\n           Customer receives contextual\n           responses on every channel\n```\n\nThe key differentiator: when a customer switches channels (e.g., emails then calls), the AI resolves their identity, loads the full cross-channel conversation history, and generates a greeting that references their prior interaction — so they never have to repeat themselves.\n\nCopy `.env.example` to `.env` and fill in:\n\n| Variable | Type | Example | Required | Description | Where to get it | \n|---|---|---|---|---|---|\n| `TELNYX_API_KEY` | `string` | `KEY0123456789ABCDEF` | **yes** | Telnyx API v2 key | [Portal](https://portal.telnyx.com/api-keys) ·[CLI: `telnyx auth`](https://developers.telnyx.com/development/cli) | \n| `TELNYX_FROM_NUMBER` | `string` | `+15551234567` | **yes** | Telnyx phone number (SMS + Voice) | [Portal](https://portal.telnyx.com/numbers/my-numbers) | \n| `TELNYX_EMAIL_FROM` | `string` | `agent@yourdomain.com` | **yes** | Verified sender email | [Portal](https://portal.telnyx.com/email) | \n| `MESSAGING_PROFILE_ID` | `string` | `40017b7e-...` | no | Messaging profile ID | [Portal](https://portal.telnyx.com/messaging/profiles) | \n| `CONNECTION_ID` | `string` | `1494404757140276705` | **yes** | Call Control connection ID | [Portal](https://portal.telnyx.com/call-control/applications) | \n| `AI_MODEL` | `string` | `meta-llama/Llama-3.3-70B-Instruct` | no | Telnyx Inference model | [Models](https://developers.telnyx.com/docs/inference/models) | \n| `PORT` | `integer` | `5000` | no | HTTP server port | — | \n| `DB_PATH` | `string` | `conversations.db` | no | SQLite database path | — | \n\n**Agent / CLI access** — provision the resources above via the [Telnyx CLI](https://developers.telnyx.com/development/cli):\n\n```\ntelnyx auth login\ntelnyx available-phone-numbers list --country US --features sms,voice\ntelnyx number-orders create --phone-number +15551234567\ntelnyx messaging-profiles create --name \"Context Carrying Agent\"\ngit clone https://github.com/team-telnyx/telnyx-code-examples.git\ncd telnyx-code-examples/omnichannel-context-carrying-python\n\npip install -r requirements.txt\n\npython demo/demo_server.py\n```\n\nThe demo walks through \"Sarah's Booking Change\" — she emails about rescheduling, then calls and hears the AI greet her with full context from her email. No Telnyx credentials required.\n\n```\ngit clone https://github.com/team-telnyx/telnyx-code-examples.git\ncd telnyx-code-examples/omnichannel-context-carrying-python\n\ncp .env.example .env    # ← fill in your credentials\npip install -r requirements.txt\npython app.py           # starts on http://localhost:5000\n```\n\nRegister a customer and test the flow:\n\n```\n# Register a customer identity\ncurl -X POST http://localhost:5000/customers/register \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"id\": \"cust_sarah_chen\",\n    \"name\": \"Sarah Chen\",\n    \"email\": \"sarah@example.com\",\n    \"phone\": \"+15551234567\"\n  }'\n```\n\n1. \nExpose your local server: \n\n```\nngrok http 5000\n```\n\n2. \nCopy the HTTPS URL and configure in [Telnyx Portal](https://portal.telnyx.com) :\n  - **Call Control Application** → Webhook URL →`https://<id>.ngrok.io/webhooks/voice`\n  - **Messaging Profile** → Inbound Webhook URL →`https://<id>.ngrok.io/webhooks/messaging`\n  - **Email** → Inbound Webhook URL →`https://<id>.ngrok.io/webhooks/email`\n\nRegister a customer identity for cross-channel resolution.\n\n```\ncurl -X POST http://localhost:5000/customers/register \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"id\": \"cust_001\", \"name\": \"Sarah Chen\", \"email\": \"sarah@example.com\", \"phone\": \"+15551234567\"}'\n```\n\nList all registered customers.\n\n```\ncurl http://localhost:5000/customers\n```\n\nView cross-channel context for a customer.\n\n```\ncurl http://localhost:5000/customers/cust_001/context\n```\n\nView all cross-channel conversation history, grouped by customer.\n\n```\ncurl http://localhost:5000/conversations\n```\n\nTrigger the full scripted demo journey (demo server only).\n\n```\ncurl -X POST http://localhost:5555/demo/journey\n```\n\nHealth check endpoint.\n\n```\ncurl http://localhost:5000/health\n```\n\nReceives [Telnyx Email](https://developers.telnyx.com/docs/email) webhook events. On `email.received`: resolves customer identity by email, stores the message, and triggers AI-generated reply in a background thread.\n\nReceives [Telnyx Call Control](https://developers.telnyx.com/docs/voice/call-control) webhook events. On `call.initiated` (incoming): resolves customer by phone and answers. On `call.answered`: loads cross-channel history and generates a contextual greeting. On `call.gather.ended`: processes customer speech with full context.\n\nReceives [Telnyx Messaging](https://developers.telnyx.com/docs/messaging) webhook events. On `message.received` (inbound): resolves customer by phone, stores message, and triggers AI reply with cross-channel context.\n\n```\npython -m pytest smoke_test.py -v\n```\n\n| Issue | Cause | Fix | \n|---|---|---|\n| `401 Unauthorized` | Invalid API key | Verify `TELNYX_API_KEY` in`.env` matches your key in the[Portal](https://portal.telnyx.com/api-keys) | \n| Email not sending | Sender not verified | Verify your email domain in the [Telnyx Email Portal](https://portal.telnyx.com/email) | \n| Call not connecting | Invalid CONNECTION_ID | Verify your Call Control Application in the [Portal](https://portal.telnyx.com/call-control/applications) | \n| No contextual greeting | Customer not registered | Register the customer with matching email/phone via `POST /customers/register` | \n| Webhook not received | Server not publicly reachable | Expose with ngrok and set webhook URLs in Portal | \n| Unknown customer on inbound | Email/phone not in registry | Ensure the customer's email/phone matches their registration | \n\nThis example is part of the [Telnyx Code Examples](https://github.com/team-telnyx/telnyx-code-examples) catalog.\n\n- **Agent signup** :[telnyx.com/agent-signup.md](https://telnyx.com/agent-signup.md) — automated account provisioning via agent mail\n- **Agent CLI** :[github.com/team-telnyx/ai/tree/main/cli](https://github.com/team-telnyx/ai/tree/main/cli)\n- **LLM-optimized docs** :[`llms-full.txt`](https://developers.telnyx.com/llms-full.txt)\n- **Example index** :[`llms.txt`](https://raw.githubusercontent.com/team-telnyx/telnyx-code-examples/main/llms.txt)", "url": "https://wpnews.pro/news/ai-agent-that-carries-context-across-email-voice-and-sms", "canonical_source": "https://github.com/team-telnyx/telnyx-code-examples/tree/main/omnichannel-context-carrying-python", "published_at": "2026-10-08 19:03:55+00:00", "updated_at": "2026-10-08 19:17:56.368779+00:00", "lang": "en", "topics": ["ai-agents", "ai-products", "developer-tools", "artificial-intelligence"], "entities": ["Telnyx", "Flask", "Python", "SQLite", "Telnyx AI Inference", "Telnyx Email API", "Telnyx Messaging API", "Telnyx Call Control API"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/ai-agent-that-carries-context-across-email-voice-and-sms", "markdown": "https://wpnews.pro/news/ai-agent-that-carries-context-across-email-voice-and-sms.md", "text": "https://wpnews.pro/news/ai-agent-that-carries-context-across-email-voice-and-sms.txt", "jsonld": "https://wpnews.pro/news/ai-agent-that-carries-context-across-email-voice-and-sms.jsonld"}}