# SMS

It's common to want customers to text your agent. For instance, a customer texts your support number "What is your return policy?", and the agent answers by SMS. The `telnyx` connector does this on your own Telnyx number.

## Answer by SMS

Add the `telnyx` connector to your agent:

```yaml title="agents/support/agent.yaml"
name: support
mode: text
llm: llm-smart
connectors:
  - name: telnyx
    connection: acme-sms # the label of your Telnyx connection
```

You need three things from Telnyx: an API key, a number with messaging in E.164, and your account's public key. The public key is under **Keys & Credentials > Public Key** in the Telnyx portal. Setup takes four steps:

1. **Point Telnyx at Stream**

   At Telnyx, set the webhook URL of your number's messaging profile to `$STREAM_ACCELERATION_URL/v1/connectors/events/telnyx/<profile ID>`. `$STREAM_ACCELERATION_URL` is your router's URL. A profile ID looks like `0f3c5e2a-1b2c-4d5e-8f90-123456789abc`, and the first call in [With the API](#with-the-api) finds it. The URL applies to every number on that profile.

2. **Save your Telnyx account**

   Give Stream the profile ID and the public key:

   ```sh
   curl -fsSL https://getstream.io/cli/beta/install.sh | bash # the agents commands are in the beta CLI
   echo "$TELNYX_PUBLIC_KEY" | getstream agents connectors client set telnyx --provider-app-id "$TELNYX_PROFILE_ID" --signing-secret -
   ```

   The CLI prints `Saved the provider app for telnyx`.

3. **Connect the number**

   Create the connection with your number and the API key:

   ```sh
   echo "$TELNYX_API_KEY" | getstream agents connections create telnyx --label acme-sms --input phone_number=+12025550100 --token -
   ```

   The CLI prints `Connected: telnyx / acme-sms`, with the connection's id.

4. **Sync the agent**

   ```sh
   getstream agents sync support
   ```

From a phone, text "What is your return policy?" to your Telnyx number. The reply comes back by SMS, from the same number.

### In the Dashboard

Steps 2 and 3 work in the Dashboard too. In the [Stream Dashboard](https://getstream.io/signin/), go to **Agents > Library > Connectors** and open **Telnyx**.

1. Click **Set OAuth client**. The dialog has two fields: fill **Provider app ID** with the profile ID and **Signing secret** with the public key, then click **Save client**.
2. Click **Create connection**. **Owner** starts on **Signed-in user**: pick **App**. Type `acme-sms` in **Label**, your number in **phone_number** and the API key in **Token**, then click **Create connection**. The connection's page opens, and the connection is connected.

## US phones need 10DLC

>
> **Warning:** A reply to a US phone needs your number in an approved 10DLC campaign at Telnyx, in the account that holds the number. Without one, the agent answers, but Telnyx doesn't deliver the text.
>

Telnyx explains the registration in [Getting Started with 10DLC](https://developers.telnyx.com/docs/messaging/10dlc/quickstart), and [10DLC](https://getstream.io/agents/docs/telephony/10dlc/) explains what it is.

Replies to a phone in Canada are delivered without a 10DLC campaign.

## Conversations

- Each phone is one conversation. The agent reads the earlier texts from that phone.
- Telnyx answers STOP, START and HELP, not the agent.
- After STOP, the person gets no reply until they text START.

## Remind by SMS

The agent can remind a customer later, by SMS. Text "Remind me in 2 minutes to check my order status". The agent confirms, and about 2 minutes later the reminder arrives by SMS, once.

Reminders need `scheduling` on, so create `support-sms` with the last call in [With the API](#with-the-api) instead of syncing `agent.yaml`. One connection serves one agent, so delete a synced `support` first.

A text has no time zone, so on a customer's first reminder the agent asks for their city and works out their time zone from it. We recommend `llm-smart` for reminders.

## With the API

Your server can do the setup instead of the CLI. First, find your number's messaging profile at Telnyx:

```bash
curl -g -H "Authorization: Bearer $TELNYX_API_KEY" \
  "https://api.telnyx.com/v2/phone_numbers?filter[phone_number]=%2B12025550100"
```

Write the number's `+` as `%2B`. Telnyx returns the profile ID as `messaging_profile_id`. Set it as `PROFILE_ID`, then point the profile's webhook URL at Stream:

```bash
curl -X PATCH "https://api.telnyx.com/v2/messaging_profiles/$PROFILE_ID" \
  -H "Authorization: Bearer $TELNYX_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"webhook_url\": \"$STREAM_ACCELERATION_URL/v1/connectors/events/telnyx/$PROFILE_ID\"}"
```

Then save your Telnyx account and create the connection. `$SERVER_TOKEN` is a [server token](https://getstream.io/agents/docs/auth/):

```bash
curl -X PUT "$STREAM_ACCELERATION_URL/v1/agents/connectors/telnyx/oauth-client" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"provider_app_id": "<profile ID>", "signing_secret": "<public key>"}'

curl -X POST "$STREAM_ACCELERATION_URL/v1/agents/connections" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"connector_id": "telnyx", "owner": {"type": "app"}, "label": "acme-sms", "inputs": {"phone_number": "+12025550100"}}'

curl -X PUT "$STREAM_ACCELERATION_URL/v1/agents/connections/$CONNECTION_ID/credentials" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"expected_revision": 1, "values": {"token": "<Telnyx API key>"}}'
```

`$CONNECTION_ID` is the `id` the second call returns. After the third call, the connection is `connected`.

For [reminders](#remind-by-sms), create the agent with this call. Put the connection's `id` in `connection_id`:

```bash
curl -X POST "$STREAM_ACCELERATION_URL/v1/agents/configs" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "support-sms", "mode": "text", "llm": "llm-smart",
       "instructions": "Answer briefly. When asked for a reminder, schedule it with schedule_task, then confirm briefly.",
       "scheduling": {"enabled": true},
       "connectors": [{"name": "sms", "connector_id": "telnyx", "connection": {"type": "fixed", "connection_id": "<connection ID>"}, "tools": []}]}'
```

## When a text gets no answer

| What you see                                   | Why                                                      | What to do                                                                                  |
| ---------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| The agent gets nothing                         | The profile's webhook URL points somewhere else          | Set it again, as in step 1                                                                  |
| The router answers Telnyx `401`                | The signing secret is not your account's public key      | Save the public key again, as in step 2                                                     |
| The agent answers, but a US phone gets nothing | Telnyx error `40010`: the number is in no 10DLC campaign | Get an approved 10DLC campaign at Telnyx. See [US phones need 10DLC](#us-phones-need-10dlc) |
| A person gets no reply after STOP              | The person opted out                                     | The person texts START                                                                      |

## Going further

- [Channels](https://getstream.io/agents/docs/connectors/channels/): Every channel, what it needs, and which one to start with.
- [iMessage](https://getstream.io/agents/docs/connectors/imessage/): Answer over iMessage on your own Linq line.
- [Slack](https://getstream.io/agents/docs/connectors/slack/): Answer in Slack threads as your workspace's bot.
- [10DLC](https://getstream.io/agents/docs/telephony/10dlc/): What 10DLC is, and why US numbers need it.

---

For the most recent version of this documentation, visit [https://getstream.io/agents/docs/connectors/sms/](https://getstream.io/agents/docs/connectors/sms/).