A support team I worked with received about 5,000 customer emails a day and read every one by hand. A developer built a quick script to score the tone of each message, and it worked well. Then someone committed the script to a shared repository with the service key pasted in plain text. The key was valid for a production resource, and the team had to rotate it in the middle of a release.
That story is common. Azure Cognitive Services Python projects usually start as a ten-line demo, and the demo habits (hardcoded keys, public endpoints, no cost limits) follow the code into production. You can avoid all of that with a few setup choices.
This guide shows you how the service family is named today, how to create a secured resource, and how to write Python for sentiment analysis, PII redaction, and image captioning without storing a single key. You will also learn the cost controls and troubleshooting steps that keep the project healthy.
Azure Cognitive Services Python: What Changed
Microsoft’s prebuilt AI APIs began life as Azure Cognitive Services. They were later renamed Azure AI Services, and Microsoft’s current product page now calls the collection Foundry Tools, which it describes as the new name for what was previously Azure AI Services or Azure Cognitive Services.
The capabilities are the same families you already know: Vision, Speech, Language, Translator, Document Intelligence, and Content Understanding.
You will still see all three names in the portal, the CLI, and old tutorials. Your Python code does not care. What matters is which SDK package you install. Microsoft’s older module list shows many azure-cognitiveservices-* packages, such as the Computer Vision, Face, and Bing search modules. For new work, use the newer azure-ai-* packages where they exist.
If you want a broader tour first, read the overview of Azure Cognitive Services and the list of Azure AI services. For a newer view of the family, see the guide to the Azure AI Foundry.
Pro Tip: In my experience, the rename confuses people more than the code does. When a tutorial says “Cognitive Services,” “AI Services,” or “Foundry Tools,” I check only two things: which package it installs and which authentication method it uses.
Plan the Architecture and Pricing Model
Make four decisions before you create anything.
Multi-service or single-service resource. A multi-service resource gives you one endpoint and one set of credentials for several AI services. A single-service resource, such as a Language resource, covers one service only.
Multi-service is convenient for a small team. Single-service gives you cleaner permissions and separate quotas per capability. Read about the Azure AI services multi-service account before you choose.
Region. Put the resource near the apps and data that call it. Regional availability also matters. Image captioning, for example, needs a Computer Vision resource in a GPU-supported region.
Pricing model. These services are consumption-based, which means you pay per transaction or per unit of work, not for a server that sits idle. Most services offer a free F0 tier with a small monthly allowance and a paid Standard tier for production. Avoid quoting prices, because they change by service and region. See the guide to Azure Cognitive Services pricing for the cost drivers.
Environments. Use a free or low-volume resource for dev, and a separate Standard resource for production. That prevents a runaway test loop from using up your production quota.
Pro Tip: I create one resource per environment and per workload. When a test script goes wrong, it hits a dev quota, and production keeps running.
Create a Secure Resource with the Azure CLI
Start with a resource group, a logical container that groups related Azure resources. Follow the guide to create a resource group in Azure if you prefer the portal.
az group create \
--name rg-ai-support-dev \
--location eastus \
--tags owner=support-team costcenter=cx environment=devThis creates rg-ai-support-dev in East US. The tags identify the owner and cost center, which makes cost reviews easier. See what Azure tags are for naming ideas.
Now create a multi-service AI resource with a custom subdomain:
az cognitiveservices account create \
--name <ai-resource-name> \
--resource-group rg-ai-support-dev \
--kind CognitiveServices \
--sku S0 \
--location eastus \
--custom-domain <unique-subdomain-name> \
--yesHere is what the key parameters do:
--kind CognitiveServicescreates the multi-service resource. Use a specific kind such asTextAnalyticsfor a single-service resource.--sku S0selects the paid Standard tier. UseF0only for learning.--custom-domainsets a custom subdomain, which looks likehttps://<unique-subdomain-name>.cognitiveservices.azure.com. This matters for security. Microsoft’s SDK notes say regional endpoints do not support Entra ID authentication, so you must have a custom subdomain to use it.--yesaccepts the Responsible AI terms prompt.
Get the endpoint:
az cognitiveservices account show \
--name <ai-resource-name> \
--resource-group rg-ai-support-dev \
--query properties.endpoint \
--output tsvThe --query and --output tsv options return only the endpoint as plain text, which is easy to store in an environment variable.
Grant Access with RBAC, Not Keys
With Microsoft Entra ID and Azure RBAC, you grant a role instead of sharing a key. Learn the basics in what Azure RBAC is and the Microsoft Entra ID tutorial for beginners.
az role assignment create \
--assignee <entra-group-object-id> \
--role "Cognitive Services User" \
--scope /subscriptions/<subscription-id>/resourceGroups/rg-ai-support-dev/providers/Microsoft.CognitiveServices/accounts/<ai-resource-name>This lets the group call the APIs on this one resource. The Image Analysis docs name the Cognitive Services User role for Entra access, and the Language docs name a Language Reader role for service principals. Use the narrowest role your service supports, and assign it to groups so access changes follow team membership.
Set Up the Python Project
Create an isolated environment and install the packages. If you need help, see how to install Azure modules in Python.
python -m venv .venv
source .venv/bin/activate
pip install azure-ai-textanalytics azure-ai-vision-imageanalysis azure-identityThe first line creates a virtual environment. The second activates it (on Windows PowerShell, use .venv\Scripts\Activate.ps1). The last installs the three packages. A virtual environment keeps this project’s dependencies separate from others on your machine.
Sign in with the Azure CLI and set the endpoint. See the az login guide if you need help signing in.
az login
export AI_SERVICES_ENDPOINT="https://<unique-subdomain-name>.cognitiveservices.azure.com/"The endpoint is not a secret, so an environment variable is fine. The code below needs no key at all.
Analyze Sentiment and Redact PII
This script scores the tone of support emails and removes personal data before anything is stored.
import os
from azure.ai.textanalytics import TextAnalyticsClient
from azure.identity import DefaultAzureCredential
endpoint = os.environ["AI_SERVICES_ENDPOINT"]
client = TextAnalyticsClient(endpoint=endpoint, credential=DefaultAzureCredential())
tickets = [
"My order arrived late and nobody answered my emails. Call me at 312-555-0176.",
"Great service! The agent fixed my billing issue in minutes.",
"The app keeps crashing, but the support chat was friendly.",
]
def batches(items, size=10):
for start in range(0, len(items), size):
yield items[start:start + size]
for batch in batches(tickets):
sentiments = client.analyze_sentiment(batch, show_opinion_mining=True)
pii_results = client.recognize_pii_entities(batch)
for text, sentiment, pii in zip(batch, sentiments, pii_results):
if sentiment.is_error or pii.is_error:
print("Document error - skipping")
continue
print(f"Sentiment: {sentiment.sentiment}")
print(
f"Scores: positive={sentiment.confidence_scores.positive:.2f}, "
f"negative={sentiment.confidence_scores.negative:.2f}"
)
print(f"Safe text to store: {pii.redacted_text}\n")Here is why the code is written this way:
DefaultAzureCredential()uses youraz loginsession on a laptop and a managed identity when the code runs in Azure. The same code works in both places, and no key appears anywhere.batches()sends documents in groups. The Language API takes a list of documents per call, and results come back in the same order.is_errorchecks each result. One bad document does not fail the whole batch, but you must test for it.show_opinion_mining=Truealso returns which aspects, such as “app” or “chat,” drew positive or negative opinions.redacted_textmasks entities like phone numbers, so you store the safe version, not the raw email.
Check the current service data limits for batch size and document length before sen