Blog Post

Microsoft Developer Community Blog
16 MIN READ

Infrastructure as Code for AI: Building and Deploying Microsoft Hosted Agents with Terraform

Lee_Stott's avatar
Lee_Stott
Icon for Microsoft rankMicrosoft
Jun 02, 2026

AI agents are no longer experimental. Teams are shipping production-grade agents that retrieve information, call APIs, reason over documents, and orchestrate multi-step workflows at scale. Microsoft Foundry's Hosted Agents service gives you a fully managed runtime for those agents, built on top of the Microsoft Foundry Agent Service, with Microsoft handling the infrastructure, scaling, and runtime lifecycle.

The challenge is that provisioning this infrastructure by hand or clicking through the portal, running one-off CLI commands, or relying on undocumented shell scripts, simply does not scale. It introduces configuration drift, makes reproducing environments painful, and creates real governance risk as teams grow.

This post walks through how to provision and manage the Azure infrastructure required to run Microsoft Hosted Agents using Terraform. You will leave with working configuration, a clear understanding of the resource model, and practical guidance on where Terraform can take you all the way and where you will need to supplement with the Azure CLI or the Microsoft Foundry Agent Service SDK.


What Are Microsoft Hosted Agents?

Microsoft Hosted Agents are AI agents deployed and managed within Microsoft Foundry. Microsoft Foundry is Microsoft's unified platform for building, evaluating, and deploying AI applications and agents. It provides:

  • A managed compute runtime — Microsoft provisions and scales the infrastructure so you do not manage VMs or containers.
  • An agent execution environment — agents are defined with instructions, tools (code interpreter, Bing grounding, Azure AI Search, function calling), and a backing model endpoint.
  • Deep Azure integration — identity via Microsoft Entra ID, secrets via Azure Key Vault, storage via Azure Blob, tracing via Azure Monitor and Application Insights.
  • A project-scoped model — each Microsoft Foundry project encapsulates an agent's resources, connections, and deployments within a logical boundary.

The "Hosted" distinction matters. You are not running agent code on your own Kubernetes cluster or App Service. Microsoft manages the runtime. Your responsibility is to provision the surrounding infrastructure correctly: the Microsoft Foundry resource, the project, the model deployment, the identity configuration, and the monitoring resources that back it all.

That boundary — the infrastructure you own — is exactly what Terraform manages well.

Why Terraform for Hosted Agent Deployments?

Infrastructure as Code (IaC) is not a new idea, but its importance grows as AI deployments become more complex. Here is why Terraform is a strong choice for Microsoft Foundry deployments specifically:

  • Repeatability: A Terraform configuration produces the same infrastructure every time. Staging mirrors production. Disaster recovery is a terraform apply away.
  • Governance: Infrastructure definitions live in version control alongside application code. Changes are reviewable, auditable, and reversible. This satisfies most enterprise change-management requirements.
  • Scale: Spinning up per-customer or per-team agent environments using Terraform workspaces or module instantiation is far more manageable than manual provisioning.
  • State management: Terraform tracks the actual state of your Azure resources. It detects drift and reconciles it declaratively.
  • Ecosystem: The AzureRM provider is mature, actively maintained by HashiCorp and Microsoft, and covers the majority of Azure services including the Microsoft Foundry resources.

Architecture Overview

Before writing any Terraform, it helps to understand the resource hierarchy in Microsoft Foundry and how each layer maps to an Azure resource type.

The Foundry Resource Hierarchy

Microsoft Foundry uses a two-level hierarchy:

1. Foundry Account (azurerm_cognitive_account, kind: AIServices) — The top-level AI Services resource. It provides the model endpoint, manages agent execution, and acts as the logical boundary for all projects beneath it. You must set project_management_enabled = true and provide a custom_subdomain_name to enable project creation. In ARM terms this is a Microsoft.CognitiveServices/accounts resource.

2. Foundry Project (azurerm_cognitive_account_project) — A child resource scoped within the Foundry Account. Each project has its own agents, model deployments, connections, and data assets. In production, you typically have one project per application, product team, or environment.

Figure 1: The Microsoft Foundry resource hierarchy. A single Foundry Account (Cognitive Services, kind AIServices) acts as the top-level container, with Projects scoped beneath it — one per application, team, or environment.

Supporting Resources

The following Azure resources make up a complete Hosted Agents deployment:

  • Microsoft Foundry Account (AI Services): A single azurerm_cognitive_account of kind AIServices serves as both the Foundry Account and the model endpoint host. Model deployments (e.g. gpt-4.1) are provisioned via azurerm_cognitive_deployment within this account.
  • Log Analytics Workspace + Application Insights: Provides observability for agent traces, request logs, and metrics.
  • User-Assigned Managed Identity: Grants the Foundry Account and Projects access to Azure resources without stored credentials.
  • Role Assignments (RBAC): Wires the managed identity to the Foundry Account with least-privilege Cognitive Services permissions.

Figure 2: Supporting infrastructure map. The managed identity holds least-privilege RBAC grants to the Microsoft Foundry Account (AI Services) — enabling model access and project management — all within the same resource group.

Reference Architecture (Described)

A production-ready layout separates concerns across two resource groups: one for shared infrastructure (networking, monitoring) and one for the Microsoft Foundry Account and its projects. The Foundry resource group houses the azurerm_cognitive_account (kind: AIServices) resource and the azurerm_cognitive_account_project instances. The shared resource group holds Log Analytics and Application Insights. A user-assigned managed identity spans both, holding RBAC grants to each backing service.

For a dev/test environment you can collapse both into a single resource group. For production, the separation makes cost attribution, access control, and lifecycle management cleaner.


Prerequisites

Accounts and Permissions

  • An active Azure subscription with the Owner or Contributor + User Access Administrator roles at the subscription or resource group level (role assignments require elevated permission).
  • Foundry access enabled in your subscription. In some tenants you may need to accept terms or request quota for Azure OpenAI.
  • Azure OpenAI quota for the model you intend to deploy (e.g. gpt-4.1). Request this via the Azure portal under Quotas in Azure OpenAI Studio.

Local Tools

  • Terraform CLI ≥ 1.9 — Install guide
  • Azure CLI ≥ 2.60 — Install guide
  • A code editor (VS Code with the HashiCorp Terraform extension and the Azure Terraform extension is a strong combination).

Authentication

For local development, authenticate via the Azure CLI. The AzureRM Terraform provider picks this up automatically:

az login
az account set --subscription "<your-subscription-id>"

For CI/CD pipelines, use a service principal with AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID, and AZURE_SUBSCRIPTION_ID environment variables, or — preferably — a workload identity federation (federated credentials) to avoid storing long-lived secrets. GitHub Actions supports OIDC-based workload identity natively.


Terraform Fundamentals for Hosted Agents

Provider Configuration

The hashicorp/azurerm provider is your primary dependency. The new Microsoft Foundry resources (azurerm_cognitive_account with kind = "AIServices" and azurerm_cognitive_account_project) require version 4.x of the provider. Pin your version to avoid unexpected breaking changes:

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

provider "azurerm" {
  features {
    key_vault {
      purge_soft_delete_on_destroy = false
    }
    resource_group {
      prevent_deletion_if_contains_resources = true
    }
  }
  subscription_id = var.subscription_id
}

The features block is required even when empty. The Key Vault setting prevents accidental secret loss during terraform destroy. The resource group setting adds an extra safety net in production.

State Management

Never use local state for shared or production environments. Store state in Azure Blob Storage with state locking via Azure Blob lease:

terraform {
  backend "azurerm" {
    resource_group_name  = "rg-terraform-state"
    storage_account_name = "sttfstate<unique>"
    container_name       = "tfstate"
    key                  = "ai-agents/prod.tfstate"
  }
}

Create the state storage account and container before running terraform init. A bootstrap script or a separate Terraform workspace dedicated to state management are both valid approaches.

Known Limitations and Workarounds

Terraform coverage of Foundry is improving rapidly but is not yet complete. You should be aware of the following gaps as of mid-2025:

  • Agent definitions are not in Terraform: The actual agent (its system prompt, instructions, tool configuration, and model binding) is created via the Azure AI Agent Service SDK or the Foundry portal, not via Terraform. Terraform provisions the infrastructure; your application code or a post-provisioning script creates the agent.
  • Connections: Some connection types within a Foundry Project (e.g. Azure AI Search, custom connections) may require the Azure CLI or the Foundry SDK. Verify coverage in the AzureRM provider docs before assuming Terraform handles them.
  • Model deployments: azurerm_cognitive_deployment covers OpenAI model deployments and is well-supported. Use this to deploy your model before referencing it from the agent.
  • Private networking: If you need private endpoints for your Foundry Account, additional VNet, subnet, and DNS zone resources are required. This post focuses on the public networking path; private networking is a follow-on topic.

Step-by-Step Implementation

The following sections build up a complete Terraform configuration. The recommended project structure is a flat module layout for a single environment, with a separate modules/ai-foundry/ directory when you need to reuse the pattern across environments.

ai-agents-infra/
├── main.tf
├── variables.tf
├── outputs.tf
├── versions.tf
└── terraform.tfvars

1. Variables

Define variables first. Parameterising from the start avoids hard-coded values that create technical debt when you replicate the configuration for staging or production:

# variables.tf

variable "subscription_id" {
  type        = string
  description = "Azure subscription ID."
}

variable "location" {
  type        = string
  default     = "eastus"
  description = "Azure region for all resources."
}

variable "environment" {
  type        = string
  default     = "dev"
  description = "Environment label (dev, staging, prod)."
}

variable "project_name" {
  type        = string
  description = "Short name for the project. Used in resource naming."
}

variable "openai_model_name" {
  type        = string
  default     = "gpt-4.1"
  description = "Azure OpenAI model to deploy for the agent."
}

variable "openai_model_version" {
  type        = string
  default     = "2025-04-14"
  description = "Model version to deploy."
}

variable "openai_sku_capacity" {
  type        = number
  default     = 10
  description = "Tokens-per-minute capacity (in thousands) for the deployment."
}

2. Resource Group and Core Infrastructure

A single resource group keeps things simple for dev. In production, consider splitting as described in the architecture section above.

# main.tf — Resource group and naming locals

locals {
  name_prefix = "${var.project_name}-${var.environment}"
  tags = {
    environment = var.environment
    project     = var.project_name
    managed_by  = "terraform"
  }
}

resource "azurerm_resource_group" "main" {
  name     = "rg-${local.name_prefix}"
  location = var.location
  tags     = local.tags
}

3. Supporting Services

Provision Log Analytics and Application Insights for agent observability and diagnostics. Unlike the legacy Hub-based architecture, the azurerm_cognitive_account (kind AIServices) does not require a dedicated Storage Account or Key Vault as provisioning dependencies.

# main.tf — Monitoring infrastructure

data "azurerm_client_config" "current" {}

# Log Analytics Workspace (required by Application Insights)
resource "azurerm_log_analytics_workspace" "main" {
  name                = "law-${local.name_prefix}"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  sku                 = "PerGB2018"
  retention_in_days   = 30
  tags                = local.tags
}

# Application Insights for agent observability
resource "azurerm_application_insights" "main" {
  name                = "appi-${local.name_prefix}"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  workspace_id        = azurerm_log_analytics_workspace.main.id
  application_type    = "web"
  tags                = local.tags
}

4. User-Assigned Managed Identity

A managed identity allows the Foundry Account and its projects to authenticate to Azure services without stored credentials. This is a security best practice and is required for several Microsoft Foundry features.

# main.tf — Managed identity for the Microsoft Foundry Account

resource "azurerm_user_assigned_identity" "foundry" {
  name                = "id-${local.name_prefix}-foundry"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  tags                = local.tags
}

5. Microsoft Foundry Account and Model Deployment

In the current Microsoft Foundry architecture, a single azurerm_cognitive_account of kind AIServices serves as both the Foundry Account and the model endpoint host. Set project_management_enabled = true and provide a globally unique custom_subdomain_name to enable Foundry Project creation beneath it.

# main.tf — Microsoft Foundry Account (AI Services)

resource "azurerm_cognitive_account" "foundry" {
  name                       = "aisa-${local.name_prefix}"
  resource_group_name        = azurerm_resource_group.main.name
  location                   = azurerm_resource_group.main.location
  kind                       = "AIServices"
  sku_name                   = "S0"
  project_management_enabled = true
  custom_subdomain_name      = "${replace(local.name_prefix, "-", "")}foundry"
  tags                       = local.tags

  identity {
    type         = "UserAssigned"
    identity_ids = [azurerm_user_assigned_identity.foundry.id]
  }
}

# Deploy the model within the Foundry Account
resource "azurerm_cognitive_deployment" "agent_model" {
  name                 = var.openai_model_name
  cognitive_account_id = azurerm_cognitive_account.foundry.id

  model {
    format  = "OpenAI"
    name    = var.openai_model_name
    version = var.openai_model_version
  }

  sku {
    name     = "Standard"
    capacity = var.openai_sku_capacity
  }
}

Note on quota: The capacity value is in thousands of tokens per minute. A value of 10 means 10,000 TPM. If terraform apply fails with a quota error, reduce this value or request a quota increase via the Azure portal.

Note on custom_subdomain_name: This must be globally unique across all Azure AI Services accounts. If provisioning fails with a conflict error, adjust the suffix (e.g. append a random string using the random_string resource).

6. Foundry Project

Create a Foundry Project beneath the Foundry Account provisioned in Step 5. Each project scopes its own agents, model connections, and data assets. Use one project per application or team.

# main.tf — Microsoft Foundry Project

resource "azurerm_cognitive_account_project" "agent_project" {
  name                 = "proj-${local.name_prefix}-agents"
  cognitive_account_id = azurerm_cognitive_account.foundry.id
  location             = azurerm_resource_group.main.location
  display_name         = "Agent Project - ${var.project_name}"
  description          = "Hosted agents project for ${var.project_name}"

  identity {
    type         = "UserAssigned"
    identity_ids = [azurerm_user_assigned_identity.foundry.id]
  }

  tags = local.tags
}

7. RBAC Role Assignments

Grant the managed identity the permissions it needs. This is the area most commonly misconfigured in manual deployments. Terraform makes it explicit and auditable.

# main.tf — RBAC assignments

# AI Services: Foundry identity needs Cognitive Services OpenAI User to call model endpoints
resource "azurerm_role_assignment" "foundry_openai" {
  scope                = azurerm_cognitive_account.foundry.id
  role_definition_name = "Cognitive Services OpenAI User"
  principal_id         = azurerm_user_assigned_identity.foundry.principal_id
}

# AI Services: Foundry identity needs Cognitive Services Contributor to manage projects
resource "azurerm_role_assignment" "foundry_contributor" {
  scope                = azurerm_cognitive_account.foundry.id
  role_definition_name = "Cognitive Services Contributor"
  principal_id         = azurerm_user_assigned_identity.foundry.principal_id
}

# Optional: grant your own principal the Azure AI Developer role on the Foundry Account
# so you can create and manage agents from your local machine or CI pipeline
resource "azurerm_role_assignment" "developer_account" {
  scope                = azurerm_cognitive_account.foundry.id
  role_definition_name = "Azure AI Developer"
  principal_id         = data.azurerm_client_config.current.object_id
}

8. Outputs

Export the values your application and post-provisioning scripts will need:

# outputs.tf

output "resource_group_name" {
  value = azurerm_resource_group.main.name
}

output "foundry_account_id" {
  value = azurerm_cognitive_account.foundry.id
}

output "ai_foundry_project_id" {
  value = azurerm_cognitive_account_project.agent_project.id
}

output "foundry_endpoint" {
  value = azurerm_cognitive_account.foundry.endpoint
}

output "openai_deployment_name" {
  value = azurerm_cognitive_deployment.agent_model.name
}

output "managed_identity_client_id" {
  value = azurerm_user_assigned_identity.foundry.client_id
}

10. Example terraform.tfvars

# terraform.tfvars — do NOT commit this file if it contains sensitive values
subscription_id      = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
location             = "eastus"
environment          = "dev"
project_name         = "contoso-agents"
openai_model_name    = "gpt-4.1"
openai_model_version = "2025-04-14"

openai_sku_capacity = 10


Figure 3: Terraform deployment workflow. State is stored in an Azure Blob Storage backend, enabling team collaboration and preventing concurrent apply conflicts.

Deploying and Validating the Agent Infrastructure

Running the Deployment

# 1. Initialise — downloads provider plugins and configures the backend
terraform init

# 2. Validate syntax and configuration
terraform validate

# 3. Preview what will be created (review carefully before applying)
terraform plan -out=tfplan

# 4. Apply the plan
terraform apply tfplan

A full initial apply typically takes 8–15 minutes. The Foundry Account (AI Services) provisioning is the longest step. The model deployment may also take a few minutes to reach a ready state — Terraform handles this with implicit dependency ordering, but you may see brief retries in the output.

Verifying the Deployment

After apply completes, verify each resource is in a healthy state:

# Confirm the resource group and its resources exist
az resource list --resource-group "rg-contoso-agents-dev" --output table

# Check the Foundry Account (AI Services) is in a Succeeded state
az cognitiveservices account show \
  --name "aisacontosoagentsdevfoundry" \
  --resource-group "rg-contoso-agents-dev" \
  --query "properties.provisioningState"

# Confirm the model deployment is ready
az cognitiveservices account deployment show \
  --resource-group "rg-contoso-agents-dev" \
  --name "aisacontosoagentsdevfoundry" \
  --deployment-name "gpt-4.1" \
  --query "properties.provisioningState"

Navigate to the Microsoft Foundry portal and confirm your Foundry Account and Project appear. At this point you can create an agent manually in the portal to validate that the model endpoint is reachable and the identity chain works correctly before automating agent creation.

Common Deployment Issues

  • Quota exceeded on model deployment: Reduce openai_sku_capacity or request a quota increase in the Azure portal under Azure OpenAI → Quotas.
  • Resource name conflicts: The custom_subdomain_name on the Foundry Account must be globally unique. Use the random_string Terraform resource to append a unique suffix if needed.
  • Role assignment propagation delay: RBAC changes can take 1–2 minutes to propagate. If the Foundry Account cannot access resources immediately after apply, wait a moment and retry.
  • project_management_enabled not set: If azurerm_cognitive_account_project fails with an error about project management, ensure project_management_enabled = true and custom_subdomain_name are set on the parent azurerm_cognitive_account.
  • azurerm_cognitive_account_project not found: Ensure your AzureRM provider version is ~> 4.0 or later. Run terraform init -upgrade if you previously initialised with an older version.

Creating an Agent After Infrastructure Provisioning

Terraform has provisioned the platform. Now you need to create the agent itself. This is done via the Azure AI Agents SDK (available for Python, C#, JavaScript, and Java) or the Foundry portal.

The following Python snippet demonstrates creating a basic agent programmatically after Terraform apply. It uses the outputs from Terraform directly:

import os
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential

# These values come from Terraform outputs
project_connection_string = os.environ["AI_PROJECT_CONNECTION_STRING"]
model_deployment = os.environ["OPENAI_DEPLOYMENT_NAME"]

client = AIProjectClient.from_connection_string(
    credential=DefaultAzureCredential(),
    conn_str=project_connection_string,
)

# Create the hosted agent
agent = client.agents.create_agent(
    model=model_deployment,
    name="customer-support-agent",
    instructions=(
        "You are a helpful customer support assistant. "
        "Answer questions accurately and concisely. "
        "If you are unsure, say so rather than guessing."
    ),
)

print(f"Agent created: {agent.id}")

Figure 5: Agent runtime architecture. The Foundry Project hosts the Agent Service, which routes requests to the GPT-4.1 model endpoint and optionally invokes tool integrations (Code Interpreter, File Search, Azure Functions, or custom tools).

The project connection string is available from the Foundry portal (Project → Overview → Project connection string) or can be constructed from Terraform outputs. Refer to the Azure AI Agents quickstart for the full SDK setup.


Operational Considerations

Lifecycle Management

Terraform's declarative model means updates are incremental by default. To update the OpenAI model version, change openai_model_version in your .tfvars file and run terraform plan to confirm the change before applying. Terraform will delete and recreate the cognitive deployment in-place — be aware this causes brief downtime for the model endpoint.

To destroy a complete environment:

terraform destroy

The prevent_deletion_if_contains_resources feature on the resource group will block destruction if any untracked resources exist, which is a useful safety net in production.

Handling Configuration Drift

Drift occurs when Azure resources are modified outside of Terraform (portal changes, CLI scripts, other automation). Detect drift with:

terraform plan -refresh-only

This reports the difference between the Terraform state and the actual resource state without making changes. Schedule this as a drift-detection job in CI to catch out-of-band changes early.

Environment Isolation

Use Terraform workspaces or separate state files per environment:

# Create and switch to a staging workspace
terraform workspace new staging
terraform workspace select staging
terraform apply -var-file="environments/staging.tfvars"

Alternatively, use a directory-per-environment layout (environments/dev/, environments/prod/) with a shared module in modules/ai-foundry/. The directory layout is more explicit and easier to navigate in a team setting.

Cost Control

  • Set a low openai_sku_capacity in dev (e.g. 1 = 1,000 TPM) to limit accidental spend.
  • Tag all resources with environment and project tags (the locals.tags block handles this) to enable cost attribution in Azure Cost Management.
  • Use the Azure Pricing Calculator to estimate monthly costs before deploying to production. The Azure AI Services account (model token usage), Log Analytics, and Application Insights are the primary cost drivers.
  • Consider destroying dev environments overnight using a scheduled CI job that runs terraform destroy and terraform apply on a schedule.

CI/CD Integration

Automating Terraform via GitHub Actions is straightforward. The following workflow runs plan on pull requests and apply on merge to the main branch:

# .github/workflows/terraform.yml

name: Terraform Deploy

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions:
  id-token: write   # Required for OIDC workload identity federation
  contents: read
  pull-requests: write

env:
  ARM_CLIENT_ID:       ${{ secrets.AZURE_CLIENT_ID }}
  ARM_TENANT_ID:       ${{ secrets.AZURE_TENANT_ID }}
  ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
  ARM_USE_OIDC:        "true"

jobs:
  terraform:
    runs-on: ubuntu-latest
    environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}

    steps:
      - uses: actions/checkout@v4

      - uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: "~1.9"

      - name: Terraform Init
        run: terraform init

      - name: Terraform Plan
        run: terraform plan -out=tfplan -var-file="environments/dev.tfvars"

      - name: Terraform Apply
        if: github.ref == 'refs/heads/main'
        run: terraform apply -auto-approve tfplan

Figure 4: CI/CD pipeline using GitHub Actions with OIDC workload identity federation. No long-lived secrets are stored — the runner exchanges a JWT for a short-lived Azure token before each Terraform run.

Use OIDC workload identity federation to avoid storing long-lived service principal secrets in GitHub. This is the recommended authentication method for GitHub Actions deployments to Azure.


Best Practices

Modular Terraform Design

Once you have a working flat configuration, extract the Foundry resources into a reusable module. A module boundary around the Hub, Project, OpenAI account, and RBAC assignments lets you stamp out new agent environments with a single module call and a new .tfvars file.

# environments/staging/main.tf
module "agent_platform" {
  source = "../../modules/ai-foundry"

  project_name         = "contoso-agents"
  environment          = "staging"
  location             = "eastus"
  subscription_id      = var.subscription_id
  openai_model_name    = "gpt-4.1"
  openai_model_version = "2025-04-14"
  openai_sku_capacity  = 30
}

Parameterisation and Environment Configs

  • Never hard-code subscription IDs, tenant IDs, or region names in main.tf.
  • Keep environment-specific values in environments/<env>.tfvars files and commit them to source control (they are config, not secrets).
  • Store actual secrets (service principal credentials, API keys for third-party connections) in Azure Key Vault or GitHub Secrets — not in .tfvars files.

Versioning Models and Agent Configurations

Treat your openai_model_version and agent instructions as versioned artefacts. When Microsoft releases a new model version, create a pull request that updates the variable value, runs a plan, and documents the expected change. This creates a clear history of when model versions changed and who approved the change.

Logging and Monitoring

  • Enable diagnostic settings on the Azure OpenAI account to route request logs and metrics to your Log Analytics workspace.
  • Use Application Insights to capture agent traces from the Azure AI Agents SDK (it integrates with OpenTelemetry).
  • Set up Azure Monitor alerts on OpenAI account errors (4xx/5xx rates) and Log Analytics ingestion failures.

Responsible AI Considerations

  • Enable Azure OpenAI content filtering on your deployment. Terraform supports this via the content_filter block in azurerm_cognitive_deployment where the policy allows.
  • Define a clear system prompt that sets agent behaviour boundaries and instructs the agent to decline harmful requests.
  • Log and review agent conversations during early deployment. Microsoft Foundry includes evaluation tools for assessing agent response quality and safety.
  • Apply least-privilege RBAC throughout — the role assignments in this post follow that principle.

Conclusion and Next Steps

You now have a complete, repeatable Terraform configuration for provisioning the Azure infrastructure required to run Microsoft Hosted Agents via Microsoft Foundry. The key takeaways:

  • Terraform manages the infrastructure layer effectively — the Foundry Account, Project, model deployment, identity, and RBAC.
  • Agent definitions themselves are provisioned via the Azure AI Agents SDK or the Foundry portal as a post-Terraform step.
  • State management, parameterisation, and modular design are non-negotiable for team environments.
  • OIDC-based workload identity is the right authentication model for CI/CD pipelines.
  • Drift detection, environment isolation, and cost tagging are operational necessities, not optional extras.

Where to Go Next

  • Add Azure AI Search: Extend the Foundry Project with an Azure AI Search connection and enable the Search tool on your agent for Retrieval-Augmented Generation (RAG).
  • Private networking: Add private endpoints for the Foundry Hub and OpenAI account to lock down ingress to your VNet.
  • Multi-region deployment: Instantiate the Terraform module twice with different regions and use Azure Traffic Manager or Front Door to route requests.
  • GitOps for agents: Store agent definitions (system prompts, tool configurations) as YAML or JSON in your repository and use a CI pipeline to apply them via the Azure AI Agents SDK on every merge, creating a fully declarative agent deployment pipeline.
  • Evaluation pipelines: Use Microsoft Foundry's built-in evaluation capabilities to run automated quality and safety assessments on every new model version or prompt change.

References

Updated Jun 02, 2026
Version 1.0
No CommentsBe the first to comment