fix: align agent workflows with unified azure.yaml#9081
Conversation
📋 Prioritization NoteThanks for the contribution! The linked issue isn't in the current milestone yet. |
There was a problem hiding this comment.
Pull request overview
Aligns agent workflows and related Foundry resource extensions with unified azure.yaml, including $ref resolution and legacy fallbacks.
Changes:
- Resolves unified and referenced agent, connection, toolbox, and deployment configurations.
- Updates local run, deployment, guidance, and doctor behavior.
- Adds regression tests and changelog entries.
Reviewed changes
Copilot reviewed 44 out of 44 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
azure.ai.toolboxes/internal/cmd/service_target.go |
Resolves toolbox $ref files. |
azure.ai.toolboxes/internal/cmd/service_target_test.go |
Tests referenced toolbox config. |
azure.ai.toolboxes/CHANGELOG.md |
Documents toolbox fix. |
azure.ai.connections/internal/cmd/service_target.go |
Resolves connection $ref files. |
azure.ai.connections/internal/cmd/service_target_test.go |
Tests referenced connection config. |
azure.ai.connections/CHANGELOG.md |
Documents connection fix. |
azure.ai.agents/internal/synthesis/synthesizer.go |
Resolves referenced provisioning inputs. |
azure.ai.agents/internal/synthesis/synthesizer_test.go |
Tests referenced deployments and agents. |
azure.ai.agents/internal/project/service_update.go |
Serializes project service writes. |
azure.ai.agents/internal/project/service_target_agent.go |
Resolves and deploys unified agent config. |
azure.ai.agents/internal/project/service_target_agent_test.go |
Tests references and environment merging. |
azure.ai.agents/internal/project/foundry_provisioning_provider.go |
Resolves referenced brownfield config. |
azure.ai.agents/internal/project/foundry_provisioning_provider_test.go |
Tests referenced project endpoints. |
azure.ai.agents/internal/project/config.go |
Accepts split toolbox names. |
azure.ai.agents/internal/project/agent_definition.go |
Adds unified $ref resolution helpers. |
azure.ai.agents/internal/project/agent_definition_test.go |
Tests unified and legacy definitions. |
azure.ai.agents/internal/cmd/run.go |
Merges service environment values locally. |
azure.ai.agents/internal/cmd/run_test.go |
Tests local environment resolution. |
azure.ai.agents/internal/cmd/resource_services.go |
Resolves split Foundry resources. |
azure.ai.agents/internal/cmd/resource_services_test.go |
Tests referenced resource collection. |
azure.ai.agents/internal/cmd/nextstep/types.go |
Extends guidance state metadata. |
azure.ai.agents/internal/cmd/nextstep/state.go |
Reads effective unified agent config. |
azure.ai.agents/internal/cmd/nextstep/state_test.go |
Tests unified guidance state. |
azure.ai.agents/internal/cmd/nextstep/resolver.go |
Selects deploy or provision guidance. |
azure.ai.agents/internal/cmd/nextstep/resolver_test.go |
Tests split-resource guidance. |
azure.ai.agents/internal/cmd/nextstep/manifest.go |
Collects unified and legacy resources. |
azure.ai.agents/internal/cmd/nextstep/manifest_test.go |
Tests resource collection and errors. |
azure.ai.agents/internal/cmd/nextstep/format.go |
Updates guidance documentation. |
azure.ai.agents/internal/cmd/nextstep/config.go |
Loads effective guidance configuration. |
azure.ai.agents/internal/cmd/listen.go |
Resolves config during lifecycle events. |
azure.ai.agents/internal/cmd/listen_test.go |
Tests referenced container settings. |
azure.ai.agents/internal/cmd/helpers.go |
Adds environment to local run context. |
azure.ai.agents/internal/cmd/doctor/checks_toolboxes.go |
Updates toolbox diagnostics. |
azure.ai.agents/internal/cmd/doctor/checks_toolboxes_test.go |
Tests toolbox ownership guidance. |
azure.ai.agents/internal/cmd/doctor/checks_remote_test.go |
Updates remote check expectations. |
azure.ai.agents/internal/cmd/doctor/checks_project.go |
Validates unified agent definitions. |
azure.ai.agents/internal/cmd/doctor/checks_project_test.go |
Tests unified definition diagnostics. |
azure.ai.agents/internal/cmd/doctor/checks_manual_env.go |
Updates environment diagnostics. |
azure.ai.agents/internal/cmd/doctor/checks_manual_env_test.go |
Updates diagnostic assertions. |
azure.ai.agents/internal/cmd/doctor/checks_local.go |
Updates local-check documentation. |
azure.ai.agents/internal/cmd/doctor/checks_local_test.go |
Updates local-check expectations. |
azure.ai.agents/internal/cmd/doctor/checks_connections.go |
Updates connection diagnostics. |
azure.ai.agents/internal/cmd/doctor/checks_connections_test.go |
Tests connection ownership guidance. |
azure.ai.agents/CHANGELOG.md |
Documents unified configuration fixes. |
jongio
left a comment
There was a problem hiding this comment.
I looked into the two $ref overlay comments already on this PR and the mechanism holds up. foundry.ResolveFileRefs overlays a directive's sibling keys on top of the referenced file wholesale (the sibling loop in resolveRef), so any field persisted next to $ref wins over that same field in the referenced file on every later run.
One thing worth adding beyond what's already noted: in prepareContainerSettings, SetAgentContainerSettings writes container onto the original $ref-bearing properties and fills in DefaultMemory/DefaultCpu whenever they're unset. populateContainerSettings runs for every agent service, not just ones that actually set resources. So after the first preprovision run a $ref-backed service ends up with a container block (often just the injected defaults) pinned beside $ref, and later edits to container in the referenced agent file stop taking effect. The resolved project/RelativePath write in persistBuildService has the same shape.
For $ref-backed services, persisting only the fields the user authored inline, or writing derived defaults into the referenced file through the ref-aware editor, would avoid pinning values that silently override the source file.
jongio
left a comment
There was a problem hiding this comment.
I re-checked the new commit against the $ref pinning I raised earlier. The persist-then-restore path plus not persisting resolved container settings for $ref-backed services closes that gap, and the added tests cover both the restore and the package-level revert.
I'm not approving yet because of a separate, unresolved issue in the connection templates. In main.bicep (and brownfield.bicep), connections is an ordinary array parameter:
param connections connectionsType = []
and connectionType carries credentials: object?. Non-secure deployment parameters are stored in the ARM deployment history in plaintext, so anyone with reader access on the deployment can recover those credentials. Moving the secret values into a @secure() object parameter, keeping only non-secret metadata in the array, and regenerating main.arm.json / brownfield.arm.json would close that off.
Worth also confirming the two related points already raised on this PR: the connection decoder in synthesizer.go dropping advanced auth properties (OAuth URLs/scopes, sharing, managed-identity), and the doctor check in checks_connections.go still pointing at azd deploy for split connections that are now provision-managed.
Once the credential handling is sorted this is good to approve.
trangevi
left a comment
There was a problem hiding this comment.
I think there was maybe a bad merge here, I'm seeing a number of changes that I believe I've reviewed elsewhere and should already be in main.
jongio
left a comment
There was a problem hiding this comment.
Following up on @trangevi's bad-merge note, since it checks out and I can pin down what happened.
The merge-base between this branch and main is 105d7e9f, and the branch is 2 commits behind main (missing #9007 and #9103, including the pin to the released azd module). The resolve unified workflow conflicts merge (18dd0d2e) pulled in changes from other in-flight PRs that have nothing to do with aligning agent workflows to unified azure.yaml.
The clearest example is an entire PR-registry-check tooling subsystem from #9042 that isn't in main and isn't part of this change:
.github/scripts/src/ext-registry-check.js(+807),.github/scripts/test/ext-registry-check.test.js(+1089).github/scripts/package.json,package-lock.json,jsconfig.json.github/workflows/ext-registry-check.yml,.github/workflows/scripts-ci.yml
None of those exist in main, so they're riding in from #9042 rather than belonging here. They account for a large chunk of the +8920/72-file size and make the actual unified-azure.yaml changes hard to isolate.
Rebasing onto current main (or dropping the merge and re-merging cleanly) so the diff only contains the agent-workflow work would resolve this and give the substantive changes a clean review. Worth a second pass over the merged-in toolbox commits (#9046, the toolbox-branch fix) to confirm which of those are genuinely part of this PR versus riding in from elsewhere.
This is separate from the credential-handling issue I raised earlier, which is still open.
|
@copilot resolve the merge conflicts in this pull request |
Resolved — the merge commit (
All tests pass. |
| if err := AddServiceSerialized( | ||
| ctx, | ||
| p.azdClient, | ||
| persisted, | ||
| ); err != nil { |
| if projectpkg.ConfigContainsFileRef(svc.GetAdditionalProperties()) || | ||
| projectpkg.ConfigContainsFileRef(svc.GetConfig()) { |
| ca, isHosted, found, source, err := | ||
| AgentDefinitionFromResolvedService(svc, projectRoot) |
1b997ef to
60069a5
Compare
| needsModels := len(resources.models) == 0 | ||
| needsToolboxes := len(resources.toolboxes) == 0 | ||
| needsConnections := len(resources.connections) == 0 |
| for _, svc := range services { | ||
| data := readManifestBytes(projectPath, svc.RelativePath) |
| return Result{ | ||
| Status: StatusPass, | ||
| Message: "model resource configuration loaded.", |
| suggestion := "Run `azd provision` to create the missing " + | ||
| "connection(s), or update their azure.yaml service names." |
jongio
left a comment
There was a problem hiding this comment.
Reviewed the doctor and next-step migration onto the unified azure.yaml. I traced the tiered resource resolution (split services, then bundled config, then the legacy manifest fallback), the env-variable precedence in the config merge, and the Foundry ${{...}} handling in extractEnvironmentRefs where the $-prefix guard correctly keeps those expressions out of both the missing-var and placeholder detectors. Build, vet, and the doctor and nextstep test suites pass locally. Moving config load and parse failures from silent skips to actionable doctor failures reads as a deliberate change, and the updated tests pin that behavior.
Summary
Migrate
azd ai agent doctorand next-step guidance to the effective configuration inazure.yaml(#8710).This PR is the diagnostics layer in a stacked change. It keeps doctor, next-step guidance, and the runtime behavior aligned when agent configuration is inline, uses the deprecated
config:block, or is provided through a local$ref. Existingagent.yamlandagent.manifest.yamlprojects remain supported.Scope
Doctor
Next-step guidance
azure.yamlservice configuration.$refconfiguration before generating guidance.Out of scope
azure.ai.toolboxes$refsupport is independent PR fix: resolve toolbox $ref config before deploy #9148.Review order
internal/pkg/projectconfigandinternal/projectin fix: read unified azure.yaml in agent run and deploy #9149 for the shared effective-configuration contract.internal/cmd/doctorfor validation and remediation behavior.internal/cmd/nextstepfor normalized state and guidance generation.Validation
go build ./...Closes #8710