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:

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 three 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 Set it up from your backend finds it. The URL applies to every number on that profile.
  2. Save your Telnyx account. On the Stream Dashboard, open Library > Connectors, then Telnyx. Choose Set OAuth client. Fill Provider app ID with the profile ID and Signing secret with the public key, then choose Save client.
  3. Create the connection. On the same page, choose Create connection. Choose App as the Owner. Enter acme-sms as the Label, your number as phone_number, such as +12025550100, and the Telnyx API key as the Token. Choose Create connection.

Sync the agent:

curl -fsSL https://getstream.io/cli/beta/install.sh | bash # the agents commands are in the beta CLI
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.

US phones need 10DLC

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, and 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 Set it up from your backend 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.

Set it up from your backend

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

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:

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:

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, create the agent with this call. Put the connection's id in connection_id:

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
A person gets no reply after STOP The person opted out The person texts START

Going further