DEV Community

anusha
anusha

Posted on

I Built a Bot That Attends Meetings I Can't Make, and I Control It by Text

Every calendar has a collision in it somewhere. Two meetings at the same time, a dentist appointment that ran long, a train with no signal for the first ten minutes of a standup.

The usual fix is an apology message and a request for notes afterward. I wanted something better: text a link, and a bot goes in my place.

I built a Node.js Telnyx code example that does exactly that. You send a meeting link to a Telnyx number. A bot joins the meeting, posts a note in the chat explaining who it is, takes notes, and texts you a TL;DR when the meeting ends.

The code example:

https://github.com/team-telnyx/telnyx-code-examples/tree/main/join-meeting-by-sms-nodejs

The video walkthrough:

https://youtu.be/cQMwlgGuU5E

The Use Case

The interaction is a single text:

I can't join this meeting: https://meet.google.com/abc-defg-hij.
Join as my bot, and send me a TL;DR when it ends.
~~~

A moment later a reply arrives:

~~~plaintext
On it. Your bot is joining now. I will text you when it is in
and send a TL;DR after the meeting.
~~~

In the meeting, a new participant appears with the bot's name and posts a chat message telling everyone it is taking notes on someone's behalf. When the meeting ends, a second text arrives with the summary.

The phone is the interface because it is the one thing you have when you cannot get to a laptop.

## What The Example Uses

The example runs as a small Express server and uses two Telnyx products with one API key:

- Telnyx Messaging to receive the inbound text and send the replies
- Telnyx Meeting Bot to join the call, capture the transcript, and generate a summary
- Telnyx webhooks with Ed25519 signatures to authenticate inbound messages

There is no separate transcription service and no separate summarization step in the code. The session is created with `summarize_on_end: true`, and Telnyx produces a summary artifact when the meeting is over.

## Keeping It Safe

A bot you can summon by text is also a bot someone else might try to summon, so the example has two guards.

First, the webhook verifies the Telnyx signature over the raw request body. A request that does not carry a valid signature gets a `401` and nothing else happens.

Second, the handler only acts on texts from one configured number, the owner's mobile. Messages from anyone else are ignored.

~~~js
if (from !== OWNER_PHONE_NUMBER) {
  return;
}
~~~

That is enough for a personal tool. It is not an access-control system, and a team version would need real per-user rules.

## Sending The Bot In

The core of the example is one API call:

~~~js
await client.meetingSessions.create({
  meeting_url: meetingUrl,
  bot_name: BOT_NAME,
  chat_on_enter: CHAT_ON_ENTER,
  summarize_on_end: true,
  idempotency_key: `join-meeting-by-sms:${messageId}`,
});
~~~

The `idempotency_key` solves a quiet problem. Telnyx retries webhooks that do not get a quick success response, and a retry must not put a second bot in the meeting. Because the key comes from the inbound message ID, a replayed message resolves to the session that already exists.

The `chat_on_enter` message matters for a human reason. A silent unknown participant is unsettling. A bot that introduces itself is a much better guest.

## Telling You What Is Happening

Joining a meeting is not instant. A host may need to admit the bot from a waiting room, and a host may decline. The server polls the session every few seconds and texts you on each change:

~~~json
waiting_for_admission -> a host needs to admit your bot
active                -> your bot is in and taking notes
admission_denied      -> the host did not admit your bot
failed                -> your bot could not join
~~~

Each status is texted once, so you are not flooded while waiting.

## Getting The TL;DR

When the session ends, the server asks for the session's artifacts and picks out the one with type `summary`. Summary generation is asynchronous, so the server waits for it to complete, up to ninety seconds, then texts it to you.

If the summary is not available, you get a clear fallback message. A silent failure would be worse than an honest one.

## Optional Extras

Two environment variables make the bot feel more like a participant:

- `ASSISTANT_ID` attaches a Telnyx AI Assistant so the bot can speak and answer questions in the meeting
- `CAMERA_IMAGE_URL` sets a static image as the bot's camera tile

## Running The Example

~~~bash
git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/join-meeting-by-sms-nodejs
cp .env.example .env
npm install
npm start
~~~

Add your API key, public key, Telnyx number, and your own mobile number to `.env`. Expose the server with a tunnel, point your Messaging Profile's inbound webhook at `/webhooks/sms`, and text your number a link.

This puts a real bot in a real meeting and sends real SMS, so try it on a meeting you control first.

## What I Would Change For Production

This is a pattern, not a product. Before using it for real I would:

- Store watched session IDs in a database so a restart does not drop the status texts
- Always disclose the bot in chat, because people deserve to know when a meeting is being summarized
- Register the sending number for US SMS with 10DLC or toll-free verification
- Replace the single owner number with per-user rules
- Plan for meeting platforms where chat is not supported

## Frequently Asked Questions

### Which meeting platforms work?

The example recognizes Google Meet, Zoom, Microsoft Teams, and Webex links.

### Can the bot talk?

Yes, if you attach a Telnyx AI Assistant with `ASSISTANT_ID`.

### What if the host never admits the bot?

You get a text saying the bot is at the waiting room, and another if the host denies admission.

### Can someone else text the bot into a meeting?

No. Only the configured owner number is accepted, and webhooks without a valid Telnyx signature are rejected.

## First comment

Demo video: https://youtu.be/cQMwlgGuU5E

Code: https://github.com/team-telnyx/telnyx-code-examples/tree/main/join-meeting-by-sms-nodejs
Enter fullscreen mode Exit fullscreen mode

Top comments (0)