Support extending synthesized Foundry infra with user-owned Bicep
- Dominant language
- Go
- Stars
- 569
- Forks
- 364
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 136
Description
## 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`:
1. **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.
2. **`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.
3. **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
- #9194 — separate bug where `azd provision` does not honor "use existing project" in the same browser-automation sample.
Contributor guide
Research direction
Start by reading cli/azd/extensions/azure.ai.projects/internal/provisioning/foundry_provisioning_provider.go and cli/azd/extensions/azure.ai.agents/internal/cmd/init_infra.go, then trace how synthesized and on-disk Bicep are selected. Define and implement an extension approach that deploys user-owned Bicep with synthesized Foundry infrastructure for both greenfield and brownfield projects, without requiring full eject or a postprovision hook.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- azure, go
- Domain
- cli, cloud, infrastructure
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100