Skip to content

Support Terraform as an IaC option for azd ai agent #8705

@hund030

Description

@hund030

Summary

Add Terraform as a supported infrastructure-as-code option for Foundry agents, so teams standardized on Terraform can provision and manage agent infrastructure with real .tf files and their own state/backend workflow.
azd ai agent init --infra would emit a Terraform template (instead of Bicep) that provisions the same resources and produces the same outputs, and the agent deploy/RBAC flow continues to work unchanged.

Goals

  • azd ai agent init --infra can emit a Terraform template instead of Bicep.
  • Ejected .tf provisions the same resources and emits the same output contract as the Bicep template.
  • Agent deploy + RBAC continue to work unchanged on the Terraform path.

Non-goals

  • No bicepless/in-memory option for Terraform — .tf files are always on disk.

Proposed approach

  1. Author a Terraform module (azurerm + azapi mix) replicating internal/synthesis/templates/{main,modules/resources,modules/acr}.bicep:

    • azurerm_resource_group, azurerm_cognitive_deployment, azurerm_container_registry, azurerm_role_assignment ×2 (Cognitive Services User on project, AcrPull on ACR).
    • azapi for the AIServices account (allow_project_management), the Foundry projects sub-resource, and the ContainerRegistry connections sub-resource.
  2. Eject command: azd ai agent init --infra=terraform

    Invocation Result
    azd ai agent init --infra eject Bicep (unchanged)
    azd ai agent init --infra=terraform eject Terraform (new)
    azd ai agent init --infra=bicep eject Bicep (explicit)
    (flag absent) bicepless default — no files, microsoft.foundry (unchanged)
  3. Set infra.provider: terraform in azure.yaml so azd-core's built-in Terraform provider handles provisioning (the microsoft.foundry provider is not used on this path).

Why delegate to azd-core's Terraform provider (instead of building a custom one)

Bicep is handled by a custom in-extension provider (microsoft.foundry) that
generates and deploys infra itself. For Terraform we could either build a similar
custom provider, or delegate to azd-core's built-in Terraform provider. We chose to
delegate, for two reasons:

  1. Cost & consistency. The custom microsoft.foundry provider's rich behavior
    is cheap for Bicep only because Bicep compiles to ARM JSON and reuses the ARM
    deployment engine the provider already has. Terraform has no such intermediate,
    so, a custom Terraform provider means building a second provisioning engine plus
    maintaining a parallel Terraform copy.

  2. Auth gap. A custom Terraform provider would have to authenticate the
    terraform Azure provider itself, but the extension only holds azd's
    credential and sets none of the ARM_* environment variables Terraform expects.
    azd-core's Terraform provider already handles that, so delegating avoids the
    problem entirely.

End-to-end journey:

Step Command Who handles it
Scaffold azd ai agent init extension (agent prompts, unchanged)
Choose IaC --infra=terraform extension eject → writes .tf + stamps infra.provider: terraform
Provision azd provision azd-core Terraform provider (terraform init/plan/apply)
Deploy azd deploy extension azure.ai.agent service target (unchanged)
Tear down azd down azd-core terraform destroy

Metadata

Metadata

Assignees

Labels

area/terraformTerraform-specific provisioningenhancementNew feature or improvementext-agentsazure.ai.agents extension
No fields configured for Feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions