Summary
When a project uses the Foundry provider's synthesized infrastructure (infra.provider: microsoft.foundry), there is no first-class way to add your own Azure resources as an extra Bicep module while still letting azd auto-generate the Foundry infra. Today you must either fully eject and own the entire main.bicep, or run a second deployment from a postprovision hook.
We should close this gap so a user can supply a user-owned Bicep module (e.g. a Playwright workspace + Foundry connection) and have azd deploy it alongside the synthesized Foundry infra — for both greenfield and brownfield (existing project) scenarios.
Why this is needed
The browser-automation / Playwright sample needs to provision a custom Azure resource (Playwright workspace) and a Foundry connection as part of azd provision. The team already has the Bicep. The only options today are:
- Eject and hand-edit the generated
main.bicep — greenfield only, and the user now owns the full template, or
- a postprovision hook that runs a separate
az deployment group create.
Neither is a real "extend the infra" experience, and eject is not available at all for existing/brownfield projects. This pushes every custom-resource sample onto hook-based workarounds.
Current behavior (the gap)
From the Foundry synth flow in cli/azd/extensions/azure.ai.projects/internal/provisioning/foundry_provisioning_provider.go:
- No auto-merge. Before synth, the provider stat-checks only
infra/main.bicep / infra/main.bicepparam (onDiskTemplatePresent). Any other .bicep file in infra/ is never scanned, referenced, or deployed — it is a dead file.
main.bicep takes over. If infra/main.bicep exists, the provider logs skipping synthesizer and treats that file as the sole template. Everything the Foundry provider would have generated is gone unless the user re-adds it by hand.
- Brownfield cannot eject. For an existing project (
endpoint: set), the on-disk Bicep path is skipped entirely, and azd ai agent init --infra rejects brownfield (cli/azd/extensions/azure.ai.agents/internal/cmd/init_infra.go). So there is no eject path at all for existing projects.
Net: the only way to add custom resources is a postprovision hook (a second deployment), which is what the official sample does.
Desired capability
Let a user extend the synthesized Foundry infra with their own Bicep module without:
- fully ejecting / owning the whole
main.bicep, or
- resorting to a
postprovision hook,
…and have it work for both greenfield and brownfield.
Possible directions (open for design)
- A convention where azd auto-includes a user module (e.g.
infra/extensions/*.bicep, or a declared module) into the synthesized deployment.
- An
azure.yaml field to reference additional Bicep modules to deploy alongside the synth output, with dependsOn ordering.
- For brownfield: support a "resources/connection only" extension deployment targeted at the existing project's resource group.
Related note (separate gap)
The azure.ai.connection service host cannot currently express fields like audience / isSharedToAll that a Playwright connection needs, so today that connection still has to be authored in Bicep. Worth tracking alongside, but not required to close this issue.
Related issues
Summary
When a project uses the Foundry provider's synthesized infrastructure (
infra.provider: microsoft.foundry), there is no first-class way to add your own Azure resources as an extra Bicep module while still letting azd auto-generate the Foundry infra. Today you must either fully eject and own the entiremain.bicep, or run a second deployment from apostprovisionhook.We should close this gap so a user can supply a user-owned Bicep module (e.g. a Playwright workspace + Foundry connection) and have azd deploy it alongside the synthesized Foundry infra — for both greenfield and brownfield (existing project) scenarios.
Why this is needed
The browser-automation / Playwright sample needs to provision a custom Azure resource (Playwright workspace) and a Foundry connection as part of
azd provision. The team already has the Bicep. The only options today are:main.bicep— greenfield only, and the user now owns the full template, oraz deployment group create.Neither is a real "extend the infra" experience, and eject is not available at all for existing/brownfield projects. This pushes every custom-resource sample onto hook-based workarounds.
Current behavior (the gap)
From the Foundry synth flow in
cli/azd/extensions/azure.ai.projects/internal/provisioning/foundry_provisioning_provider.go:infra/main.bicep/infra/main.bicepparam(onDiskTemplatePresent). Any other.bicepfile ininfra/is never scanned, referenced, or deployed — it is a dead file.main.biceptakes over. Ifinfra/main.bicepexists, the provider logsskipping synthesizerand treats that file as the sole template. Everything the Foundry provider would have generated is gone unless the user re-adds it by hand.endpoint:set), the on-disk Bicep path is skipped entirely, andazd ai agent init --infrarejects brownfield (cli/azd/extensions/azure.ai.agents/internal/cmd/init_infra.go). So there is no eject path at all for existing projects.Net: the only way to add custom resources is a postprovision hook (a second deployment), which is what the official sample does.
Desired capability
Let a user extend the synthesized Foundry infra with their own Bicep module without:
main.bicep, orpostprovisionhook,…and have it work for both greenfield and brownfield.
Possible directions (open for design)
infra/extensions/*.bicep, or a declared module) into the synthesized deployment.azure.yamlfield to reference additional Bicep modules to deploy alongside the synth output, withdependsOnordering.Related note (separate gap)
The
azure.ai.connectionservice host cannot currently express fields likeaudience/isSharedToAllthat a Playwright connection needs, so today that connection still has to be authored in Bicep. Worth tracking alongside, but not required to close this issue.Related issues
azd provisiondoesn't honor the flag touse existing projectand the tool is not getting deployed on provision too. #9194 — separate bug whereazd provisiondoes not honor "use existing project" in the same browser-automation sample.