Phone
Voice in and out, and SMS. Not phone calls.
What it does
Speech recognition and synthesis run self-hosted, routed per language across providers, with a turn-taking layer that handles interruption and sentence-level streaming so a spoken exchange does not feel like a walkie-talkie. A separate SMS path is implemented behind a feature flag for text messaging.
Why it matters
Voice is where the "assistant" framing either becomes real or falls apart, and latency is the whole game. Self-hosting speech means the round trip is not at the mercy of a third-party queue.
How it works
Speech runs self-hosted by default
Recognition and synthesis run as their own containers, with per-language provider routing for languages the local models handle poorly.
Turn-taking is explicit
A turn gate and sentence chunker manage interruption and streaming, rather than waiting for a full response before speaking.
Telephony is SMS-only and off by default
The SMS path is built but gated behind a flag and requires a carrier account. Voice calling was explicitly out of scope, and we have not built it.
Questions
- Can my agent answer the phone?
- No. There is no inbound or outbound calling. Voice works in the browser; telephony is SMS-only and currently gated off.
- Which languages does speech support?
- A broad set, with routing to different providers per language, including a dedicated provider for Indic languages where the general models underperform.
The rest of the bag
AccessControl
Per-document permissions that filter answers, not just pages.
Policy resolution is cached per session for speed; a permission change propagates on cache invalidation rather than instantly on every in-flight request.
Docs
A folder tree the agent reads, and a config file it obeys.
Extraction covers PDFs, spreadsheets and transcripts. Exotic binary formats are not parsed.
Events
A durable ledger of what agents did, and why.
The in-process event bus is a single-node emitter, not a distributed broker. The durable cross-agent record is a separate Postgres task ledger.
That was step 1 of 6: a request arrives. Next, the subdomain is the isolation boundary, so the request resolves to one workspace, one database, and one question of whether it is even in scope.