GitHub Copilot ChatGPT Claude Codex CLI Cursor opencode Skill Text

azure-communication-callautomation-java

Build call automation workflows with Azure Communication Services Call Automation Java SDK. Use when implementing IVR systems, call routing, call recording, DTMF recognition, text-to-speech, or AI-powered call flows.

Ciza · 0 points · 17 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download microsoft-skills-.github_plugins_azure-sdk-java_skills_azure-communication-callautomation-java-e58528d.zip · 6 KB
Part of microsoft/skills — 195 skills

Install

skills CLI npx skills add https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-java/skills/azure-communication-callautomation-java
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install microsoft-skills@llmmart
Git git clone https://github.com/microsoft/skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole microsoft/skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Azure Communication Call Automation (Java)

Build server-side call automation workflows including IVR systems, call routing, recording, and AI-powered interactions.

Installation

<dependency>
    <groupId>com.azure</groupId>
    <artifactId>azure-communication-callautomation</artifactId>
    <version>1.6.0</version>
</dependency>

Client Creation

import com.azure.communication.callautomation.CallAutomationClient;
import com.azure.communication.callautomation.CallAutomationClientBuilder;
import com.azure.core.credential.TokenCredential;
import com.azure.identity.AzureIdentityEnvVars;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.identity.ManagedIdentityCredentialBuilder;

// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
TokenCredential credential = new DefaultAzureCredentialBuilder()
    .requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS)
    .build();
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/java/api/overview/azure/identity-readme?view=azure-java-stable#credential-classes
// TokenCredential credential = new ManagedIdentityCredentialBuilder().build();

// With DefaultAzureCredential
CallAutomationClient client = new CallAutomationClientBuilder()
    .endpoint("https://<resource>.communication.azure.com")
    .credential(credential)
    .buildClient();

// With connection string
CallAutomationClient client = new CallAutomationClientBuilder()
    .connectionString("<connection-string>")
    .buildClient();

Key Concepts

Class Purpose
CallAutomationClient Make calls, answer/reject incoming calls, redirect calls
CallConnection Actions in established calls (add participants, terminate)
CallMedia Media operations (play audio, recognize DTMF/speech)
CallRecording Start/stop/pause recording
CallAutomationEventParser Parse webhook events from ACS

Create Outbound Call

import com.azure.communication.callautomation.models.*;
import com.azure.communication.common.CommunicationUserIdentifier;
import com.azure.communication.common.PhoneNumberIdentifier;

// Call to PSTN number
PhoneNumberIdentifier target = new PhoneNumberIdentifier("+14255551234");
PhoneNumberIdentifier caller = new PhoneNumberIdentifier("+14255550100");

CreateCallOptions options = new CreateCallOptions(
    new CommunicationUserIdentifier("<user-id>"),  // Source
    List.of(target))                                // Targets
    .setSourceCallerId(caller)
    .setCallbackUrl("https://your-app.com/api/callbacks");

CreateCallResult result = client.createCall(options);
String callConnectionId = result.getCallConnectionProperties().getCallConnectionId();

Answer Incoming Call

// From Event Grid webhook - IncomingCall event
String incomingCallContext = "<incoming-call-context-from-event>";

AnswerCallOptions options = new AnswerCallOptions(
    incomingCallContext,
    "https://your-app.com/api/callbacks");

AnswerCallResult result = client.answerCall(options);
CallConnection callConnection = result.getCallConnection();

Play Audio (Text-to-Speech)

CallConnection callConnection = client.getCallConnection(callConnectionId);
CallMedia callMedia = callConnection.getCallMedia();

// Play text-to-speech
TextSource textSource = new TextSource()
    .setText("Welcome to Contoso. Press 1 for sales, 2 for support.")
    .setVoiceName("en-US-JennyNeural");

PlayOptions playOptions = new PlayOptions(
    List.of(textSource),
    List.of(new CommunicationUserIdentifier("<target-user>")));

callMedia.play(playOptions);

// Play audio file
FileSource fileSource = new FileSource()
    .setUrl("https://storage.blob.core.windows.net/audio/greeting.wav");

callMedia.play(new PlayOptions(List.of(fileSource), List.of(target)));

Recognize DTMF Input

// Recognize DTMF tones
DtmfTone stopTones = DtmfTone.POUND;

CallMediaRecognizeDtmfOptions recognizeOptions = new CallMediaRecognizeDtmfOptions(
    new CommunicationUserIdentifier("<target-user>"),
    5)  // Max tones to collect
    .setInterToneTimeout(Duration.ofSeconds(5))
    .setStopTones(List.of(stopTones))
    .setInitialSilenceTimeout(Duration.ofSeconds(15))
    .setPlayPrompt(new TextSource().setText("Enter your account number followed by pound."));

callMedia.startRecognizing(recognizeOptions);

Recognize Speech

// Speech recognition with AI
CallMediaRecognizeSpeechOptions speechOptions = new CallMediaRecognizeSpeechOptions(
    new CommunicationUserIdentifier("<target-user>"))
    .setEndSilenceTimeout(Duration.ofSeconds(2))
    .setSpeechLanguage("en-US")
    .setPlayPrompt(new TextSource().setText("How can I help you today?"));

callMedia.startRecognizing(speechOptions);

Call Recording

CallRecording callRecording = client.getCallRecording();

// Start recording
StartRecordingOptions recordingOptions = new StartRecordingOptions(
    new ServerCallLocator("<server-call-id>"))
    .setRecordingChannel(RecordingChannel.MIXED)
    .setRecordingContent(RecordingContent.AUDIO_VIDEO)
    .setRecordingFormat(RecordingFormat.MP4);

RecordingStateResult recordingResult = callRecording.start(recordingOptions);
String recordingId = recordingResult.getRecordingId();

// Pause/resume/stop
callRecording.pause(recordingId);
callRecording.resume(recordingId);
callRecording.stop(recordingId);

// Download recording (after RecordingFileStatusUpdated event)
callRecording.downloadTo(recordingUrl, Paths.get("recording.mp4"));

Add Participant to Call

CallConnection callConnection = client.getCallConnection(callConnectionId);

CommunicationUserIdentifier participant = new CommunicationUserIdentifier("<user-id>");
AddParticipantOptions addOptions = new AddParticipantOptions(participant)
    .setInvitationTimeout(Duration.ofSeconds(30));

AddParticipantResult result = callConnection.addParticipant(addOptions);

Transfer Call

// Blind transfer
PhoneNumberIdentifier transferTarget = new PhoneNumberIdentifier("+14255559999");
TransferCallToParticipantResult result = callConnection.transferCallToParticipant(transferTarget);

Handle Events (Webhook)

import com.azure.communication.callautomation.CallAutomationEventParser;
import com.azure.communication.callautomation.models.events.*;

// In your webhook endpoint
public void handleCallback(String requestBody) {
    List<CallAutomationEventBase> events = CallAutomationEventParser.parseEvents(requestBody);
    
    for (CallAutomationEventBase event : events) {
        if (event instanceof CallConnected) {
            CallConnected connected = (CallConnected) event;
            System.out.println("Call connected: " + connected.getCallConnectionId());
        } else if (event instanceof RecognizeCompleted) {
            RecognizeCompleted recognized = (RecognizeCompleted) event;
            // Handle DTMF or speech recognition result
            DtmfResult dtmfResult = (DtmfResult) recognized.getRecognizeResult();
            String tones = dtmfResult.getTones().stream()
                .map(DtmfTone::toString)
                .collect(Collectors.joining());
            System.out.println("DTMF received: " + tones);
        } else if (event instanceof PlayCompleted) {
            System.out.println("Audio playback completed");
        } else if (event instanceof CallDisconnected) {
            System.out.println("Call ended");
        }
    }
}

Hang Up Call

// Hang up for all participants
callConnection.hangUp(true);

// Hang up only this leg
callConnection.hangUp(false);

Error Handling

import com.azure.core.exception.HttpResponseException;

try {
    client.answerCall(options);
} catch (HttpResponseException e) {
    if (e.getResponse().getStatusCode() == 404) {
        System.out.println("Call not found or already ended");
    } else if (e.getResponse().getStatusCode() == 400) {
        System.out.println("Invalid request: " + e.getMessage());
    }
}

Environment Variables

AZURE_COMMUNICATION_ENDPOINT=https://<resource>.communication.azure.com  # Required for all auth methods
AZURE_COMMUNICATION_CONNECTION_STRING=endpoint=https://...;accesskey=...  # Alternative to Entra ID auth
CALLBACK_BASE_URL=https://your-app.com/api/callbacks  # Required for webhook callbacks
AZURE_TOKEN_CREDENTIALS=prod  # Required only if DefaultAzureCredential is used in production

Trigger Phrases

  • "call automation Java", "IVR Java", "interactive voice response"
  • "call recording Java", "DTMF recognition Java"
  • "text to speech call", "speech recognition call"
  • "answer incoming call", "transfer call Java"
  • "Azure Communication Services call automation"
Files (skills)
  • references
    • examples.md 16.1 KB
      # Azure Communication Call Automation SDK for Java - Examples
      
      Comprehensive code examples for the Azure Communication Call Automation SDK for Java.
      
      ## Table of Contents
      - [Maven Dependency](#maven-dependency)
      - [Client Creation](#client-creation)
      - [Creating Outbound Calls](#creating-outbound-calls)
      - [Answering Inbound Calls](#answering-inbound-calls)
      - [Playing Audio/TTS](#playing-audiotts)
      - [Recognizing DTMF Tones](#recognizing-dtmf-tones)
      - [Recording Calls](#recording-calls)
      - [Transfer Calls](#transfer-calls)
      - [Add/Remove Participants](#addremove-participants)
      - [Handling Call Events](#handling-call-events)
      - [Async Client Patterns](#async-client-patterns)
      - [Error Handling](#error-handling)
      
      ## Maven Dependency
      
      ```xml
      <dependency>
          <groupId>com.azure</groupId>
          <artifactId>azure-communication-callautomation</artifactId>
          <version>1.5.2</version>
      </dependency>
      ```
      
      ## Client Creation
      
      ### Sync Client
      
      ```java
      import com.azure.communication.callautomation.CallAutomationClient;
      import com.azure.communication.callautomation.CallAutomationClientBuilder;
      
      CallAutomationClient callAutomationClient = new CallAutomationClientBuilder()
          .connectionString("<Azure Communication Services connection string>")
          .buildClient();
      ```
      
      ### Async Client
      
      ```java
      import com.azure.communication.callautomation.CallAutomationAsyncClient;
      
      CallAutomationAsyncClient asyncClient = new CallAutomationClientBuilder()
          .connectionString("<acsConnectionString>")
          .buildAsyncClient();
      ```
      
      ## Creating Outbound Calls
      
      ### Single PSTN Call
      
      ```java
      import com.azure.communication.callautomation.models.*;
      import com.azure.communication.common.PhoneNumberIdentifier;
      import com.azure.core.util.Context;
      
      String callbackUri = "https://<myendpoint>/Events";
      PhoneNumberIdentifier callerIdNumber = new PhoneNumberIdentifier("+18001234567");
      PhoneNumberIdentifier target = new PhoneNumberIdentifier("+16471234567");
      
      CallInvite callInvite = new CallInvite(target, callerIdNumber);
      CreateCallOptions createCallOptions = new CreateCallOptions(callInvite, callbackUri);
      
      // Optional: Add AI capabilities
      CallIntelligenceOptions callIntelligenceOptions = new CallIntelligenceOptions()
          .setCognitiveServicesEndpoint("https://your-cognitive-services.cognitiveservices.azure.com/");
      createCallOptions.setCallIntelligenceOptions(callIntelligenceOptions);
      
      Response<CreateCallResult> result = callAutomationClient.createCallWithResponse(
          createCallOptions, 
          Context.NONE
      );
      String callConnectionId = result.getValue().getCallConnectionProperties().getCallConnectionId();
      ```
      
      ### Group Call
      
      ```java
      import com.azure.communication.common.CommunicationUserIdentifier;
      import java.util.ArrayList;
      import java.util.Arrays;
      import java.util.List;
      
      List<CommunicationIdentifier> targets = new ArrayList<>(Arrays.asList(
          new PhoneNumberIdentifier("+16471234567"),
          new CommunicationUserIdentifier("<user_id>")
      ));
      
      CreateGroupCallOptions groupCallOptions = new CreateGroupCallOptions(targets, callbackUri);
      groupCallOptions.setSourceCallIdNumber(callerIdNumber);
      
      Response<CreateCallResult> response = callAutomationClient.createGroupCallWithResponse(
          groupCallOptions, 
          Context.NONE
      );
      ```
      
      ## Answering Inbound Calls
      
      ### Basic Answer
      
      ```java
      import com.azure.communication.callautomation.models.*;
      
      String incomingCallContext = "<IncomingCallContext_From_IncomingCall_Event>";
      String callbackUri = "https://<myendpoint>/Events";
      
      AnswerCallOptions answerCallOptions = new AnswerCallOptions(incomingCallContext, callbackUri);
      Response<AnswerCallResult> response = callAutomationClient.answerCallWithResponse(
          answerCallOptions, 
          Context.NONE
      );
      ```
      
      ### Answer with AI Capabilities
      
      ```java
      CallIntelligenceOptions callIntelligenceOptions = new CallIntelligenceOptions()
          .setCognitiveServicesEndpoint("https://cognitive-services.cognitiveservices.azure.com/");
      
      AnswerCallOptions answerCallOptions = new AnswerCallOptions(incomingCallContext, callbackUri)
          .setCallIntelligenceOptions(callIntelligenceOptions);
      
      Response<AnswerCallResult> response = callAutomationClient.answerCallWithResponse(
          answerCallOptions, 
          Context.NONE
      );
      ```
      
      ### Answer with Transcription
      
      ```java
      TranscriptionOptions transcriptionOptions = new TranscriptionOptions(
          "wss://your-websocket-url",
          TranscriptionTransport.WEBSOCKET,
          "en-US",
          false,
          "your-endpoint-id"
      );
      
      AnswerCallOptions answerCallOptions = new AnswerCallOptions(incomingCallContext, callbackUri)
          .setCallIntelligenceOptions(callIntelligenceOptions)
          .setTranscriptionOptions(transcriptionOptions);
      ```
      
      ## Playing Audio/TTS
      
      ### Play Text-to-Speech to All
      
      ```java
      import com.azure.communication.callautomation.CallConnection;
      
      String textToPlay = "Welcome to Contoso. How can I help you today?";
      
      TextSource textSource = new TextSource()
          .setText(textToPlay)
          .setVoiceName("en-US-NancyNeural");
      
      CallConnection callConnection = callAutomationClient.getCallConnection(callConnectionId);
      callConnection.getCallMedia().playToAll(textSource);
      ```
      
      ### Play Audio File to Participant
      
      ```java
      import java.util.Arrays;
      
      CommunicationIdentifier targetParticipant = new PhoneNumberIdentifier("+16471234567");
      
      FileSource playSource = new FileSource()
          .setUrl("https://storage.blob.core.windows.net/audio/welcome.wav")
          .setPlaySourceCacheId("<playSourceId>");  // Optional: cache for repeated playback
      
      var playTo = Arrays.asList(targetParticipant);
      PlayOptions playOptions = new PlayOptions(playSource, playTo);
      
      callAutomationClient.getCallConnection(callConnectionId)
          .getCallMedia()
          .playWithResponse(playOptions, Context.NONE);
      ```
      
      ### Play with SSML
      
      ```java
      String ssmlText = "<speak version=\"1.0\" xmlns=\"http://www.w3.org/2001/10/synthesis\" xml:lang=\"en-US\">" +
          "<voice name=\"en-US-JennyNeural\">Hello, welcome to our service!</voice></speak>";
      
      SsmlSource ssmlSource = new SsmlSource()
          .setSsmlText(ssmlText);
      
      callConnection.getCallMedia().playToAll(ssmlSource);
      ```
      
      ## Recognizing DTMF Tones
      
      ### DTMF Recognition
      
      ```java
      import java.time.Duration;
      import java.util.Arrays;
      
      CommunicationIdentifier targetParticipant = new PhoneNumberIdentifier("+16471234567");
      int maxTonesToCollect = 3;
      
      TextSource playSource = new TextSource()
          .setText("Please enter 3 digits.")
          .setVoiceName("en-US-ElizabethNeural");
      
      CallMediaRecognizeDtmfOptions recognizeOptions = new CallMediaRecognizeDtmfOptions(
          targetParticipant, 
          maxTonesToCollect
      )
          .setInitialSilenceTimeout(Duration.ofSeconds(30))
          .setPlayPrompt(playSource)
          .setInterToneTimeout(Duration.ofSeconds(5))
          .setInterruptPrompt(true)
          .setStopTones(Arrays.asList(DtmfTone.POUND));
      
      callAutomationClient.getCallConnection(callConnectionId)
          .getCallMedia()
          .startRecognizingWithResponse(recognizeOptions, Context.NONE);
      ```
      
      ### Speech or DTMF Recognition
      
      ```java
      CallMediaRecognizeSpeechOrDtmfOptions recognizeOptions = 
          new CallMediaRecognizeSpeechOrDtmfOptions(
              targetParticipant, 
              maxTonesToCollect, 
              Duration.ofMillis(1000)
          )
          .setPlayPrompt(playSource)
          .setInitialSilenceTimeout(Duration.ofSeconds(30))
          .setInterruptPrompt(true)
          .setOperationContext("OpenQuestionSpeechOrDtmf");
      
      callAutomationClient.getCallConnection(callConnectionId)
          .getCallMedia()
          .startRecognizingWithResponse(recognizeOptions, Context.NONE);
      ```
      
      ### Choice Recognition
      
      ```java
      import java.util.List;
      
      List<RecognitionChoice> choices = Arrays.asList(
          new RecognitionChoice()
              .setLabel("Confirm")
              .setPhrases(Arrays.asList("Confirm", "Yes", "One"))
              .setTone(DtmfTone.ONE),
          new RecognitionChoice()
              .setLabel("Cancel")
              .setPhrases(Arrays.asList("Cancel", "No", "Two"))
              .setTone(DtmfTone.TWO)
      );
      
      TextSource playSource = new TextSource()
          .setText("Say Confirm or press 1 to confirm, or say Cancel or press 2 to cancel.")
          .setVoiceName("en-US-ElizabethNeural");
      
      CallMediaRecognizeChoiceOptions recognizeOptions = new CallMediaRecognizeChoiceOptions(
          targetParticipant, 
          choices
      )
          .setInterruptPrompt(true)
          .setInitialSilenceTimeout(Duration.ofSeconds(30))
          .setPlayPrompt(playSource)
          .setOperationContext("AppointmentReminderMenu");
      
      callAutomationClient.getCallConnection(callConnectionId)
          .getCallMedia()
          .startRecognizingWithResponse(recognizeOptions, Context.NONE);
      ```
      
      ### Send DTMF Tones
      
      ```java
      List<DtmfTone> tones = Arrays.asList(
          DtmfTone.ONE, 
          DtmfTone.TWO, 
          DtmfTone.THREE, 
          DtmfTone.POUND
      );
      
      SendDtmfTonesOptions options = new SendDtmfTonesOptions(
          tones, 
          new PhoneNumberIdentifier(targetPhoneNumber)
      );
      options.setOperationContext("dtmfs-to-ivr");
      
      callAutomationClient.getCallConnection(callConnectionId)
          .getCallMedia()
          .sendDtmfTonesWithResponse(options, Context.NONE);
      ```
      
      ## Recording Calls
      
      ### Start Recording
      
      ```java
      import com.azure.communication.callautomation.CallRecording;
      
      CallRecording callRecording = callAutomationClient.getCallRecording();
      
      StartRecordingOptions startRecordingOptions = new StartRecordingOptions(
          new ServerCallLocator(serverCallId)
      )
          .setRecordingContent(RecordingContent.AUDIO_VIDEO)
          .setRecordingChannel(RecordingChannel.MIXED)
          .setRecordingFormat(RecordingFormat.MP4);
      
      Response<RecordingStateResult> response = callRecording.startWithResponse(
          startRecordingOptions, 
          Context.NONE
      );
      
      String recordingId = response.getValue().getRecordingId();
      ```
      
      ### Pause/Resume Recording
      
      ```java
      // Pause
      callRecording.pause(recordingId);
      
      // Resume
      callRecording.resume(recordingId);
      ```
      
      ### Stop Recording
      
      ```java
      callRecording.stop(recordingId);
      ```
      
      ### Download Recording
      
      ```java
      callRecording.downloadToWithResponse(
          recordingUrl,
          Paths.get("recording.mp4"),
          null,  // HttpRange (optional)
          Context.NONE
      );
      ```
      
      ## Transfer Calls
      
      ### Blind Transfer
      
      ```java
      CommunicationIdentifier transferDestination = new PhoneNumberIdentifier("+16471234567");
      
      TransferCallToParticipantOptions transferOptions = new TransferCallToParticipantOptions(
          transferDestination
      );
      
      Response<TransferCallResult> response = callAutomationClient
          .getCallConnection(callConnectionId)
          .transferCallToParticipantWithResponse(transferOptions, Context.NONE);
      ```
      
      ### Transfer with Announcement
      
      ```java
      TextSource transferee Prompt = new TextSource()
          .setText("Please hold while we transfer your call.")
          .setVoiceName("en-US-NancyNeural");
      
      TransferCallToParticipantOptions transferOptions = new TransferCallToParticipantOptions(
          transferDestination
      )
          .setSourceCallerIdNumber(new PhoneNumberIdentifier("+18001234567"))
          .setTransfereeGreeting(transfereePrompt);
      
      callAutomationClient.getCallConnection(callConnectionId)
          .transferCallToParticipantWithResponse(transferOptions, Context.NONE);
      ```
      
      ## Add/Remove Participants
      
      ### Add Participant
      
      ```java
      CommunicationIdentifier participant = new PhoneNumberIdentifier("+16471234567");
      PhoneNumberIdentifier callerId = new PhoneNumberIdentifier("+18001234567");
      
      AddParticipantOptions addOptions = new AddParticipantOptions(
          new CallInvite(participant, callerId)
      );
      
      Response<AddParticipantResult> response = callAutomationClient
          .getCallConnection(callConnectionId)
          .addParticipantWithResponse(addOptions, Context.NONE);
      ```
      
      ### Remove Participant
      
      ```java
      CommunicationIdentifier participant = new PhoneNumberIdentifier("+16471234567");
      
      callAutomationClient.getCallConnection(callConnectionId)
          .removeParticipant(participant);
      ```
      
      ### List Participants
      
      ```java
      ListParticipantsResult participants = callAutomationClient
          .getCallConnection(callConnectionId)
          .listParticipants();
      
      participants.getValues().forEach(p -> 
          System.out.println("Participant: " + p.getIdentifier().getRawId()));
      ```
      
      ## Handling Call Events
      
      ### Event Grid Webhook Handler (Spring Boot)
      
      ```java
      import com.azure.communication.callautomation.CallAutomationEventParser;
      import com.azure.communication.callautomation.models.events.*;
      import org.springframework.web.bind.annotation.*;
      
      @RestController
      public class CallbackController {
      
          @PostMapping("/Events")
          public ResponseEntity<String> handleCallEvents(@RequestBody String requestBody) {
              List<CallAutomationEventBase> events = CallAutomationEventParser.parseEvents(requestBody);
              
              for (CallAutomationEventBase event : events) {
                  String callConnectionId = event.getCallConnectionId();
                  
                  if (event instanceof CallConnected) {
                      handleCallConnected((CallConnected) event);
                  } else if (event instanceof RecognizeCompleted) {
                      handleRecognizeCompleted((RecognizeCompleted) event);
                  } else if (event instanceof RecognizeFailed) {
                      handleRecognizeFailed((RecognizeFailed) event);
                  } else if (event instanceof PlayCompleted) {
                      handlePlayCompleted((PlayCompleted) event);
                  } else if (event instanceof CallDisconnected) {
                      handleCallDisconnected((CallDisconnected) event);
                  }
              }
              
              return ResponseEntity.ok("");
          }
          
          private void handleCallConnected(CallConnected event) {
              System.out.println("Call connected: " + event.getCallConnectionId());
          }
          
          private void handleRecognizeCompleted(RecognizeCompleted event) {
              CollectTonesResult result = (CollectTonesResult) event.getRecognizeResult();
              String tones = result.getTones().stream()
                  .map(DtmfTone::toString)
                  .collect(Collectors.joining());
              System.out.println("DTMF tones received: " + tones);
          }
          
          private void handleRecognizeFailed(RecognizeFailed event) {
              System.out.println("Recognition failed: " + event.getResultInformation().getMessage());
          }
          
          private void handlePlayCompleted(PlayCompleted event) {
              System.out.println("Play completed: " + event.getOperationContext());
          }
          
          private void handleCallDisconnected(CallDisconnected event) {
              System.out.println("Call disconnected: " + event.getCallConnectionId());
          }
      }
      ```
      
      ## Async Client Patterns
      
      ### Create Call Async
      
      ```java
      asyncClient.createCall(callInvite, callbackUri)
          .subscribe(
              result -> System.out.println("Call ID: " + 
                  result.getCallConnectionProperties().getCallConnectionId()),
              error -> System.err.println("Error: " + error.getMessage())
          );
      ```
      
      ### Play Audio Async
      
      ```java
      asyncClient.getCallConnectionAsync(callConnectionId)
          .getCallMediaAsync()
          .playToAll(textSource)
          .subscribe(
              unused -> System.out.println("Play started"),
              error -> System.err.println("Error: " + error.getMessage())
          );
      ```
      
      ### Recognize Async
      
      ```java
      asyncClient.getCallConnectionAsync(callConnectionId)
          .getCallMediaAsync()
          .startRecognizingWithResponse(recognizeOptions)
          .subscribe(
              response -> System.out.println("Recognition started"),
              error -> System.err.println("Error: " + error.getMessage())
          );
      ```
      
      ## Error Handling
      
      ### Sync Error Handling
      
      ```java
      import com.azure.core.exception.HttpResponseException;
      
      try {
          Response<CreateCallResult> result = callAutomationClient.createCallWithResponse(
              createCallOptions, 
              Context.NONE
          );
      } catch (HttpResponseException e) {
          System.err.println("HTTP Status: " + e.getResponse().getStatusCode());
          System.err.println("Error: " + e.getMessage());
      } catch (Exception e) {
          System.err.println("Unexpected error: " + e.getMessage());
      }
      ```
      
      ### Async Error Handling
      
      ```java
      asyncClient.createCall(callInvite, callbackUri)
          .subscribe(
              result -> System.out.println("Success"),
              error -> {
                  if (error instanceof HttpResponseException) {
                      HttpResponseException httpError = (HttpResponseException) error;
                      System.err.println("HTTP error: " + httpError.getResponse().getStatusCode());
                  } else {
                      System.err.println("Error: " + error.getMessage());
                  }
              }
          );
      ```
      
      ### Common Error Codes
      
      | Code | Meaning |
      |------|---------|
      | 400 | Invalid request |
      | 401 | Authentication failed |
      | 403 | Not authorized |
      | 404 | Call/resource not found |
      | 429 | Rate limited |
      | 500 | Server error |
      
  • SKILL.md 9.1 KB
    ---
    name: azure-communication-callautomation-java
    description: Build call automation workflows with Azure Communication Services Call Automation Java SDK. Use when implementing IVR systems, call routing, call recording, DTMF recognition, text-to-speech, or AI-powered call flows.
    license: MIT
    metadata:
      author: Microsoft
      version: "1.0.0"
      package: com.azure:azure-communication-callautomation
    ---
    
    # Azure Communication Call Automation (Java)
    
    Build server-side call automation workflows including IVR systems, call routing, recording, and AI-powered interactions.
    
    ## Installation
    
    ```xml
    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-communication-callautomation</artifactId>
        <version>1.6.0</version>
    </dependency>
    ```
    
    ## Client Creation
    
    ```java
    import com.azure.communication.callautomation.CallAutomationClient;
    import com.azure.communication.callautomation.CallAutomationClientBuilder;
    import com.azure.core.credential.TokenCredential;
    import com.azure.identity.AzureIdentityEnvVars;
    import com.azure.identity.DefaultAzureCredentialBuilder;
    import com.azure.identity.ManagedIdentityCredentialBuilder;
    
    // Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
    TokenCredential credential = new DefaultAzureCredentialBuilder()
        .requireEnvVars(AzureIdentityEnvVars.AZURE_TOKEN_CREDENTIALS)
        .build();
    // Or use a specific credential directly in production:
    // See https://learn.microsoft.com/java/api/overview/azure/identity-readme?view=azure-java-stable#credential-classes
    // TokenCredential credential = new ManagedIdentityCredentialBuilder().build();
    
    // With DefaultAzureCredential
    CallAutomationClient client = new CallAutomationClientBuilder()
        .endpoint("https://<resource>.communication.azure.com")
        .credential(credential)
        .buildClient();
    
    // With connection string
    CallAutomationClient client = new CallAutomationClientBuilder()
        .connectionString("<connection-string>")
        .buildClient();
    ```
    
    ## Key Concepts
    
    | Class | Purpose |
    |-------|---------|
    | `CallAutomationClient` | Make calls, answer/reject incoming calls, redirect calls |
    | `CallConnection` | Actions in established calls (add participants, terminate) |
    | `CallMedia` | Media operations (play audio, recognize DTMF/speech) |
    | `CallRecording` | Start/stop/pause recording |
    | `CallAutomationEventParser` | Parse webhook events from ACS |
    
    ## Create Outbound Call
    
    ```java
    import com.azure.communication.callautomation.models.*;
    import com.azure.communication.common.CommunicationUserIdentifier;
    import com.azure.communication.common.PhoneNumberIdentifier;
    
    // Call to PSTN number
    PhoneNumberIdentifier target = new PhoneNumberIdentifier("+14255551234");
    PhoneNumberIdentifier caller = new PhoneNumberIdentifier("+14255550100");
    
    CreateCallOptions options = new CreateCallOptions(
        new CommunicationUserIdentifier("<user-id>"),  // Source
        List.of(target))                                // Targets
        .setSourceCallerId(caller)
        .setCallbackUrl("https://your-app.com/api/callbacks");
    
    CreateCallResult result = client.createCall(options);
    String callConnectionId = result.getCallConnectionProperties().getCallConnectionId();
    ```
    
    ## Answer Incoming Call
    
    ```java
    // From Event Grid webhook - IncomingCall event
    String incomingCallContext = "<incoming-call-context-from-event>";
    
    AnswerCallOptions options = new AnswerCallOptions(
        incomingCallContext,
        "https://your-app.com/api/callbacks");
    
    AnswerCallResult result = client.answerCall(options);
    CallConnection callConnection = result.getCallConnection();
    ```
    
    ## Play Audio (Text-to-Speech)
    
    ```java
    CallConnection callConnection = client.getCallConnection(callConnectionId);
    CallMedia callMedia = callConnection.getCallMedia();
    
    // Play text-to-speech
    TextSource textSource = new TextSource()
        .setText("Welcome to Contoso. Press 1 for sales, 2 for support.")
        .setVoiceName("en-US-JennyNeural");
    
    PlayOptions playOptions = new PlayOptions(
        List.of(textSource),
        List.of(new CommunicationUserIdentifier("<target-user>")));
    
    callMedia.play(playOptions);
    
    // Play audio file
    FileSource fileSource = new FileSource()
        .setUrl("https://storage.blob.core.windows.net/audio/greeting.wav");
    
    callMedia.play(new PlayOptions(List.of(fileSource), List.of(target)));
    ```
    
    ## Recognize DTMF Input
    
    ```java
    // Recognize DTMF tones
    DtmfTone stopTones = DtmfTone.POUND;
    
    CallMediaRecognizeDtmfOptions recognizeOptions = new CallMediaRecognizeDtmfOptions(
        new CommunicationUserIdentifier("<target-user>"),
        5)  // Max tones to collect
        .setInterToneTimeout(Duration.ofSeconds(5))
        .setStopTones(List.of(stopTones))
        .setInitialSilenceTimeout(Duration.ofSeconds(15))
        .setPlayPrompt(new TextSource().setText("Enter your account number followed by pound."));
    
    callMedia.startRecognizing(recognizeOptions);
    ```
    
    ## Recognize Speech
    
    ```java
    // Speech recognition with AI
    CallMediaRecognizeSpeechOptions speechOptions = new CallMediaRecognizeSpeechOptions(
        new CommunicationUserIdentifier("<target-user>"))
        .setEndSilenceTimeout(Duration.ofSeconds(2))
        .setSpeechLanguage("en-US")
        .setPlayPrompt(new TextSource().setText("How can I help you today?"));
    
    callMedia.startRecognizing(speechOptions);
    ```
    
    ## Call Recording
    
    ```java
    CallRecording callRecording = client.getCallRecording();
    
    // Start recording
    StartRecordingOptions recordingOptions = new StartRecordingOptions(
        new ServerCallLocator("<server-call-id>"))
        .setRecordingChannel(RecordingChannel.MIXED)
        .setRecordingContent(RecordingContent.AUDIO_VIDEO)
        .setRecordingFormat(RecordingFormat.MP4);
    
    RecordingStateResult recordingResult = callRecording.start(recordingOptions);
    String recordingId = recordingResult.getRecordingId();
    
    // Pause/resume/stop
    callRecording.pause(recordingId);
    callRecording.resume(recordingId);
    callRecording.stop(recordingId);
    
    // Download recording (after RecordingFileStatusUpdated event)
    callRecording.downloadTo(recordingUrl, Paths.get("recording.mp4"));
    ```
    
    ## Add Participant to Call
    
    ```java
    CallConnection callConnection = client.getCallConnection(callConnectionId);
    
    CommunicationUserIdentifier participant = new CommunicationUserIdentifier("<user-id>");
    AddParticipantOptions addOptions = new AddParticipantOptions(participant)
        .setInvitationTimeout(Duration.ofSeconds(30));
    
    AddParticipantResult result = callConnection.addParticipant(addOptions);
    ```
    
    ## Transfer Call
    
    ```java
    // Blind transfer
    PhoneNumberIdentifier transferTarget = new PhoneNumberIdentifier("+14255559999");
    TransferCallToParticipantResult result = callConnection.transferCallToParticipant(transferTarget);
    ```
    
    ## Handle Events (Webhook)
    
    ```java
    import com.azure.communication.callautomation.CallAutomationEventParser;
    import com.azure.communication.callautomation.models.events.*;
    
    // In your webhook endpoint
    public void handleCallback(String requestBody) {
        List<CallAutomationEventBase> events = CallAutomationEventParser.parseEvents(requestBody);
        
        for (CallAutomationEventBase event : events) {
            if (event instanceof CallConnected) {
                CallConnected connected = (CallConnected) event;
                System.out.println("Call connected: " + connected.getCallConnectionId());
            } else if (event instanceof RecognizeCompleted) {
                RecognizeCompleted recognized = (RecognizeCompleted) event;
                // Handle DTMF or speech recognition result
                DtmfResult dtmfResult = (DtmfResult) recognized.getRecognizeResult();
                String tones = dtmfResult.getTones().stream()
                    .map(DtmfTone::toString)
                    .collect(Collectors.joining());
                System.out.println("DTMF received: " + tones);
            } else if (event instanceof PlayCompleted) {
                System.out.println("Audio playback completed");
            } else if (event instanceof CallDisconnected) {
                System.out.println("Call ended");
            }
        }
    }
    ```
    
    ## Hang Up Call
    
    ```java
    // Hang up for all participants
    callConnection.hangUp(true);
    
    // Hang up only this leg
    callConnection.hangUp(false);
    ```
    
    ## Error Handling
    
    ```java
    import com.azure.core.exception.HttpResponseException;
    
    try {
        client.answerCall(options);
    } catch (HttpResponseException e) {
        if (e.getResponse().getStatusCode() == 404) {
            System.out.println("Call not found or already ended");
        } else if (e.getResponse().getStatusCode() == 400) {
            System.out.println("Invalid request: " + e.getMessage());
        }
    }
    ```
    
    ## Environment Variables
    
    ```bash
    AZURE_COMMUNICATION_ENDPOINT=https://<resource>.communication.azure.com  # Required for all auth methods
    AZURE_COMMUNICATION_CONNECTION_STRING=endpoint=https://...;accesskey=...  # Alternative to Entra ID auth
    CALLBACK_BASE_URL=https://your-app.com/api/callbacks  # Required for webhook callbacks
    AZURE_TOKEN_CREDENTIALS=prod  # Required only if DefaultAzureCredential is used in production
    ```
    
    ## Trigger Phrases
    
    - "call automation Java", "IVR Java", "interactive voice response"
    - "call recording Java", "DTMF recognition Java"
    - "text to speech call", "speech recognition call"
    - "answer incoming call", "transfer call Java"
    - "Azure Communication Services call automation"
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related