Calls
Web calls and security
Use a browser microphone while the agent and workspace stay on the runtime host.
Three ways a browser call travels
| Delivery | How you get it | Signaling | Media path | Time limit |
|---|---|---|---|---|
| This computer | sleeptalk --web on the runtime host | Package-owned service on 127.0.0.1 | Local WebRTC. No STUN or TURN. | None |
| Your tailnet | Agent link or --tailnet when the profile uses the tailnet | The same local service, published with tailscale serve | Direct between tailnet addresses. No relay or TURN. | None |
| Hosted relay | Agent link (the default for links sent from chat) | Cloudflare Worker at call.sleep.talk, one room per call | Direct first, with Cloudflare TURN when needed | 30 minutes |
All three end after 90 seconds of silence. A detected embedded browser, such as an in-app browser, is relay-required on the hosted service: setup fails if TURN credentials are unavailable. Open the link in an external browser instead.
Start a call
On the runtime host, run sleeptalk --web from your workspace. Allow microphone access and start the call. The launcher opens a localhost URL, which does not work on your phone.
For another device, ask your agent for a call link. Open it yourself on the device you want to speak from. Keep the runtime host online throughout the call.
During a call
The call page has a Stop button (key: S) that ends the current reply and clears pending output. The gear menu holds these controls:
| Control | Choices |
|---|---|
| Playback speed | 0.5x, Normal, 1.25x, 1.5x |
| Tool narration | Narrated, Silent, Keyboard sounds |
| Response length | Full, Summarized |
| Voices | The live provider's voices, limited to the call's language |
| Advanced settings | Offers an Open settings link to the full settings page |
Choosing a voice tries it first, switches only if the provider accepts it, and saves it to the profile. Switching providers is not offered in a call, because a new provider needs a key and keys never enter a call.
Advanced settings asks the runtime host for a single-use settings link, and the call page shows Open settings. Tap it to open the full settings page on your phone. The page reaches the host through a sealed channel; the hosted relay sees only ciphertext. Changes there apply to your next call. If the hosted service can't be reached, the host opens the page in its own browser instead. If it has no browser either, the call page tells you to run sleeptalk settings on that computer.
The transcript shows each spoken sentence once. A reply is not repeated as a second block when the turn completes.
How the connection works
- The runtime creates a short-lived call ticket.
- The browser redeems the ticket and receives its own signaling credential.
- The browser and runtime exchange connection offers and network candidates through the rendezvous service.
- WebRTC connects the browser and runtime. Audio flows over media tracks; transcripts and agent state flow over a WebRTC data channel.
- The runtime sends speech to your configured providers and passes requests to your agent.
Rendezvous is the meeting point for connection setup. It relays signaling messages only. It does not run your agent, act as a speech provider, or carry transcripts.
WebRTC carries audio and the display data channel between the browser and runtime. ICE selects a working network path. STUN helps discover reachable addresses; TURN relays traffic when a direct connection cannot be established.
Calls over your tailnet
When the host and the device you call from share a Tailscale network, calls can skip the hosted relay entirely: no TURN, no time limit. Setup, the profile setting, and the errors are on Calls over your tailnet.
Hosted relay limits
- A call is limited to 30 minutes. The page warns 2 minutes and 30 seconds before the end, then explains why the call ended.
- Creating a link costs nothing and issues no TURN credential. The relay allowance is charged, and TURN credentials are issued, only when a browser redeems the link.
- Each installation may create a limited number of links per minute and per day and hold three concurrent calls. Installations and source networks also have daily relay budgets and per-minute rate limits.
When a limit is reached, the service refuses new links or new relay credentials with a stable error. Local and tailnet calls do not use these budgets.
What protects the call
- Bounded invitations. Call links are single-use and expire within five minutes if unused.
- Separate credentials. The runtime and browser authenticate signaling with distinct keys. The browser never receives your speech-provider key.
- Fragment-based invitation. The invitation secret is in the URL fragment, which is not part of the initial page request. The call page submits it when redeeming the ticket.
- Encrypted media and data. WebRTC encrypts audio and the data channel between the browser and runtime. A TURN relay forwards encrypted packets. Transcripts never pass through the hosted relay.
- Hosted issuance controls. Installation grants, link limits, concurrent-call limits, relay budgets, and revocation restrict link creation and TURN issuance.
- Tailnet membership. On a tailnet call, only tailnet members can reach the host name at all.
The encryption boundary ends at the runtime, which must process the audio. Your STT provider receives audio, your agent's model provider receives requests and context, and your TTS provider receives text to speak. Network services can still observe metadata such as IP addresses and timing.
The hosted service serves the call page and the phone settings page. Their end-to-end protections hold while it serves this repository's code. See SECURITY.md and the WebRTC security architecture.
Settings links are separate
A settings link opens the settings page on your phone; it is not a call link. You get one from sleeptalk settings --phone, from an agent (host settings-link, or host input link when it needs a key), or from Advanced settings during a call. The page opens a sealed channel to the runtime host. Every request, key, voice, check result, icon, voice sample, and Discord detail travels inside it, and the relay forwards only ciphertext. The link is single use and expires in ten minutes if nobody opens it. A settings session ends after 30 minutes idle.
Open settings links yourself. Do not paste keys into the agent's chat or share the link. See set up through an agent.
Current limits and recovery
These controls describe the implementation, not a completed independent security audit. Not every cellular, VPN, corporate, or restricted network has been tested. Do not assume every firewall can carry a hosted call.
If a hosted call cannot connect, open the link in an external browser, allow microphone access, and confirm that the runtime is still online. An expired or used link needs a new one. End the call from the browser or with sleeptalk host stop when finished. See call lifecycle and recovery.
A service halt blocks new links and new TURN issuance; it does not end media paths that are already established. Operators should read browser service operations and the connectivity design.