Governors and Privacy
Two governors
Section titled “Two governors”Both governors end a call gracefully - the caller hears a goodbye rather than a sudden drop.
StandIn-side (tier limits)
Section titled “StandIn-side (tier limits)”When a StandIn tier limit is reached (a sandbox/free daily cap or a subscription max-minutes governor), StandIn sends an assistant.say with the goodbye text. The bridge speaks it and StandIn tears the call down. ElevenLabs is not involved in the timing.
Bridge-side (MAX_CALL_MINUTES)
Section titled “Bridge-side (MAX_CALL_MINUTES)”Because ElevenLabs knows nothing about your budget, the bridge can enforce its own hard cap. Set MAX_CALL_MINUTES (fractional allowed; 0 disables it). At call start the bridge arms a timer; on expiry it flushes playback, speaks GOODBYE_TEXT, and ends the call with reason time-limit.
Stale-call reaper (STALE_CALL_REAPER_SECONDS)
Section titled “Stale-call reaper (STALE_CALL_REAPER_SECONDS)”Not every ending has someone to say goodbye to. A worker can authenticate, send session.start, and then never reach a live relay - a wedged agent connect, a call it never completes. By then the pre-start timeout has defused, and the dead-peer timer only fires on silence, so a worker that keeps heartbeating would hold the call id and a connection slot indefinitely. Every STALE_CALL_REAPER_SECONDS (default 120, 0 disables) the bridge ends such a call with reason no-answer, through the same teardown a caller hangup takes: the worker is told, both sockets close, the registry entry is evicted.
The eviction is the point. Freeing the registry slot without closing the sockets would reopen the connection cap while the leaked call is still up and still billing.
Unlike the vision features this one is on by default, and that does not break the “a default must not spend money” rule: the reaper makes no provider call at all. It only frees local resources.
Deterministic goodbye
Section titled “Deterministic goodbye”Set EL_TTS_VOICE_ID and the goodbye is synthesized as the exact GOODBYE_TEXT via standalone TTS - the agent is muted while it plays, and the real audio duration is used for the grace. Without it, the goodbye is delegated to the agent via a user_message, and GOODBYE_GRACE_MS covers the unknown duration.
Recording gate
Section titled “Recording gate”StandIn reports the Teams recording state (recording.status). The bridge honors it:
- Transcripts are never logged or persisted unless
LOG_TRANSCRIPTS=trueand recording isactive. - Vision path 1 (uploading the raw frame to ElevenLabs) is refused unless recording is
active. - Video frames are buffered in memory only and dropped at teardown.
- Ambient vision pushes are held back until recording is
active(AMBIENT_VISION_REQUIRE_RECORDING, defaulttrue). Note what the gate does and does not cover: it gates delivery, not buffering - frames arriving before recording starts still sit in memory as the latest-per-source buffer until the call ends.
Vision path 2 descriptions are ungated by design - see the trade-off in Vision and Tools.
Data residency and retention
Section titled “Data residency and retention”Caller audio, transcripts, and any vision descriptions transit ElevenLabs’ cloud and are retained per the agent’s settings. For deployments that must not retain caller data with a third party:
- Enable ElevenLabs zero-retention on the agent (or the account-level equivalent).
- Pin
EL_HOSTto the region that matches your residency requirement. - Disclose that an AI is on the call - a spoken
EL_FIRST_MESSAGEis the simplest way, and follows most tenants’ call-recording/AI-disclosure policy.
This is the same “customer data leaves the tenant” conversation as any hosted agent; surface it to your stakeholders explicitly.