Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Azure Communication Services common utilities for Java. Use when working with CommunicationTokenCredential, user identifiers, token refresh, or shared authentication across ACS services.
.claude/skills/azure-communication-common-java/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 46% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 43% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 68% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 154% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 66% | 0% |
Shared authentication utilities and data structures for Azure Communication Services.
xml<dependency> <groupId>com.azure</groupId> <artifactId>azure-communication-common</artifactId> <version>1.4.0</version> </dependency>
| Class | Purpose | |-------|---------| | CommunicationTokenCredential | Authenticate users with ACS services | | CommunicationTokenRefreshOptions | Configure automatic token refresh | | CommunicationUserIdentifier | Identify ACS users | | PhoneNumberIdentifier | Identify PSTN phone numbers | | MicrosoftTeamsUserIdentifier | Identify Teams users | | UnknownIdentifier | Generic identifier for unknown types |
javaimport com.azure.communication.common.CommunicationTokenCredential; // Simple static token - no refresh String userToken = "<user-access-token>"; CommunicationTokenCredential credential = new CommunicationTokenCredential(userToken); // Use with Chat, Calling, etc. ChatClient chatClient = new ChatClientBuilder() .endpoint("https://<resource>.communication.azure.com") .credential(credential) .buildClient();
javaimport com.azure.communication.common.CommunicationTokenRefreshOptions; import java.util.concurrent.Callable; // Token refresher callback - called when token is about to expire Callable<String> tokenRefresher = () -> { // Call your server to get a fresh token return fetchNewTokenFromServer(); }; // With proactive refresh CommunicationTokenRefreshOptions refreshOptions = new CommunicationTokenRefreshOptions(tokenRefresher) .setRefreshProactively(true) // Refresh before expiry .setInitialToken(currentToken); // Optional initial token CommunicationTokenCredential credential = new CommunicationTokenCredential(refreshOptions);
javaimport java.util.concurrent.CompletableFuture; // Async token fetcher Callable<String> asyncRefresher = () -> { CompletableFuture<String> future = fetchTokenAsync(); return future.get(); // Block until token is available }; CommunicationTokenRefreshOptions options = new CommunicationTokenRefreshOptions(asyncRefresher) .setRefreshProactively(true); CommunicationTokenCredential credential = new CommunicationTokenCredential(options);
javaimport com.azure.identity.InteractiveBrowserCredentialBuilder; import com.azure.communication.common.EntraCommunicationTokenCredentialOptions; import java.util.Arrays; import java.util.List; // For Teams Phone Extensibility InteractiveBrowserCredential entraCredential = new InteractiveBrowserCredentialBuilder() .clientId("<your-client-id>") .tenantId("<your-tenant-id>") .redirectUrl("<your-redirect-uri>") .build(); String resourceEndpoint = "https://<resource>.communication.azure.com"; List<String> scopes = Arrays.asList( "https://auth.msft.communication.azure.com/TeamsExtension.ManageCalls" ); EntraCommunicationTokenCredentialOptions entraOptions = new EntraCommunicationTokenCredentialOptions(entraCredential, resourceEndpoint) .setScopes(scopes); CommunicationTokenCredential credential = new CommunicationTokenCredential(entraOptions);
javaimport com.azure.communication.common.CommunicationUserIdentifier; // Create identifier for ACS user CommunicationUserIdentifier user = new CommunicationUserIdentifier("8:acs:resource-id_user-id"); // Get raw ID String rawId = user.getId();
javaimport com.azure.communication.common.PhoneNumberIdentifier; // E.164 format phone number PhoneNumberIdentifier phone = new PhoneNumberIdentifier("+14255551234"); String phoneNumber = phone.getPhoneNumber(); // "+14255551234" String rawId = phone.getRawId(); // "4:+14255551234"
javaimport com.azure.communication.common.MicrosoftTeamsUserIdentifier; // Teams user identifier MicrosoftTeamsUserIdentifier teamsUser = new MicrosoftTeamsUserIdentifier("<teams-user-id>") .setCloudEnvironment(CommunicationCloudEnvironment.PUBLIC); // For anonymous Teams users MicrosoftTeamsUserIdentifier anonymousTeamsUser = new MicrosoftTeamsUserIdentifier("<teams-user-id>") .setAnonymous(true);
javaimport com.azure.communication.common.UnknownIdentifier; // For identifiers of unknown type UnknownIdentifier unknown = new UnknownIdentifier("some-raw-id");
javaimport com.azure.communication.common.CommunicationIdentifier; import com.azure.communication.common.CommunicationIdentifierModel; // Parse raw ID to appropriate type public CommunicationIdentifier parseIdentifier(String rawId) { if (rawId.startsWith("8:acs:")) { return new CommunicationUserIdentifier(rawId); } else if (rawId.startsWith("4:")) { String phone = rawId.substring(2); return new PhoneNumberIdentifier(phone); } else if (rawId.startsWith("8:orgid:")) { String teamsId = rawId.substring(8); return new MicrosoftTeamsUserIdentifier(teamsId); } else { return new UnknownIdentifier(rawId); } }
javaimport com.azure.communication.common.CommunicationIdentifier; public void processIdentifier(CommunicationIdentifier identifier) { if (identifier instanceof CommunicationUserIdentifier) { CommunicationUserIdentifier user = (CommunicationUserIdentifier) identifier; System.out.println("ACS User: " + user.getId()); } else if (identifier instanceof PhoneNumberIdentifier) { PhoneNumberIdentifier phone = (PhoneNumberIdentifier) identifier; System.out.println("Phone: " + phone.getPhoneNumber()); } else if (identifier instanceof MicrosoftTeamsUserIdentifier) { MicrosoftTeamsUserIdentifier teams = (MicrosoftTeamsUserIdentifier) identifier; System.out.println("Teams User: " + teams.getUserId()); System.out.println("Anonymous: " + teams.isAnonymous()); } else if (identifier instanceof UnknownIdentifier) { UnknownIdentifier unknown = (UnknownIdentifier) identifier; System.out.println("Unknown: " + unknown.getId()); } }
javaimport com.azure.core.credential.AccessToken; // Get current token (for debugging/logging - don't expose!) CommunicationTokenCredential credential = new CommunicationTokenCredential(token); // Sync access AccessToken accessToken = credential.getToken(); System.out.println("Token expires: " + accessToken.getExpiresAt()); // Async access credential.getTokenAsync() .subscribe(token -> { System.out.println("Token: " + token.getToken().substring(0, 20) + "..."); System.out.println("Expires: " + token.getExpiresAt()); });
java// Clean up when done credential.close(); // Or use try-with-resources try (CommunicationTokenCredential cred = new CommunicationTokenCredential(options)) { // Use credential chatClient.doSomething(); }
javaimport com.azure.communication.common.CommunicationCloudEnvironment; // Available environments CommunicationCloudEnvironment publicCloud = CommunicationCloudEnvironment.PUBLIC; CommunicationCloudEnvironment govCloud = CommunicationCloudEnvironment.GCCH; CommunicationCloudEnvironment dodCloud = CommunicationCloudEnvironment.DOD; // Set on Teams identifier MicrosoftTeamsUserIdentifier teamsUser = new MicrosoftTeamsUserIdentifier("<user-id>") .setCloudEnvironment(CommunicationCloudEnvironment.GCCH);
bashAZURE_COMMUNICATION_ENDPOINT=https://<resource>.communication.azure.com AZURE_COMMUNICATION_USER_TOKEN=<user-access-token>
setRefreshProactively(true) for long-lived clientsjava// Pattern: Create credential for Chat/Calling client public ChatClient createChatClient(String token, String endpoint) { CommunicationTokenRefreshOptions refreshOptions = new CommunicationTokenRefreshOptions(this::refreshToken) .setRefreshProactively(true) .setInitialToken(token); CommunicationTokenCredential credential = new CommunicationTokenCredential(refreshOptions); return new ChatClientBuilder() .endpoint(endpoint) .credential(credential) .buildClient(); } private String refreshToken() { // Call your token endpoint return tokenService.getNewToken(); }
This skill is applicable to execute the workflow or actions described in the overview.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 10,602 | 5,099 | -52% | 1 | 1 | 0% | 2,190 | 3,204 | +46% | 0 | 0 | — |
case-02 | fail→fail | 16,007 | 9,017 | -44% | 1 | 1 | 0% | 3,499 | 4,372 | +25% | 0 | 0 | — |
case-03 | fail→pass | 13,848 | 8,025 | -42% | 1 | 1 | 0% | 2,793 | 3,999 | +43% | 0 | 0 | — |
case-04 | pass→pass | 5,437 | 2,644 | -51% | 1 | 1 | 0% | 1,054 | 2,647 | +151% | 0 | 0 | — |
case-05 | fail→pass | 9,726 | 3,453 | -64% | 1 | 1 | 0% | 1,653 | 2,775 | +68% | 0 | 0 | — |
case-06 | fail→pass | 6,279 | 2,861 | -54% | 1 | 1 | 0% | 1,082 | 2,753 | +154% | 0 | 0 | — |
case-07 | fail→fail | 6,929 | 2,085 | -70% | 1 | 1 | 0% | 1,268 | 2,623 | +107% | 0 | 0 | — |
case-08 | fail→fail | 8,733 | 3,108 | -64% | 1 | 1 | 0% | 1,598 | 2,791 | +75% | 0 | 0 | — |
case-09 | fail→fail | 6,594 | 3,237 | -51% | 1 | 1 | 0% | 1,273 | 2,805 | +120% | 0 | 0 | — |
case-10 | fail→fail | 3,481 | 2,179 | -37% | 1 | 1 | 0% | 592 | 2,672 | +351% | 0 | 0 | — |
case-11 | fail→pass | 9,475 | 5,464 | -42% | 1 | 1 | 0% | 1,769 | 2,930 | +66% | 0 | 0 | — |
case-12 | fail→pass | 12,268 | 4,560 | -63% | 1 | 1 | 0% | 2,276 | 3,113 | +37% | 0 | 0 | — |
case-13 | pass→pass | 9,668 | 4,973 | -49% | 1 | 1 | 0% | 1,680 | 3,171 | +89% | 0 | 0 | — |
case-14 | fail→pass | 7,090 | 3,093 | -56% | 1 | 1 | 0% | 1,271 | 2,449 | +93% | 0 | 0 | — |
case-15 | fail→fail | 5,205 | 3,802 | -27% | 1 | 1 | 0% | 1,046 | 3,016 | +188% | 0 | 0 | — |
case-16 | pass→pass | 7,698 | 3,433 | -55% | 1 | 1 | 0% | 1,589 | 2,943 | +85% | 0 | 0 | — |
case-17 | pass→pass | 5,771 | 3,081 | -47% | 1 | 1 | 0% | 1,198 | 2,876 | +140% | 0 | 0 | — |
case-18 | fail→pass | 9,612 | 4,101 | -57% | 1 | 1 | 0% | 1,513 | 2,947 | +95% | 0 | 0 | — |
case-19 | pass→pass | 10,063 | 5,800 | -42% | 1 | 1 | 0% | 2,026 | 3,504 | +73% | 0 | 0 | — |
case-20 | fail→fail | 11,309 | 14,190 | +25% | 1 | 1 | 0% | 2,339 | 4,149 | +77% | 0 | 0 | — |
case-21 | fail→fail | 8,772 | 5,862 | -33% | 1 | 1 | 0% | 1,901 | 3,457 | +82% | 0 | 0 | — |
case-22 | fail→fail | 10,156 | 8,566 | -16% | 1 | 1 | 0% | 2,017 | 3,907 | +94% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +36 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.