AI-103 Set Up AI Solutions in Foundry: Deployment Types, Agent Setup and CI/CD
Setting up AI solutions in Microsoft Foundry means designing the Azure infrastructure behind your apps and agents, choosing deployment types that meet residency, latency and cost requirements, configuring model and agent deployments, and promoting them through CI/CD pipelines. This lesson covers the Foundry resource and project model, every deployment type and processing tier, model version upgrade options, basic versus standard agent setup, prompt versus hosted agents, and keyless, evaluation-gated pipelines.
On this page10 sections
- How is Microsoft Foundry infrastructure organized?
- Which deployment type keeps prompts where you need them?
- Standard, provisioned, batch or Developer: matching the workload
- Priority, flex and default processing on standard deployments
- Serverless API or managed compute?
- How do model versions and upgrade policies work?
- Model deployments as code and deployment governance
- Basic vs standard agent setup in Foundry Agent Service
- Prompt agents vs hosted agents
- Integrating Foundry projects with CI/CD pipelines
- Design Foundry infrastructure with resources and projects, and choose the right isolation boundary for teams and environments
- Choose a deployment type (Global, Data Zone or geography; Standard, Provisioned, Batch or Developer) from residency, latency, quota and cost requirements
- Use priority, flex and default processing tiers and choose between Serverless API and managed compute
- Configure model version upgrade options and create or govern deployments as code with CLI, Bicep and Azure Policy
- Choose basic or standard agent setup and prompt or hosted agents, and configure hosted agent versions, protocols and identity
- Integrate Foundry projects with GitHub Actions or Azure DevOps using OIDC, agents as code and evaluation gates
How is Microsoft Foundry infrastructure organized?
Current Foundry infrastructure is a Foundry resource (an Azure resource of kind AIServices) with one or more child Foundry projects. The resource is the unit of networking, resource-level RBAC, policy, keys and model deployments; a project is the unit of development work — its agents, files, evaluations and project-scoped access. No separate hub or Azure Machine Learning workspace is needed.
Hub-based projects still exist in Foundry (classic), built on an Azure Machine Learning hub, but new investment goes into Foundry projects. Treat a hub as the extra resource a new design avoids, not as a current choice for agent work.
An existing Azure OpenAI resource can be upgraded to a Foundry resource. The upgrade keeps the endpoint, API keys and existing deployments and state, and adds the project model, Foundry Agent Service and the wider model catalog. That is the low-change path when many apps already call the Azure OpenAI endpoint; creating a brand-new Foundry resource instead means a new endpoint and new keys for every caller.
Choosing the isolation boundary
Because model deployments and networking live on the resource, the boundary you pick decides what is shared:
| Design | Shared | Separate | Fits |
|---|---|---|---|
| Several projects under one Foundry resource | Model deployments and their quota, network rules, resource-level role assignments | Agents, files, evaluations, project-level access | Teams that should reuse the same managed model deployments but keep their work and access apart |
| Separate Foundry resources (each with its own project) | Nothing at the resource level | Deployments and quota, networking, role assignments, keys | Dev/test/prod, where a load test must not drain prod capacity and prod security must change independently |
| One project shared by several teams | Everything, including the access boundary | Only names | Rarely — naming prefixes are not isolation |
Separate deployments inside one resource do give each workload its own tokens-per-minute limit, but network rules and resource-scoped role assignments remain shared, so they are not a full environment boundary.
Which deployment type keeps prompts where you need them?
The deployment type — not the resource's region — decides where prompts and responses are processed. The resource region governs data stored at rest; a Global deployment of a resource in an EU region may still process inferencing in any Azure region. Each type has a processing scope and a billing model:
| Processing scope | Pay per token | Reserved capacity (PTU) | Asynchronous batch |
|---|---|---|---|
| Global — any Azure region | Global Standard (GlobalStandard) | Global Provisioned (GlobalProvisionedManaged) | Global Batch (GlobalBatch) |
| Data zone — a Microsoft-defined zone such as the EU or US | Data Zone Standard (DataZoneStandard) | Data Zone Provisioned (DataZoneProvisionedManaged) | Data Zone Batch (DataZoneBatch) |
| Azure geography of the deployment | Standard (Standard) | Regional Provisioned (ProvisionedManaged) | — |
Two rules decide most residency scenarios:
- Wider scope means higher default quota and more capacity. Global types carry the highest default quotas; Data Zone types sit between Global and the geography-based types. When a requirement is "EU-only" and also asks for the most quota, Data Zone Standard beats Standard.
- A data zone spans several countries. The EU data zone follows the EU Data Boundary, and other zones (for example in Asia Pacific) also cover multiple countries. A rule that processing stays inside one country's geography — Switzerland, Australia — needs a geography-based type: Standard for pay-per-token, Regional Provisioned for reserved capacity.
The Developer type (DeveloperTier) has no data residency guarantee at all, so treat it like a Global type when governing residency.
Standard, provisioned, batch or Developer: matching the workload
After residency, the workload's shape picks the billing model. Standard types are best-effort shared capacity billed per token; Provisioned types reserve throughput in provisioned throughput units (PTUs) billed per hour whether used or not; Batch types process files of requests asynchronously; Developer exists only to test fine-tuned models.
| Workload | Type family | Why |
|---|---|---|
| Bursty or light interactive traffic | Standard (Global, Data Zone or geography) | Pay only for tokens used; latency can vary under heavy load |
| Steady, high-volume interactive traffic that needs predictable latency | Provisioned (Global, Data Zone or Regional) | Reserved PTU capacity gives lower, more consistent latency; idle hours are still billed |
| Large offline jobs that can wait up to a day | Batch (Global or Data Zone) | About 50% below the Global Standard price, a 24-hour target turnaround (not a guarantee or real-time SLA), and a separate enqueued-token quota so bulk work does not consume the online deployment's quota |
| A short evaluation of a fine-tuned model | Developer | Low cost, no SLA, no residency guarantee, and the deployment is deleted automatically after 24 hours |
Adding another Standard deployment adds quota headroom but not latency consistency — both are still best-effort. And because a Developer deployment disappears after 24 hours, never point a staging or production app at one; redeploy the fine-tuned model as Standard or Global Standard instead.
Priority, flex and default processing on standard deployments
Standard deployments of supported models can also run requests at different processing tiers, chosen with the service_tier request parameter (or, for priority, enabled on the whole deployment). The tier changes latency and price without changing the deployment type, so residency still comes from the type.
service_tier | Behaviour | Price | Use for |
|---|---|---|---|
priority | Lower, more consistent latency without reserving PTUs; can be turned on at the deployment level or per request | Higher than standard, pay per token | Latency-sensitive traffic that is hard to forecast, where nobody will pay for idle reserved capacity |
default | Standard processing — and it overrides a deployment set to priority | Standard rate | Requests on a priority deployment that should be billed normally (for example a report job) |
auto | Uses the tier configured on the deployment (priority, if the deployment has it on) | Depends on the deployment | The default when you send nothing |
flex (preview) | Delay-tolerant, preemptible capacity; requests stay synchronous but can be slower or rejected with a 429, and there is no automatic fallback | About half the standard rate | Background work that must keep a synchronous call pattern; retry with backoff and finally resend as default to guarantee completion |
Priority processing is offered on Global Standard and on US Data Zone Standard deployments, so a US-only workload can have priority latency while keeping data-zone residency. It draws on the same quota as standard processing, and under ramp-rate limits or peak load a priority request can be served at standard processing and billed at the standard rate. Flex is narrower: it is available only on Global Standard deployments of supported models and shares that deployment's quota. Flex differs from Batch in the integration, not just the price: Batch means uploading an input file and polling an asynchronous job, while Flex keeps existing synchronous calls. Both tiers depend on the model being supported, so check the model list before designing around them.
Serverless API or managed compute?
Foundry deploys catalog models in one of two ways, and the model usually decides which. Serverless API deployments serve Foundry Models sold by Azure and selected partner models on Microsoft-managed shared capacity, billed per token, with the deployment types above. Managed compute (preview) hosts open-weight, partner and custom-weight models — for example the Hugging Face collection — on dedicated GPU virtual machines that Foundry sizes and patches, with a curated serving runtime, billed per hour for the compute.
| Capability | Serverless API | Managed compute |
|---|---|---|
| Models | Foundry Models sold by Azure, selected partner models | Open-weight and custom models not offered serverless |
| Billing | Per token (or PTU for provisioned types) | Per hour for the dedicated compute |
| Data processing options | Global, data zone and geography types | Currently global only |
| Built-in, configurable content filtering | Yes | Not available in the preview — add your own moderation |
| Infrastructure you manage | None | None (Foundry manages the VMs and runtime), but you choose the size |
When a model is offered both ways, Serverless API is the default choice: it brings built-in filters, data-zone options and provisioned capacity that managed compute lacks. Self-hosting on Azure Kubernetes Service or Container Apps can run any model, but it hands the cluster and serving runtime back to your team.
How do model versions and upgrade policies work?
Every model deployment pins a model version, and its version upgrade option (versionUpgradeOption) decides what happens when Microsoft sets a new default version or retires the current one. The api-version query parameter is unrelated: it selects the API contract, not the model version.
| Option | What happens | Fits |
|---|---|---|
OnceNewDefaultVersionAvailable | The deployment moves to a new default version shortly after Microsoft designates it (within about two weeks) | Teams that want improvements early and do not gate version changes on their own tests |
OnceCurrentVersionExpired | Stays on the current version until its retirement date, then upgrades automatically to the current default | Stay on the validated version as long as possible but never fail at retirement |
NoAutoUpgrade | Never upgrades; the deployment stops working when the version retires | Full control — only safe with a migration plan finished before retirement |
Both automatic options can put an untested version into production before a regression suite runs. When a regulated workload must evaluate every change and avoid a retirement outage, the pattern is NoAutoUpgrade on production plus a planned migration: deploy the new version as a separate deployment, evaluate it, then switch the application before the retirement date.
Model deployments as code and deployment governance
A model deployment is a child resource of the Foundry resource — Microsoft.CognitiveServices/accounts/deployments — so it can be created with the Azure CLI, Bicep or ARM like any other resource. The deployment type is the deployment's SKU: sku.name (CLI --sku-name) takes values such as GlobalStandard, DataZoneStandard or GlobalProvisionedManaged, and sku.capacity (--sku-capacity) sets the quota or PTUs. The model's format, name and version, the versionUpgradeOption and the content filter (raiPolicyName) are deployment properties.
az cognitiveservices account deployment create \
-n $accountName -g $resourceGroupName \
--deployment-name chat-model \
--model-name gpt-4.1 --model-version 2025-04-14 \
--model-format OpenAI \
--sku-name DataZoneStandard --sku-capacity 50
Do not confuse the deployment SKU with the account's --kind (for example AIServices), which is set when the Foundry resource itself is created.
Governing which types can be created
Because the type is a property of the deployment resource, Azure Policy can evaluate the deployment's sku.name and deny the ones you do not allow. To keep all inferencing inside the EU, deny the Global SKUs (GlobalStandard, GlobalProvisionedManaged, GlobalBatch) and DeveloperTier across the management group or subscriptions. A policy on resource location cannot do this — every resource may already sit in an EU region — and an RBAC role that removes deployment rights blocks compliant types too.
Basic vs standard agent setup in Foundry Agent Service
The agent setup decides where Foundry Agent Service stores agent state. Basic setup keeps conversations, files and vector stores in Microsoft-managed resources — quickest to start. Standard setup brings your own Azure resources in your own tenant, so all agent data stays under your control:
| Your resource (standard setup) | Holds |
|---|---|
| Azure Cosmos DB for NoSQL | Threads: messages, conversation history and agent metadata |
| Azure Storage | Files uploaded to agents |
| Azure AI Search | The vector stores agents create |
| Azure Key Vault | Secrets and connection strings (not conversations or vectors) |
A customer-managed key encrypts data but does not move it into resources you own, and diagnostic logs copy telemetry rather than the agent's state — neither substitutes for standard setup when ownership is the requirement.
Capability settings are fixed at project creation
The links from a project to its Cosmos DB, Storage and AI Search resources are capability settings. They can be set on the account (as defaults for new projects) or on the project, but they cannot be updated on an existing project. Moving a basic-setup project to your own stores therefore means creating a new project with the right capability settings and recreating the agents there; redeploying the template or adding ordinary project connections does not change where agent state lives.
Standard setup also isolates data per project: each project gets its own Cosmos DB containers with their own throughput, so the Cosmos DB account's total throughput must grow with every project. A throughput error while provisioning a new project points at the account's RU/s, while a missing role assignment shows up as authorization failures when agents run.
Prompt agents vs hosted agents
A prompt agent is declarative: a model deployment, instructions and tools configured in the portal or SDK, which Foundry runs for you with no code or containers to own. A hosted agent is your own agent code — LangGraph, Microsoft Agent Framework or custom orchestration — packaged as a container image in Azure Container Registry and run by Foundry with a managed endpoint, per-session scaling, a Microsoft Entra identity and built-in tracing. Choose a prompt agent when instructions plus tools are enough; choose a hosted agent when you have custom orchestration code but still want Foundry's managed runtime instead of operating Container Apps or AKS yourself. (Managed compute is not an agent runtime — it hosts model weights.)
Hosted agent versions
- Each version is an immutable snapshot of the container image, CPU and memory, environment variables and protocol configuration. Changing any of them — a new model deployment name in an environment variable, a bigger size — means creating a new version.
- An agent endpoint sends all traffic to one version. There is no percentage traffic split; rolling back means deploying the previous version again.
- Hosted agents scale per session: each session gets its own VM-isolated sandbox of the version's size (sizes such as 0.5 vCPU/1 GiB up to 2 vCPU/4 GiB), released after an idle timeout. There are no replica counts or warm pools, and cost follows CPU and memory across active sessions — oversizing multiplies with concurrency.
Protocols
| Protocol | Caller sends | Fits |
|---|---|---|
| Responses | The OpenAI-compatible responses contract; the platform manages history and streaming | Conversational agents (the default) |
| Invocations | Arbitrary JSON you define; the container manages any state | Webhooks and other callers whose payload you cannot change, non-chat processing |
| Activity | Channel activities; the agent keeps the Responses protocol for its logic | Teams / Microsoft 365 channels (bridged automatically from Responses when the agent is published there, with no separate wiring) |
| A2A | Agent-to-agent requests | Delegation between agents |
| Invocations (WebSocket) | A bidirectional stream | Real-time voice and other bidirectional streaming |
Identity
Each hosted agent gets a dedicated Microsoft Entra agent identity that its container uses at runtime for models, tools and downstream Azure services. To let one agent read your storage account without keys, assign the data role (for example Storage Blob Data Reader) to that agent's identity. The project managed identity is used by the platform for infrastructure tasks such as pulling the image from the registry and is shared across the project, so granting it access widens the scope to every agent. Never put connection strings, keys or SAS tokens in the image or a version's environment variables.
Integrating Foundry projects with CI/CD pipelines
CI/CD for Foundry means treating everything as code — infrastructure, model deployments and agent definitions — and promoting it through separate dev, test and prod environments with keyless authentication and an evaluation gate.
Agents as code
Store agent definitions in the repository, review them by pull request, and let the pipeline create them in each environment's project. In the azure-ai-projects 2.x SDK, project.agents.create_version(agent_name=..., definition=PromptAgentDefinition(model=..., instructions=...)) creates the agent, or a new immutable version if the name already exists, giving the evaluation step a name:version to reference. create_agent and update_agent belong to the classic assistants-style API, where agents were edited in place; get_openai_client returns a client for calling agents and models.
Keyless pipeline authentication
Pipelines should hold no long-lived Azure secrets. With workload identity federation (OpenID Connect), the pipeline exchanges a short-lived token from its own identity provider for a Microsoft Entra access token:
- GitHub Actions: grant the job
permissions: id-token: writeso GitHub issues an OIDC token, add a federated credential on the app registration (or user-assigned managed identity) whose subject matches the repository and branch or environment, and callazure/loginwith the client, tenant and subscription IDs — no client secret. - Azure DevOps: use an Azure Resource Manager service connection with workload identity federation.
Client secrets, Foundry API keys and personal access tokens stored as pipeline secrets are exactly what this avoids; an API key also only authorizes data-plane calls and cannot deploy Bicep. Give the pipeline identity least-privilege roles for what it does: a control-plane role on the resource to create deployments, and the Foundry User role (formerly Azure AI User) on the project to create agents.
Evaluation gates
| Pipeline | Evaluation step |
|---|---|
| GitHub Actions | The microsoft/ai-agent-evals action with a data file of queries and evaluators |
| Azure DevOps | The AIAgentEvaluation@2 task |
Both invoke the agents with the dataset, score the answers with Foundry evaluators and publish a summary in the run. Agents are listed as comma-separated agent-name:version values; when several are listed the report compares them with statistical significance against a baseline — the agent named in baseline-agent-id, or the first agent listed if that input is omitted. List the production version first (or name it as the baseline) so the new version is judged against it, and fail the pipeline when scores regress.
A sound promotion design combines these: definitions in source control, a new version created by the pipeline in each environment's project, and an evaluation gate before prod. Editing agents directly in the prod portal, merging environments into one project, or tightening content filters (which detect harmful categories, not answer quality) do not provide review or quality gating.
Tip. Questions in this topic are scenario-based. Deployment items give a residency rule, a traffic pattern and a cost or quota constraint and ask for the deployment type or processing tier, so you need to separate where prompts are processed (Global, data zone, geography) from how capacity is billed (per token, PTU, batch). Infrastructure items ask how to split teams or environments across Foundry resources and projects, how to keep an Azure OpenAI endpoint while moving to Foundry, and how to restrict deployment types with policy. Agent items contrast basic and standard setup, which resource stores which data, prompt and hosted agents, hosted agent versioning, protocols and identity. Expect short CLI and Python snippets asking which parameter, value or method completes them, version upgrade options, and pipeline items on OIDC sign-in and evaluation inputs. Some items ask you to select two answers.
- A Foundry resource holds model deployments, networking and resource-level RBAC; Foundry projects hold agents and files. Separate resources isolate environments; projects under one resource share deployments.
- Upgrading an Azure OpenAI resource to a Foundry resource keeps its endpoint and keys; hub-based projects are Foundry (classic).
- The deployment type, not the resource region, decides where prompts are processed: Global (any region), Data Zone (a multi-country zone), Standard and Regional Provisioned (one Azure geography).
- Provisioned (PTU) gives predictable latency for steady volume; Batch is about half price with a 24-hour target and its own quota; Developer is a 24-hour, no-SLA deployment for testing fine-tuned models.
- service_tier: priority buys latency per token, default overrides a priority deployment, flex is half price but preemptible with no automatic fallback.
- Serverless API has built-in filters and data-zone options; managed compute hosts open-weight models, is global only and has no built-in filtering in preview.
- versionUpgradeOption: OnceNewDefaultVersionAvailable, OnceCurrentVersionExpired or NoAutoUpgrade (plus a migration plan before retirement).
- Deployment type is the deployment's sku.name, so Azure Policy on sku.name governs which types can exist.
- Standard agent setup: Cosmos DB for threads, Storage for files, AI Search for vector stores; capability settings cannot change on an existing project.
- Hosted agent versions are immutable, one version serves all traffic, scaling is per session, and each agent has its own Entra agent identity; pipelines use OIDC and an evaluation gate before prod.
Frequently asked questions
Does creating a Foundry resource in an EU region keep all AI processing in the EU?
No. The resource region governs where data is stored at rest, but the deployment type decides where prompts and responses are processed. Global deployment types can process requests in any Azure region. To keep processing inside the EU, use a Data Zone type in the EU data zone or a geography-based Standard or Regional Provisioned deployment, and use Azure Policy on the deployment SKU to deny Global and Developer types.
What is the difference between Data Zone Standard and Standard deployments in Foundry?
Both bill per token and keep processing out of the global pool. Data Zone Standard processes requests anywhere within a Microsoft-defined multi-country zone, such as the EU or US, and has higher default quotas. Standard processes requests within the Azure geography of the deployment, which is the choice when a single country's boundary, such as Switzerland, is required.
When should I use a Batch deployment instead of Standard or Provisioned?
Use Global Batch or Data Zone Batch for large asynchronous jobs that can wait up to a day. Batch costs about half the Global Standard price, targets a 24-hour turnaround without a real-time guarantee, and uses a separate enqueued-token quota so it does not consume the quota of online deployments. Interactive traffic belongs on Standard or Provisioned deployments.
What is the Developer deployment type in Microsoft Foundry?
The Developer type is a low-cost deployment for evaluating fine-tuned models. It has no SLA and no data residency guarantee, and it is deleted automatically 24 hours after creation, so an application should never depend on one. Deploy the fine-tuned model as Standard or Global Standard for anything longer-lived.
What is the difference between basic and standard agent setup in Foundry Agent Service?
Basic agent setup stores conversations, files and vector stores in Microsoft-managed resources. Standard agent setup uses your own Azure Cosmos DB for NoSQL for threads and conversation history, Azure Storage for files and Azure AI Search for vector stores, so agent data stays in your tenant. The choice is made through capability settings when a project is created and cannot be changed on an existing project.
How do I change the configuration of a hosted agent in Foundry?
Create a new agent version. A hosted agent version is an immutable snapshot of its container image, CPU and memory, environment variables and protocols, and an endpoint routes all traffic to one version. To change a setting, create and deploy a new version; to roll back, deploy the previous version again.
How should a GitHub Actions workflow authenticate to Azure to deploy Foundry resources and agents?
Use OpenID Connect workload identity federation. Grant the job the id-token: write permission, add a federated credential on the Microsoft Entra app registration or managed identity that matches the repository and branch or environment, and sign in with azure/login using client, tenant and subscription IDs. No client secret or API key is stored.
How do I gate an agent release on evaluation results in a pipeline?
Run the microsoft/ai-agent-evals action in GitHub Actions or the AIAgentEvaluation@2 task in Azure DevOps against a dataset of test queries. List agents as agent-name:version values; the report compares them against the baseline set by baseline-agent-id, or the first agent listed when it is omitted. Fail the pipeline when the new version's scores regress before promoting it to production.
Source
This lesson covers the "Plan and manage an Azure AI solution" domain of the official AI-103 exam guide. Vendors revise their guides — check the source for the current version.
- Microsoft AI-103 study guide — Microsoft Learn
Sign up free to mark lessons complete, bookmark topics and track your exam readiness.