ONE

When an Agent Books the Room

A visitor asks to talk to a real person. The agent opens a live video room, drops their reason in it, alerts the team, and puts the room in the conversation as a card with a Join button. Here is the whole path, including what happens when the join fails.

meetings video agents chat product

Every chat agent hits the same wall. Someone types “can I just talk to a person” and the honest answer used to be a form. Leave your email. Someone will be in touch. The visitor was ready to speak right then, and the best the software could do was take a message.

The agent can now open the door itself. It calls one tool, meet_human, and a live video room appears in the conversation with a Join button on it.

What the agent actually does

The tool takes two things: a one-line reason (up to 280 characters) and the visitor’s name if they gave it (up to 60). That is the whole input. The agent is told to ask for the name first and to write the reason as the sentence a person on the team will read before joining — “pricing for 20 seats” beats “wants to talk”.

Server-side, that call creates a real video room, opens a thread beside it, writes the reason into that thread, and sends a notification to wherever the workspace already listens: the inbox, Telegram, Discord, web push. The person on the team sees “Dana wants to talk (web) — pricing for 20 seats” with a button that goes straight to the room.

Back in the conversation, the tool’s result carries the room itself, so the transcript renders a join card in the same turn. There is no second step where the agent has to remember to send a link, and no link for the visitor to chase.

The card does not turn the camera on when it appears. It is a card, not a call: the video client is not even downloaded until the visitor taps Join. A block that grabs a webcam the moment it renders is hostile, and the tool sets that explicitly rather than relying on a default.

Two more details worth naming. Ask twice in the same conversation and you get the same room back, not a second one — the room is keyed on the conversation. And when the notification fails to go out, the tool says so in its result, which means the agent tells the visitor a person may take a moment instead of promising someone is already on the way. A system that quietly claims success it did not achieve is worse than one that says nothing.

The room

The rooms are 100ms. Each join mints its own short-lived token from /api/stream/token, scoped to a role — the visitor joins as a guest, an operator can join as host. Nothing about the room is a public URL with a permanent key in it.

Two settings turn the whole thing on: an HMS access key and secret. Without them, every room request refuses and the visitor is told the site has not configured video yet. That is deliberate. Half-configured video that fails at the moment someone tries to join is worse than video that says up front it is not ready.

There is also a ceiling: ten handoff rooms per workspace per hour. It counts only the rooms this path creates, so an operator’s own scheduled rooms never cause a visitor to be turned away. Past the ceiling the answer is no, and it is only ever no. The tempting alternative — hand the eleventh visitor the newest open room so nobody hits a dead end — would seat a stranger in someone else’s live call. The agent degrades instead: it promises a follow-up.

Worth being precise, because these get conflated.

The chat handoff has no invite link at all. The room arrives as a card in the conversation, and the path behind it is a plain workspace path. Nothing is signed because nothing needs to be: the visitor never chose a destination, and the only party who can reach the room is the one already holding the conversation.

The operator-initiated invite is different. When a person on the team invites named people to a room, or schedules a webinar, each invitee gets their own signed, tracked link — a short id with a signature on it that resolves to the room and records who followed it. Those links refuse to be minted at all when the signing secret is missing, rather than falling back to an unsigned one. An invite you can forge is not an invite.

Failure is a feature, if it tells you which failure

The most useful file in this feature is nine lines long. It maps every reason a join can fail to one plain sentence:

  • The room does not exist, or it has been switched off.
  • Video is not configured for this site yet.
  • The server did not return a join token.
  • Could not reach the server. Check your connection and reload.
  • Sign in to host this room.
  • You do not have permission to host in this workspace.
  • Permissions could not be checked just now. Reload in a moment.
  • That invite link is no longer valid.
  • The room is misconfigured — the join mode is not one the server accepts.

Anything unrecognised falls back to “The room could not be joined.”

The rule behind the list is the part worth stealing: one sentence per real cause, and no “try again” on a cause that retrying cannot fix. Reloading fixes a permissions check that timed out. Reloading does not fix a room that was switched off, an invite that expired, or a site with no video credentials, and telling someone to try again in those cases wastes their time and hides the real problem from whoever could fix it.

The last three in that list are host-side, so a visitor in a chat will realistically only ever see the first four. That is not an accident either — the errors are split by who can actually be in that situation, which is why the visitor’s version never says “sign in” to a person who has no account.

You can drive the join card and the failure states on the meetings demo, and the full capability write-up is on the meetings feature page.

The agent does not attend the meeting. It does not pick a time, sit in the call, or take notes on your behalf. It does the one thing that was missing: it gets a person who wants to talk into a room with a person who can help, in the time it takes to ask.