AgentStream: what to use when
Short chooser for connecting Voice AI over Exotel AgentStream.
There are two control models:
Model | How call logic is defined | Typical entry |
|---|---|---|
Flow (App Bazaar) | Dashboard applets (Voicebot, Stream, Connect, Passthru, Gather, Greeting) | Exophone → Appbazaar flow, Voicebot applet or Passthru/ Connect Applet with Url |
ExoML (Programmable Voice APIs) | Your code reacts to gRPC leg events and issues leg actions (start_stream, start_say, start_play, hangup, bridge, …). No App Bazaar flow required. | Number attached to gRPC endpoint (inbound), or POST /legs (outbound) |
Your bot WebSocket (AgentStream) is the same either way. Choose the telephony control plane, not a different bot protocol.
Quick chooser
You need… | Use |
|---|---|
Outbound: answer → bot only | |
Outbound: answer → bot with custom routing logics via applets: Voicebot applet and then / IVR / greeting / DTMF / agent handoff via connect applet in Exotel | |
Outbound or inbound: full runtime control in code, per-call stream URL, parallel greeting while bot connects | |
Inbound: dashboard flow with Voicebot applet | Assign virtual number (Exophone) to an App Bazaar flow that includes Voicebot applet |
Inbound: no flow — events to your app, you drive the call | Attach virtual number to a gRPC endpoint (ExoML / Programmable Voice) |
Outbound
1. Connect Voice AI API — simplest outbound
Docs: Connect Voice AI API
What happens: Your API dials the customer. On answer, Exotel opens bidirectional WSS to StreamUrl.
Use when:
- Campaigns, surveys, reminders — bot is the whole experience
- No IVR, no compliance applet, no agent transfer in Exotel
- Fixed bot URL is fine in the request (StreamUrl + StreamType=bidirectional)
Not for: Menus, disclosure before bot, bot→human, or per-leg programmable actions.
2. Connect Voice AI with Flow API — outbound + App Bazaar journey
What happens: Same connect call, but Url points at an App Bazaar flow. After answer, applets run. When the flow hits Voicebot / Stream, Exotel opens WSS. Stream URL is configured in the applet, not in the API body.
Use when:
- Compliance greeting → bot
- IVR / DTMF → bot
- Bot → Connect (human) or Passthru (your system)
- Unidirectional Stream for assist / transcription
Not for: Pure “answer → bot” (use Connect Voice AI), or code-owned per-leg control (use ExoML).
Common flow patterns: Greeting → Voicebot · Gather → Voicebot · Voicebot → Connect · Voicebot → Passthru
3. ExoML (Programmable Legs) — outbound in code
What happens: You POST /legs to dial the customer, receive events on your gRPC leg_event_endpoint, then issue leg actions yourself (e.g. start_stream, optional start_say / start_play).
Use when:
- Stream URL / routing decided per call at runtime
- Parallel filler while bot connects (sales / collections “instant feel”)
- You want application-owned call logic, not a dashboard flow
Scenario | Pattern |
|---|---|
Bot-first / tech support | leg_answered → start_stream |
Sales / collections / CC simulation | leg_answered → start_stream + short start_say / start_play → on stream_started → stop_say / stop_play |
Inbound
Inbound has two separate paths. Do not mix them with the same mental model.
A. Flow-based inbound (App Bazaar + Voicebot applet)
What happens: Customer dials your Exophone. The number is linked to an App Bazaar flow. Applets execute in the dashboard-defined order. Voicebot opens bidirectional AgentStream to your bot.
Use when:
- You want visual / applet-based journeys (Voicebot, greeting, IVR, bot, agent handoff)
- Same patterns as Connect-with-Flow outbound, but the customer dials in
Customer → Exophone → App Bazaar flow → Voicebot → WSS ↔ bot
Setup: Procure Exophone → assign Voice URL / flow → include Voicebot (and optional Connect / Passthru / Gather).
B. ExoML programmable inbound (no App Bazaar flow)
What happens: Customer dials your Exophone. The number is attached to a gRPC endpoint (Programmable Voice / Legs), not to an App Bazaar flow. Exotel pushes leg events to your gRPC service. Your application is the flow — you answer/control the leg with leg actions (start_stream, say, play, gather, bridge, hangup, …).
Use when:
- Call logic must live entirely in code
- Per-call dynamic stream URL, A/B routing, CRM-driven branching
- Same ExoML action model as outbound Legs (inbound or outbound legs)
Setup: Implement gRPC event endpoint → register it → attach Exophone to that gRPC endpoint → on inbound events, issue leg actions.
ExoML inbound does not require a Voicebot applet or App Bazaar flow. The programmable “flow” is the sequence of leg actions your service sends in response to gRPC events.
Side-by-side
| Connect Voice AI | Connect + Flow | ExoML (Legs) | Inbound Flow + Voicebot | Inbound ExoML |
|---|---|---|---|---|---|
Direction | Outbound | Outbound | Outbound and inbound | Inbound | Inbound |
Control plane | Single connect API | App Bazaar applets | gRPC events + leg actions | App Bazaar applets | gRPC events + leg actions |
App Bazaar flow | No | Yes | No | Yes | No |
Where WSS URL is set | API StreamUrl | Voicebot/Stream applet | start_stream action | Voicebot/Stream applet | start_stream action |
Parallel greeting while bot warms | Bot-owned | Flow Play applet | start_say / start_play + stop on stream_started | Bot-owned | Same ExoML say/play pattern |
Best for | Simple outbound bot | Multi-step outbound | Code-first, dynamic control | Dashboard inbound journeys | Code-first inbound |
Decision tree
Same bot, four front doors
Entry | Who dials | Control | Who configures WSS |
|---|---|---|---|
Connect Voice AI | Your API | Connect API | StreamUrl in API |
Connect + Flow | Your API | App Bazaar | Voicebot/Stream applet |
ExoML outbound | Your API (POST /legs) | gRPC + leg actions | start_stream body |
Inbound Flow | Customer | App Bazaar | Voicebot/Stream applet |
ExoML Inbound | Customer | gRPC + leg actions | start_stream body |
References
- Connect Voice AI APIConnect Voice AI API
- Connect Voice AI with Flow APIConnect Voice AI with Flow API
- Programmable Voice APIs with AgentStreamProgrammable Voice APIs with AgentStream (ExoML)
- ExoML — IntroductionExoML — Introduction
- Implementing Your gRPC Endpoint for Real-Time Call EventsgRPC endpoint for real-time leg events