Background
Sections
IntroductionFoundations1. Resource Hierarchy2. Resource Manager3. Identity and RBAC4. Regions and Availability5. Naming and TaggingVirtual Machines1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetVirtual Network1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetBlob Storage1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure SQL Database1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure Kubernetes Service1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure Container Registry1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetMicrosoft Entra ID1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure RBAC1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure Functions1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAPI Management1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure App Configuration1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure Machine Learning1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure Monitor1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and CheatsheetAzure AI Foundry1. What and Why2. Core Concepts3. Architecture4. Getting Started5. Deployment6. Integrations7. Production8. Interview Questions9. Glossary and Cheatsheet

4. Getting Started

7 min read

The task: create a Foundry resource, deploy one chat model, and get one completion back. Three ways — portal, CLI, and Terraform — then delete it all.

This page is deliberately throwaway. Hard-coded names, public network access, default everything. Nothing here should survive contact with a pull request; the production-shaped version lives in Deployment.

Everything goes in one throwaway resource group so teardown is a single command. That is a genuine advantage of Azure's resource-group model and it is worth using every time you experiment.

Portal, CLI, and Terraform converging on the same Foundry account and model deployment

Before you start: three things that will stop you

  1. Model access and region. Not every model is available in every region, and availability differs by deployment type. Pick your region after checking where the model you want is offered. ⚠️ Verify current regional model availability against current Azure docs.
  2. Quota. A brand-new subscription may have little or no TPM quota for a given model. If deployment creation fails with a quota error, that is not a bug — request quota or choose another model or region.
  3. The name is globally unique and soft-deleted. <name>.services.ai.azure.com must be unique across Azure, and deleting the account reserves the name until it is purged. Use a name with a random suffix for demos, or you will fight your own deleted resource on the second run.

1. Azure Portal

Fastest to understand, least repeatable.

  • In the Azure portal, search Azure AI Foundry (branded Microsoft Foundry in newer portal builds) and create a new resource — choose the Foundry resource option, not the classic hub.
  • Set subscription, a throwaway resource group, a region where your model is offered, and a name.
  • Leave networking public and identity defaults on for now; create.
  • Open the resource and choose Go to Foundry portal. A default project is created for you.
  • In the Foundry portal, go to the Model catalog, pick a chat model, and Deploy. Give the deployment a job-shaped name — chat-default — choose a deployment type, and accept a small capacity.
  • Open the Chat playground, select that deployment, and send a message.

That is the whole loop: resource → project → deployment → call. The portal quietly did three things you will have to do yourself in code — it created the project, it assigned you the data-plane role, and it attached the default content filter.

2. Azure CLI

Repeatable and scriptable. The CLI still speaks the resource provider's language, so you will be typing cognitiveservices, not foundry.

# --- variables -------------------------------------------------------------
RG=rg-foundry-demo
LOC=eastus2                       # pick a region that offers your model
ACC=aifdemo$RANDOM                # must be globally unique
DEPLOY=chat-default
MODEL=gpt-4.1                     # verify the model name and version are offered here
MODELVER=2025-04-14               # verify against `az cognitiveservices model list`

# --- what's actually available in this region ------------------------------
az cognitiveservices model list -l $LOC \
  --query "[?kind=='AIServices'].{model:model.name, version:model.version, sku:model.skus[0].name}" \
  -o table

# --- resource group and Foundry account ------------------------------------
az group create -n $RG -l $LOC

az cognitiveservices account create \
  -n $ACC -g $RG -l $LOC \
  --kind AIServices \
  --sku S0 \
  --custom-domain $ACC \
  --assign-identity \
  --yes

# --- deploy one model ------------------------------------------------------
az cognitiveservices account deployment create \
  -n $ACC -g $RG \
  --deployment-name $DEPLOY \
  --model-name $MODEL \
  --model-version $MODELVER \
  --model-format OpenAI \
  --sku-name GlobalStandard \
  --sku-capacity 10          # capacity is in thousands of TPM for standard types

# --- grant YOURSELF the data-plane role (control-plane Owner is not enough) --
ACC_ID=$(az cognitiveservices account show -n $ACC -g $RG --query id -o tsv)
ME=$(az ad signed-in-user show --query id -o tsv)
az role assignment create \
  --assignee-object-id $ME --assignee-principal-type User \
  --role "Cognitive Services OpenAI User" \
  --scope $ACC_ID

# --- call it, with a token, not a key --------------------------------------
ENDPOINT=$(az cognitiveservices account show -n $ACC -g $RG --query properties.endpoint -o tsv)
TOKEN=$(az account get-access-token --resource https://cognitiveservices.azure.com --query accessToken -o tsv)

curl -s "${ENDPOINT}openai/deployments/${DEPLOY}/chat/completions?api-version=2024-10-21" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"messages":[{"role":"user","content":"Say hello in one short sentence."}],"max_tokens":50}'

⚠️ Model names, model versions, --sku-name values, and the inference api-version all move. Verify each against current Azure docs or the az cognitiveservices model list output above before assuming a copy-paste works.

Note what just happened at step "grant yourself". You created the resource, so you are Owner, and you still could not call the model until a data-plane role existed. That is not a quirk of the CLI — it is the control-plane/data-plane split from Architecture showing up on your first attempt. The portal hid it by assigning the role for you.

PowerShell shops: the Az.CognitiveServices module has New-AzCognitiveServicesAccount and New-AzCognitiveServicesAccountDeployment with the same shape. Foundry is not especially PowerShell-first, so the az path above is the one most examples use.

3. Terraform — minimal

The smallest thing that produces a callable deployment. No variables, no remote state, no modules — all of that is in Deployment.

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.0"
    }
  }
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "demo" {
  name     = "rg-foundry-demo-tf"
  location = "eastus2"
}

resource "azurerm_cognitive_account" "demo" {
  name                = "aifdemotf001" # globally unique
  resource_group_name = azurerm_resource_group.demo.name
  location            = azurerm_resource_group.demo.location

  kind                       = "AIServices"
  sku_name                   = "S0"
  custom_subdomain_name      = "aifdemotf001"
  project_management_enabled = true # makes this a Foundry account rather than a bare AI Services one

  identity {
    type = "SystemAssigned"
  }
}

resource "azurerm_cognitive_deployment" "chat" {
  name                 = "chat-default"
  cognitive_account_id = azurerm_cognitive_account.demo.id

  model {
    format  = "OpenAI"
    name    = "gpt-4.1"
    version = "2025-04-14"
  }

  sku {
    name     = "GlobalStandard"
    capacity = 10
  }
}

output "endpoint" {
  value = azurerm_cognitive_account.demo.endpoint
}
terraform init
terraform plan
terraform apply

Two things this minimal snippet deliberately leaves out, both of which are load-bearing in real life: the project (the azurerm provider's coverage of Foundry projects has lagged the API — azapi or the CLI is the reliable path, shown in Deployment) and the data-plane role assignment, without which the resource exists and nothing can use it. ⚠️ Verify current azurerm support for azurerm_ai_foundry-style project resources versus azurerm_cognitive_account projects before choosing an approach — this area is changing.

Note also that azurerm_ai_foundry and azurerm_ai_foundry_project in the provider refer to the classic hub architecture (Microsoft.MachineLearningServices), not to the account above. The names are misleading and cost people an afternoon.

Teardown — and the purge that everyone forgets

az group delete -n rg-foundry-demo --yes --no-wait
# or, for the Terraform copy:
terraform destroy

Deleting the resource group removes the account — but Cognitive Services accounts are soft-deleted. The name stays reserved, and recreating it with the same name fails with a confusing conflict. Purge it:

az cognitiveservices account list-deleted -o table

az cognitiveservices account purge \
  -n $ACC -g $RG -l $LOC

⚠️ Verify the current soft-delete retention period against current Azure docs. Also note that terraform destroy will not purge for you, and a subsequent apply with the same name will fail — which is exactly the drift-and-rollback scenario discussed in Deployment.

Half of all surprise cloud bills come from forgotten demo resources; on this service the specific one to watch for is a provisioned (PTU) deployment, which bills per hour from the moment it exists whether or not you ever call it. If you experimented with provisioned throughput, check it is gone.


Next: Deployment →

← Back to the Azure AI Foundry overview · ← Previous: Architecture