Skip to main content

ACS Module

Run automated phone calls on Azure Communication Services with TTS prompts and DTMF capture.

The ACS Module drives outbound and inbound voice calls through Azure Communication Services Call Automation. Each call step on the AcsPhone Channel starting the call, speaking a synthesized message, collecting a keypad digit, and hanging up is handled by this Module, so you can build IVR menus, outbound notifications, and voice surveys in the same BPMN editor you use for chat and Slack workflows. It requires Environment configuration: an Azure Communication Services connection and a linked Cognitive Services resource so prompts can be synthesized with Azure neural voices natively inside ACS. OpenAI / Resemble.ai streaming voices and a full conversational agent are rolling out over ACS bidirectional media streaming.

How it works​

When a call is started or received on the AcsPhone Channel, the engine creates a Session and starts a Token through the Process. The live call stays bound to the Session for its entire lifetime, so every Task can address it.

The Process begins at its ACS call start: the Module records the call on the Session, hands the flow {call} (who is calling, the number they called, the call id, the language) and waits until ACS reports the call connected, so the first prompt is never played too early. Each OutputTask converts its message to speech through the configured TTS provider and plays the audio over the call. Each InputTask speaks a prompt and then listens for a keypad (DTMF) digit the caller's digit is written into the configured variable when it arrives. At the End Event the Module hangs up the call.

If a Session ends abnormally before reaching the End Event, the Module automatically hangs up the dangling call so the Azure connection does not stay open and keep billing. No configuration is needed to enable this behavior.

Configuration​

The ACS Module is configured per Environment each Environment supplies its own Azure Communication Services credentials and TTS settings. Set these values in the Module's Environment configuration. The settings are grouped the same way as the configuration form: Connection reaches Azure Communication Services, Text-to-Speech selects how prompts are synthesized, Media Streaming applies only to the streaming voice agent, and Voice Agent configures the optional conversational agent.

Connection​

FieldTypeRequiredDescription
ACS Connection StringstringYesAzure Communication Services connection string (endpoint=https://...;accesskey=...). The single credential the Module uses to reach Azure.
Callback Base URLstringYesPublicly reachable base URL where Azure Communication Services delivers call event notifications (e.g. https://myapp.azurewebsites.net).
Default LanguagestringNoDefault language for call interactions when a Task doesn't override it. One of it-IT, en-US, en-GB, de-DE, fr-FR, es-ES. Default: it-IT.
Cognitive Services EndpointstringNoAzure AI / Cognitive Services endpoint linked to the ACS resource (e.g. https://myresource.cognitiveservices.azure.com). Required for the Azure voice path.
warning

The Module refuses to execute any Task until the ACS Connection String is set. While it is empty, every Task on the AcsPhone Channel stops with a configuration error and the call cannot proceed.

Text-to-Speech​

FieldTypeRequiredDescription
TTS ProviderstringYesSpeech engine. Azure synthesizes neural voices natively inside ACS the supported path today. OpenAI / Resemble voices stream over the real-time media agent (rolling out). Default: Azure.

The settings for the selected provider appear below the TTS Provider field; the other providers' settings stay hidden.

Azure Speech settings shown when TTS Provider is Azure. The voice agent's speech recognition also uses this Speech resource.

FieldTypeRequiredDescription
Azure Speech EndpointstringNoAzure Cognitive Services Speech endpoint URL (e.g. https://italynorth.api.cognitive.microsoft.com).
Azure Speech KeystringNoAzure Cognitive Services Speech subscription key.
Azure Speech RegionstringNoAzure region where the Speech resource is deployed. Default: italynorth.
Default VoicestringNoDefault neural voice (e.g. it-IT-ElsaNeural, en-US-JennyNeural). Default: it-IT-ElsaNeural.
Audio FormatstringNoPCM audio format for synthesized speech. One of Riff24Khz16BitMonoPcm, Riff16Khz16BitMonoPcm, Riff8Khz16BitMonoPcm. Default: Riff16Khz16BitMonoPcm.

OpenAI TTS settings shown when TTS Provider is OpenAI.

FieldTypeRequiredDescription
OpenAI API KeystringYesOpenAI API key (sk-...).
ModelstringNoOpenAI TTS model. One of tts-1, tts-1-hd (tts-1-hd offers higher quality). Default: tts-1.
VoicestringNoVoice persona. One of alloy, echo, fable, onyx, nova, shimmer. Default: nova.
SpeednumberNoPlayback speed multiplier (0.25–4.0). Default: 1.0.

Resemble TTS settings shown when TTS Provider is Resemble.

FieldTypeRequiredDescription
Resemble API KeystringYesResemble.ai API token, sent as a Bearer token.
Voice UUIDstringYesUUID of the Resemble voice to synthesize with (from the Resemble dashboard).
Sample RatestringNoResemble output sample rate in Hz. One of 8000, 16000, 22050, 32000, 44100, 48000. Default: 16000.
PrecisionstringNoResemble audio sample precision. One of PCM_16, PCM_24, PCM_32, MULAW. Default: PCM_16.

Media Streaming​

These settings matter only for the streaming voice agent. Standard IVR flows can leave them at their defaults.

FieldTypeRequiredDescription
Enable Media StreamingbooleanNoTurns on bidirectional media streaming for this Environment. Needed only by the streaming voice agent. Leave it off for standard IVR flows while the media stream is open, ACS routes the call audio through it and rejects the server-side prompt playback used by the OutputTask and InputTask, so the caller hears nothing. Default: off.
Media Token TTL (seconds)integerNoLifetime of the signed token embedded in the media-streaming URL handed to ACS (10–3600). Keep it short to limit exposure if the URL leaks. Only used when Enable Media Streaming is on. Default: 30.

Voice Agent​

Optional needed only by the real-time conversational voice agent (rolling out). Leave the whole section unset for plain IVR flows. The agent listens with Azure speech recognition (reusing the Azure Speech settings above), replies through the configured LLM, and speaks with the streaming voice of the selected TTS provider.

FieldTypeRequiredDescription
STT LanguagestringNoSpeech-recognition language for the caller's voice. One of it-IT, en-US, en-GB, de-DE, fr-FR, es-ES. Falls back to the Default Language when blank.
LLM ProviderstringNoLarge-language-model backend that drives the conversation. Currently OpenAI. Default: OpenAI.
LLM ModelstringNoChat model id (e.g. gpt-4o-mini). Smaller, faster models keep per-turn latency low. Default: gpt-4o-mini.
LLM API KeystringNoAPI key for the LLM provider. Leave blank to reuse the OpenAI API Key from the Text-to-Speech settings when the LLM Provider is OpenAI.
System PromptstringNoSystem instructions that frame the agent's persona, scope, and when to end the conversation. Default: empty.
TemperaturenumberNoSampling temperature (0.0–2.0). Lower is more deterministic. Default: 0.4.
Max Tokens per TurnintegerNoCap on the length of each agent reply (16–4096 tokens). Keeps turns short and bounds cost. Default: 256.
Agent VoicestringNoVoice id for the selected TTS provider (e.g. an OpenAI voice name or a Resemble voice UUID). Blank uses that provider's configured default.
Max TurnsintegerNoHard ceiling on conversational turns before the agent ends the call (0–200). 0 = no turn limit. Default: 30.
Max Duration (seconds)integerNoHard wall-clock ceiling for the whole conversation (0–3600). 0 = no duration limit. Default: 300.
Per-Turn Timeout (seconds)integerNoHow long to wait for the caller or the model on a single turn before timing out (0–120). 0 = no per-turn timeout. Default: 20.
End IntentsstringNoComma-separated intent names the agent can call to finish the conversation (e.g. booking_complete, info_provided). Default: empty.
Handoff IntentsstringNoComma-separated intent names that end the conversation with an escalation to a human (e.g. transfer_to_agent). Default: empty.

Tasks​

AcsCallStartTask is the call's own start. OutputTask, InputTask and EndTask are channel-specific implementations for the AcsPhone Channel: they use the same Task types as the Standard Module, so the property panel in the BPMN Editor is identical to the chat versions; only the runtime behavior differs. AcsAgentConverse is an ACS-specific Task with its own property panel.

AcsCallStartTask (Channel: AcsPhone)​

Starts the Process when someone calls your Azure Communication Services number, and hands the flow the call as one variable.

Properties​

PropertyTypeRequiredExampleDescription
Call variablevariableNo{call}The variable that receives the call. Default: {call}.

Variables​

VariableExampleDescription
{call.from}+393331234567Who is calling: the phone number of a phone caller, or the ACS / Teams id of any other caller.
{call.to}+390200000000The number they called.
{call.callId}411f0b00-…The ACS call connection id.
{call.direction}inboundAlways inbound: the Module answers incoming calls.
{call.language}en-USThe Environment's Default Language. Set the Language variable to speak another language.
{call.channel}AcsPhoneThe Session's Channel (Chat in test mode).
{call.isTest}falsetrue when the start ran in the test chat.

The caller and the number called are also the Session's sender and recipient, as shown in the Sessions list.

Behavior​

  1. Checks that the Session is bound to a live call and that the ACS connection is configured.
  2. Records the call connection details and the call start time on the Session, and writes {call}.
  3. Waits until ACS reports the call connected, then moves the Token on to the first prompt.

Test mode​

Started from the test chat (or by the assistant with test data), the start writes {call} from the test data instead of a real call: from, to, callId and language (the Environment's Default Language when missing), with isTest = true, and the flow goes on at once. On any Channel other than AcsPhone and Chat the start stops the Session with error 8025 StartWrongChannel.

Processes built on the plain StartTask keep working: on AcsPhone it does the same, without {call}, and writes the Default Language into the Language variable.

Example​

A customer calls the booking line from +393331234567. The ACS call start writes {call.from} = +393331234567, waits for the call to connect, and the next OutputTask greets them with Hello! We will text the confirmation to {call.from}.

OutputTask (Channel: AcsPhone)​

Speaks a message to the caller using the configured TTS provider.

Properties​

PropertyTypeRequiredExampleDescription
Output MessagestringYesWelcome back, {userName}. Press 1 to hear your balance.The text spoken to the caller. Supports {variable} placeholders for dynamic values.

Behavior​

  1. Checks that the Session is bound to a live call, that the Output Message is non-empty, and that the ACS connection is configured.
  2. Resolves every {variable} placeholder against the current Session variables.
  3. Converts the text to audio with the active TTS provider, honoring the Voice and Language Session variables if present (otherwise falling back to the Default Language).
  4. Plays the audio to the caller over the live call.

Example​

After collecting {userName} in an earlier InputTask, an OutputTask with Output Message Welcome back, {userName}. Press 1 to hear your balance. synthesizes that line in the active language and plays it to the caller. The Token then continues to the next node.

InputTask (Channel: AcsPhone)​

Plays a prompt and waits for a keypad (DTMF) digit from the caller.

Properties​

PropertyTypeRequiredExampleDescription
Prompt MessagestringYesPress 1 for booking, 2 to cancel.Prompt spoken to the caller before digit recognition starts. Supports {variable} placeholders.
Store result instringYes{userChoice}On the AcsPhone Channel, type the variable as a {name} reference. The captured digit is written there when the caller presses a key.

Behavior​

  1. Checks that the Session is bound to a live call, that the Prompt Message is non-empty, that Store result in is a {name} reference, and that the ACS connection is configured.
  2. Resolves {variable} placeholders in the prompt and converts it to audio with the active TTS provider, honoring the Voice and Language Session variables if set.
  3. Plays the prompt and starts keypad recognition for a single digit, with a 5-second initial silence window. The caller can press a key while the prompt is still playing.
  4. The Token waits at this node; when the digit arrives, it is written into the configured variable and the Token resumes.

Example​

An IVR menu plays Prompt Message Press 1 for booking, 2 to cancel. with Store result in {userChoice}. The caller presses 1; {userChoice} now holds 1, and a downstream SwitchTask routes the Token to the booking branch.

EndTask (Channel: AcsPhone)​

Hangs up the call when the Token reaches the End Event.

Properties​

PropertyTypeRequiredExampleDescription
(none)———The EndTask has no configurable properties on the AcsPhone Channel.

Behavior​

  1. Checks that the Session is bound to a live call and that the ACS connection is configured.
  2. If the call is already terminated, the Task exits cleanly with no action.
  3. Otherwise it ends the call for all parties and the Session closes.

To speak a farewell to the caller, place an OutputTask with your goodbye text immediately before the End Event.

Example​

After the IVR has played its goodbye message through a final OutputTask, the Token reaches the End Event. The Module ends the call, Azure tears the connection down, and the Session closes.

AcsAgentConverse (Channel: AcsPhone)​

Runs the real-time conversational voice agent (speech recognition, LLM, streaming voice) over the live call and waits until the conversation ends. It needs the Voice Agent Environment settings, a streaming TTS provider (OpenAI or Resemble), and Enable Media Streaming turned on for the Environment.

Properties​

PropertyTypeRequiredExampleDescription
Greeting MessagestringNoHi, this is the booking line.Opening line spoken before the agent starts listening. Supports {variable} placeholders. Leave blank to start listening immediately.
Enable AI DisclosurebooleanNoonOptional. Speaks an AI disclosure at the start of the conversation, in front of the Greeting Message. Default: off.
AI Disclosure MessagestringNoThis call is handled by {companyName}'s automated AI assistant.Your own wording for the disclosure. Supports {variable} placeholders. Leave it blank to use the built-in sentence for the agent language: Italian when the Voice Agent's STT Language (or, when that is blank, the Module's Default Language) is Italian, English for every other language. Default: empty.
System Prompt OverridestringNoYou only answer questions about opening hours.Per-flow system prompt. When blank, the agent uses the System Prompt from the Voice Agent settings. Supports {variable} placeholders.
Transcript VariablestringNo{transcript}Variable that receives the full conversation transcript when the Token resumes.
Intent VariablestringNo{intent}Variable that receives the captured end or handoff intent name.
Outcome VariablestringYes{outcome}Variable that receives how the conversation ended (IntentCaptured, Handoff, CallerHangup, MaxDuration, Error) so a SwitchTask can route on it.

Behavior​

  1. Checks that the Session is bound to a live call with an open media stream, that Outcome Variable is a {name} reference, and that the Voice Agent and a streaming TTS provider are configured.
  2. Speaks the opening utterance: the AI disclosure first (when enabled), then the Greeting Message, synthesized as a single utterance through the streaming voice so the caller hears no gap between them.
  3. Listens continuously, transcribes each caller turn, asks the LLM for a reply, and speaks it while the caller can still interrupt.
  4. The Token waits at this node until the model calls one of the configured End or Handoff Intents, the caller hangs up, or the Max Turns / Max Duration ceiling is reached.
  5. On resume the transcript, the intent, any captured slots, and the outcome kind are written into the configured variables.

About the AI disclosure option​

Transparency towards the people your flows talk to, for example under Article 50 of the EU AI Act (Regulation (EU) 2024/1689), is the responsibility of the organisation that builds and runs the flow. The option is there to make that easy: when you switch it on, the sentence is spoken as the conversation opens and the agent is additionally instructed to answer truthfully if the caller asks later whether they are speaking to a human. You can also give the disclosure yourself earlier in the flow, for example with an OutputTask. See AI Act disclosure for practical guidance.

Example​

A booking line runs AcsAgentConverse with Greeting Message Hi, this is the booking line., the disclosure switched on, and Outcome Variable {outcome}. The caller first hears Please note: you are talking to an automated AI assistant. Hi, this is the booking line., then holds a normal conversation with the agent. When the model calls the booking_complete end intent, {outcome} holds IntentCaptured, {intent} holds booking_complete, and a SwitchTask routes the Token to the confirmation branch.

Common recipes​

Route callers through a keypad menu​

Greet the caller, collect a single digit, and branch the call with the Standard Module's SwitchTask.

  1. InputTask Prompt Message Welcome! Press 1 for bookings, 2 to cancel an appointment., Store result in {menuChoice}. The caller's digit lands in {menuChoice}.
  2. SwitchTask (Standard Module) Variable to evaluate {menuChoice}; Case 1: Value 1, Branch booking; Case 2: Value 2, Branch cancel; Default branch other. Label the outgoing Sequence Flows booking, cancel, and other.
  3. OutputTask, one per branch booking speaks You can book online or stay on the line., cancel speaks the cancellation instructions, and other speaks Sorry, that key is not on the menu.
  4. EndTask hangs up the call and closes the Session.

Confirm an appointment with an outbound reminder call​

Format the stored appointment time with the Date Module, speak it to the customer, and capture their confirmation.

  1. Extract Date (Date Module) Operation Format text, Input date {appointmentUtc}, Pattern Custom…, Custom pattern dddd d MMMM HH:mm, Locale en-US, Time zone Europe/Rome, Output variable appointmentText. {appointmentText} becomes e.g. Monday 25 May 14:30.
  2. OutputTask Output Message Hello {customerName}, this is a reminder of your appointment on {appointmentText}.
  3. InputTask Prompt Message Press 1 to confirm, or 2 if you need to reschedule., Store result in {confirmChoice}.
  4. SwitchTask (Standard Module) Variable to evaluate {confirmChoice}; Case: Value 1, Branch confirmed; Default branch other.
  5. OutputTask, one per branch confirmed speaks Great, see you then!; other speaks No problem, an operator will call you back.
  6. EndTask hangs up and closes the Session.

Best practices​

  1. Leave Enable Media Streaming off for IVR flows while the media stream is open, ACS rejects the server-side prompt playback the OutputTask and InputTask rely on, so callers hear nothing. Turn it on only when the Environment runs the streaming voice agent.
  2. Set Default Language to match your Default Voice speech synthesis falls back to the Default Language when no Language variable is set on the Session; aligning them avoids accent mismatches.
  3. Cap voice-agent conversations set Max Turns and Max Duration in the Voice Agent settings so a runaway conversation cannot rack up Azure minutes and LLM cost indefinitely.
  4. Validate keypad input before branching the InputTask captures a single digit; pair it with a SwitchTask on the captured variable and handle unexpected digits via the Default branch.
  5. Keep prompts short every OutputTask costs a TTS synthesis; long monologues add latency and cost. Break long messages across multiple OutputTasks. With the Resemble provider this is also a hard limit: a single synthesis accepts at most 2000 characters and the Task fails above that, so split long scripts.

Error codes​

CodeNameDescription
3005TaskInvalidDataA required Task field (e.g. the message to speak) is empty. See full details
4006ModuleGenericExceptionThe call context is missing or invalid (e.g. no live call bound to the Session). See full details
4008ModuleMissingConfigurationThe ACS connection is not configured for the Environment. See full details
8025StartWrongChannelThe ACS call start ran on a Channel other than AcsPhone or the test chat. Add a start for that Channel to the Process. See full details