MicrosoftMicrosoft Certified: Multi-Agent AI Solutions Expert2026-104.3 Deploy multi-agent solutions to Azure
Recreate environments from validated infrastructure definitions
Completed by the knowledge check
Learning objective
Provision and validate reproducible environments using Bicep, Terraform, and Azure Developer CLI as appropriate.
Core idea
A reproducible environment comes from versioned infrastructure definitions, explicit environment inputs, and retained deployment evidence. Repeating a command is not enough if it reads different parameters, uses another subscription, or shares the wrong Terraform state. Validate both planned changes and deployed behavior.
Bicep and Terraform describe infrastructure. Azure Developer CLI (azd) coordinates application provisioning and deployment around project configuration. They are therefore not three interchangeable infrastructure languages: azd can use Bicep or Terraform as its infrastructure provider.
Select the combination that fits the project’s ownership and validation requirements. See 4.3.2 for environment isolation and compatible release sets. Validate recreation separately from runtime readiness.
How it works
Use Bicep for an Azure-native definition
Bicep is a declarative language for deploying Azure resources through Azure Resource Manager. Microsoft’s overview documents support for Azure resource types and API versions, reusable modules, and what-if preview. It does not require a separate client-maintained state file for determining the resources’ existing state.
Keep infrastructure modules and environment parameter values under deliberate version control. Declare location, naming, network choices, and dependency inputs. Pin resource API versions in the definition and review the feature status of the exact resource capabilities you select; support for a preview API version does not make the capability generally available.
At resource-group scope, use az deployment group what-if to inspect the intended deployment against existing resources. Other deployment scopes have their own commands: az deployment sub what-if, az deployment mg what-if, and az deployment tenant what-if. Select the command that matches the definition’s deployment scope.
Azure CLI 2.76.0 or later provides --validation-level. Its documented values are Provider, ProviderNoRbac, and Template. Provider, the default, includes resource and deployment-permission validation. ProviderNoRbac performs resource validation but checks read permissions rather than full deployment permissions. Template performs static validation and skips provider preflight and permission checks. A pipeline passing Template has not established the properties checked by Provider.
What-if has analysis limits: 500 nested templates, 800 resource groups in a cross-resource-group deployment, and five minutes spent expanding nested templates. Reaching a limit sets remaining resources’ change type to Ignore. Unresolved expressions can also prevent complete analysis, and some predictions are false positives. Inspect diagnostics and unexplained changes instead of accepting an empty-looking preview as complete evidence.
Use Terraform with deliberate state ownership
Terraform uses configuration files and an execution plan. Microsoft’s Azure integration-testing guide separates terraform validate, which checks configuration syntax, from terraform plan, which connects to the target Azure subscription and determines intended additions, changes, and destruction against the existing environment. Initialize the working directory with terraform init before validation.
A valid configuration is not a harmless plan. Review the proposed changes before applying them, especially replacement or destruction of resources that hold conversation data, tool dependencies, or recovery evidence. Treat a plan as evidence for the specific configuration, inputs, target, and state used to produce it. If those inputs change, reassess the plan rather than relying on an earlier review.
Terraform maintains persisted state. Remote state supports shared access, protects sensitive state data, and reduces the chance of accidental deletion associated with local state. Microsoft’s azd Terraform guidance requires remote state before azd pipeline config sets up a GitHub deployment pipeline. Its documented configuration uses an azurerm backend, with the remote storage details configured for the environment. By default, azd uses local state. If you ran azd up before enabling remote state, Microsoft documents running azd down and switching to remote state; do not assume that enabling a backend transparently migrates that environment.
Allocate separate state ownership to separate environments so a production run does not interpret development resources as its own. Remote state supports shared work; it does not remove the need to verify which backend and environment a pipeline actually selected.
Let Azure Developer CLI coordinate the lifecycle
azd assumes Bicep as the infrastructure provider by default. To select Terraform, configure infra.provider: terraform in the project’s azure.yaml and place the Terraform files in infra. Microsoft’s documentation marks the Terraform integration beta. Keep that status in the architectural decision instead of presenting every azd provider path as equally mature.
See 0.14 for azd provision, azd deploy, and the combined azd up lifecycle. In a controlled release, infrastructure review and application promotion may need separate gates even when one convenience command can perform both.
Use a template as a starting definition that your team reviews and versions, rather than an assurance that its defaults meet your requirements. Record the resolved subscription, location, inputs, and project configuration.
For the documented local Terraform flow, the azurerm provider uses Azure CLI authentication by default and does not read the azd credential cache. Microsoft documents az login with azd config set auth.useAzCliAuth true to share Azure CLI authentication, or separate az login and azd auth login commands. Signing in only to azd can leave Terraform provisioning unauthenticated. Configure unattended CI identity separately; see 4.3.8.
The generated GitHub Actions path has an additional restriction: azd pipeline config is beta, defaults to OIDC/federated credentials, and does not support those credentials for Terraform. Do not assume that choosing infra.provider: terraform automatically yields the required secretless pipeline. Decide the pipeline path explicitly rather than silently changing the identity requirement.
Validate the deployed environment
Retain predeployment and postdeployment evidence with the infrastructure revision and resolved inputs. Reviewers need to reconstruct both the approved changes and the observed environment.
Check the deployed resource configuration against the intended environment, then run the agent through its runtime path. For Foundry hosted agents, azd ai agent invoke exercises the deployed agent. Include a representative model request, tool operation, and workflow handoff under the environment’s runtime identity, using non-destructive fixtures. See 4.3.6 for test scope and 4.3.7 for behavioral acceptance.
Recreate a disposable environment from the definitions to expose missing manual setup. Provisioning an existing environment successfully can conceal resources or permissions created outside the template. A clean recreation plus dependency checks gives stronger evidence that another operator can recover the environment from the retained definitions and inputs.
Key distinctions and trade-offs
The mechanisms validate different properties:
| Mechanism | Main question |
|---|---|
| Bicep what-if | What Azure resource changes does this deployment predict? |
terraform validate | Is the initialized configuration syntactically valid? |
terraform plan | What changes does this configuration require against its target and state? |
azd provision | Can the configured infrastructure provider provision the environment? |
azd deploy | Can the application package be deployed? |
| Deployed invocation | Does the runtime path work with deployed dependencies? |
Bicep suits an Azure-native definition without a separate Terraform state lifecycle. Terraform suits teams that deliberately manage provider configuration and shared state. azd provides a consistent project lifecycle around either, with the documented beta and authentication limitations checked for the selected path.
Architecture / decision scenario
A team must reproduce a claims environment in a separate test subscription. Its Azure-only application uses Bicep modules and azd lifecycle commands. CI runs resource-group what-if with Provider validation, inspects diagnostics and predicted changes, and retains the parameter set. It provisions, deploys, and invokes the hosted agent against a test tool fixture.
A second team already operates Terraform with remote state. It initializes and validates configuration, reviews the plan against the test environment’s backend, and selects Terraform in azure.yaml. It accounts for the beta integration and chooses an independently verified CI identity path because generated azd GitHub OIDC is unsupported for Terraform.
Both teams recreate an empty disposable environment and exercise the model, tool, and workflow connections. If provisioning passes but the tool call fails, neither calls the environment validated. They repair the missing dependency in the versioned definition or inputs, repeat recreation, and retain the resulting release evidence.
Common exam traps
- Treating
azdas an alternative infrastructure language to Bicep and Terraform. - Equating
terraform validatewith an inspected deployment plan. - Assuming
Templatevalidation checks deployment permissions. - Ignoring what-if diagnostics or
Ignoreresults at analysis limits. - Sharing Terraform state accidentally across environments.
- Treating successful
azd upas proof of agent behavior and dependency access.
What to remember
Version definitions and environment inputs, inspect the intended changes, and validate the deployed runtime separately. Bicep uses Azure deployment analysis; Terraform adds an explicit state lifecycle; azd coordinates provisioning and application deployment. Reproducibility requires a clean recreation and retained evidence, with provider status and authentication limits understood.
Knowledge check
A team already maintains Terraform modules with remote state and wants the azd provision-and-deploy lifecycle for its agent application. A colleague says the modules must first be rewritten in Bicep. What is the correct response?
azd requiresinfra.provider: terraform in azure.yamlazd hooks while azd provisions Bicepazd template that defines the infrastructure itselfazd is not a third infrastructure language: it coordinates the project lifecycle around an infrastructure provider, Bicep by default or Terraform when azure.yaml selects it with the files in infra . The Terraform integration is documented as beta, which belongs in the decision, and a template is a starting definition the team still reviews rather than a replacement for its own.A resource-group Bicep what-if step runs with --validation-level Template. Review policy requires provider preflight and a check of full deployment permissions. Which change meets the policy?
ProviderNoRbac for the same resource-group what-ifTemplate and run the what-if at subscription scope insteadProvider for the same resource-group what-ifTemplate and review any resources reported as IgnoreProvider , the default, adds provider preflight and deployment-permission validation; ProviderNoRbac validates resources but checks only read permissions, and Template skips both preflight and permission checks. The deployment scope must still match the definition, and Ignore results are a separate analysis-limit concern.Terraform configuration passes terraform validate. Before applying it to production, the team must know whether any resource holding conversation data would be replaced or destroyed. What evidence is needed next?
terraform validate checks configuration syntax; only terraform plan connects to the target and determines additions, changes and destruction against existing state. A plan is evidence for the inputs, target and state that produced it, so a development plan says nothing reliable about production resources.A developer runs azd auth login and then azd up on a project whose infrastructure provider is Terraform. The provision step fails to authenticate to Azure. Which fix matches the documented local flow?
azd pipeline config to set up federated credentials for Terraformazurerm backend before running azd up againaz login , optionally setting azd to reuse Azure CLI authenticationazd auth login again with the subscription’s tenant selectedazurerm provider authenticates through Azure CLI by default and does not read the azd credential cache, so signing in only to azd leaves Terraform unauthenticated. az login , with auth.useAzCliAuth if one sign-in should serve both tools, fixes the local flow; remote state and the generated pipeline answer different questions, and that generator does not support OIDC for Terraform.Provisioning and deployment succeed in an existing test environment. What additional exercise most directly exposes undocumented manual dependencies and shows the environment can be recovered?
References
- Microsoft, What is Bicep?
- Microsoft, Bicep what-if: Preview changes before deployment
- Microsoft, Implement integration testing with Terraform and Azure
- Microsoft, Use Terraform as an infrastructure as code tool for Azure Developer CLI
- Microsoft, Get started using Azure Developer CLI
- Microsoft, Configure a pipeline using GitHub Actions
- Microsoft, Test a hosted agent