Skip to content

fix: read unified azure.yaml in agent run and deploy#9149

Open
huimiu wants to merge 6 commits into
mainfrom
hui/unified-config-runtime
Open

fix: read unified azure.yaml in agent run and deploy#9149
huimiu wants to merge 6 commits into
mainfrom
hui/unified-config-runtime

Conversation

@huimiu

@huimiu huimiu commented Jul 15, 2026

Copy link
Copy Markdown
Member

Why this change is needed

Azure AI Agents services can now be defined directly in azure.yaml, under the deprecated config: block, or in local files referenced through $ref. These forms were not resolved consistently across local run, deploy, and provision. As a result, a valid project could lose environment expressions, skip referenced resources, or use inconsistent agent configuration.

What changed

  • Added a shared resolver for inline, legacy config:, and local $ref agent configuration.
  • Applied the resolved configuration consistently across local run, deploy, provision, synthesis, and brownfield validation.
  • Preserved environment expressions while resolving extension-owned configuration and normalized values at runtime without changing the existing schema type contract.
  • Added azure.yml support while retaining compatibility with agent.yaml and agent.yml projects.
  • Made azd ai agent optimize apply reject only root agent-definition references, avoiding writes to the wrong file without blocking unrelated nested references.
  • Preserved Windows environment-variable precedence regardless of key casing.

Configuration contract

A root $ref may provide agent-owned configuration such as the agent definition, protocols, environment settings, deployments, connections, and Foundry-specific settings. Core-owned execution fields (project, language, image, and docker) must remain inline on the service entry in azure.yaml.

Scope

This PR intentionally leaves environment value type contracts unchanged in both the core and agent extension schemas. Supporting boolean, number, or null environment values, together with related type-focused review feedback, is outside the scope of this PR and can be handled separately. Runtime normalization is defensive and does not expand public schema support.

Why this approach

Core azd selects frameworks and executes build, package, and deploy operations from the service entry it reads directly. Keeping execution fields inline makes that lifecycle deterministic and avoids a new cross-boundary API. The extension still resolves its own configuration without rewriting user files.

Testing

From cli/azd/extensions/azure.ai.agents:

  • go test ./internal/cmd ./internal/pkg/projectconfig ./internal/project ./internal/synthesis
  • go build ./...

Closes #9151.
Part of #8710.

Copilot AI review requested due to automatic review settings July 15, 2026 05:06
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
21 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Unifies agent configuration resolution across run, deploy, provision, and synthesis while retaining legacy configuration support.

Changes:

  • Resolves $ref files and typed service environment values.
  • Applies normalized configuration across lifecycle paths.
  • Adds coverage for referenced services and resource definitions.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
internal/synthesis/synthesizer.go Resolves referenced synthesis inputs.
internal/synthesis/synthesizer_test.go Tests referenced synthesis resources.
internal/project/service_update.go Serializes project service updates.
internal/project/service_target_agent.go Uses resolved deploy configuration.
internal/project/service_target_agent_test.go Tests deployment and build resolution.
internal/project/resource_group_location_check.go Resolves referenced brownfield endpoints.
internal/project/resource_group_location_check_validate_test.go Tests referenced endpoint validation.
internal/project/foundry_provisioning_provider.go Resolves provisioning references.
internal/project/foundry_provisioning_provider_test.go Tests referenced Foundry endpoints.
internal/project/config.go Supports toolbox service-name values.
internal/project/agent_definition.go Centralizes effective agent resolution.
internal/project/agent_definition_test.go Tests unified, legacy, and referenced definitions.
internal/pkg/projectconfig/environment.go Loads and normalizes raw service environments.
internal/pkg/projectconfig/environment_test.go Tests typed and referenced environments.
internal/cmd/run.go Applies unified environment values locally.
internal/cmd/run_test.go Tests service environment resolution.
internal/cmd/resource_services.go Resolves referenced Foundry resources.
internal/cmd/resource_services_test.go Tests referenced resource collection.
internal/cmd/optimize_apply.go Rejects updates to referenced definitions.
internal/cmd/listen.go Updates provision and deploy hooks.
internal/cmd/listen_test.go Tests referenced container settings.
internal/cmd/helpers.go Builds resolved local-run context.
internal/cmd/helpers_test.go Tests raw unified environment loading.
.vscode/cspell.yaml Adds the new package name.

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/listen.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/optimize_apply.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go Outdated

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One question on a behavior change that's outside what the description covers. Everything else (the $ref/unified resolution across run, deploy, provision, and the env precedence handling) reads cleanly and is well covered by tests.

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/listen.go
Copilot AI review requested due to automatic review settings July 15, 2026 08:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 3 comments.

Comment thread cli/azd/extensions/azure.ai.agents/internal/synthesis/synthesizer.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/synthesis/synthesizer.go Outdated

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new commit restores the hosted-agent session carryover (capture in predeploy, resume in postdeploy) that the first commit had dropped, so my earlier question is resolved. The restored wiring matches what's on main. Approving.

Copilot AI review requested due to automatic review settings July 15, 2026 09:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • cli/azd/pkg/azdext/container.pb.go: Generated file

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new commit swaps the persist/restore state mutation for a per-request service_path override on the container build, package, and publish calls. The server treats it as a one-operation override without touching the stored config, rejects path traversal via filepath.IsLocal, and falls back to protowire unknown fields for wire compatibility. That resolves my earlier question about how the referenced-service path was being carried into the container operations. Re-approving against the latest commit.

Copilot AI review requested due to automatic review settings July 15, 2026 09:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • cli/azd/pkg/azdext/container.pb.go: Generated file

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/run.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go Outdated
@github-actions

Copy link
Copy Markdown

📋 Prioritization Note

Thanks for the contribution! The linked issue isn't in the current milestone yet.
Thank you for logging this issue; our team is reviewing it. If you need urgent prioritization, tag @RickWinter and @kristenwomack to let us know.

@huimiu
huimiu force-pushed the hui/unified-config-runtime branch from bce9965 to 9ce8720 Compare July 17, 2026 15:20
Copilot AI review requested due to automatic review settings July 17, 2026 15:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 1 comment.

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/listen.go
Copilot AI review requested due to automatic review settings July 17, 2026 15:34

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latest automated review batch (2026-07-17) is pointing at files that aren't in this PR's net diff: cli/version.txt, pkg/azdext/validation_provider.go, cmd/invoke.go, and cmd/init_adopt.go. Those came in from merging main (the provision-validation rename from #8844, the invoke-name change from #9114, and the release version bumps), so they don't show up in gh pr diff. Nothing to change there for this PR, the net diff is 23 files, all under the agents extension.

The substantive open items are still trangevi's threads: the Resolve/Normalize wrapper methods, and the request to expand the doc comments on ResolveServiceConfigInPlace and NormalizeServiceConfigInPlace.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 17, 2026 15:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 1 comment.

Comment on lines +405 to +407
if selector.Host == "" && selector.Ref == "" {
return node, false, nil
}

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One note on the latest commit (fix: remove unsupported workflow handling): dropping the non-hosted branch validation in agentDefinitionFromStruct leaves the inline path inconsistent with the on-disk path. parseContainerAgentYAML still calls ValidateAgentDefinition before it branches on kind, so an invalid kind or a malformed name on a workflow agent is rejected when it lives in agent.yaml on disk, but silently accepted when it is inline in azure.yaml (agent_definition.go:596).

Since the goal of this PR is resolving these forms consistently across run/deploy/provision, is skipping validation on the inline non-hosted path intentional, or should it validate like the disk path does? Hosted agents are unaffected either way, so not a blocker.

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ran the reworked commits (9ce8720..d6edea1) through the agents extension build, vet, and package tests locally. All green except the two synthesis ARM-template snapshot tests (TestARMTemplate_MatchesBicepBuild and the brownfield variant), and those only fail because the committed main.arm.json/brownfield.arm.json are stale against my local bicep version, which is unrelated to this change (no .bicep/.arm.json files are in the diff). The container-config rework also resolves the earlier version-gate concern, since the resolved service path is now read locally instead of carried over the container RPC.

Not approving yet: the maintainability threads above (the wrapper methods with no conditional handling, and the doc clarity + DRY on ResolveServiceConfigInPlace/NormalizeServiceConfigInPlace) are still open and worth settling first.

@huimiu

huimiu commented Jul 20, 2026

Copy link
Copy Markdown
Member Author

@copilot resolve the merge conflicts in this pull request

Co-authored-by: huimiu <107838226+huimiu@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 20, 2026 06:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 7 comments.

Comment thread cli/azd/extensions/azure.ai.agents/internal/synthesis/synthesizer.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/synthesis/synthesizer_test.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/resource_services.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/resource_services_test.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/listen.go Outdated

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The automated conflict resolution in the latest commit (f8ebf63, "begin merge conflict resolution with main") is incomplete. Unresolved conflict markers (<<<<<<<, =======, >>>>>>>) are still in 7 files, so both extensions fail to compile and CI is red.

Files with leftover markers:

  • azure.ai.agents/internal/cmd/listen.go (2)
  • azure.ai.agents/internal/cmd/resource_services.go (1)
  • azure.ai.agents/internal/cmd/resource_services_test.go (5)
  • azure.ai.agents/internal/synthesis/synthesizer.go (9)
  • azure.ai.agents/internal/synthesis/synthesizer_test.go (6)
  • azure.ai.projects/internal/provisioning/foundry_provisioning_provider.go (6)
  • azure.ai.projects/internal/provisioning/resource_group_location_check.go (1)

go build ./... fails in both extensions with syntax errors right at the marker lines (for example synthesizer.go:277: unexpected <<).

A few of these conflicts aren't just formatting, so it's worth a careful pass when finishing them. In synthesizer.go, deriveIncludeAcr has two different signatures across the sides: HEAD returns (bool, error) and propagates the error, origin/main returns a plain bool. The call site (~line 278) and the definition (~line 604) have to agree, and the loop bodies differ too (serviceForHost vs resolveServiceRefs). Same story with the collectConnections argument order around line 297. Pick the version that matches the rest of the current code, then run go build and go test on both extensions before the next pass.

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This branch is mid-merge with main and still has unresolved conflict markers, so the agents and projects extensions don't compile at this HEAD. I found <<<<<<< / ======= / >>>>>>> markers in:

  • cli/azd/extensions/azure.ai.agents/internal/cmd/listen.go
  • cli/azd/extensions/azure.ai.agents/internal/cmd/resource_services.go
  • cli/azd/extensions/azure.ai.agents/internal/cmd/resource_services_test.go
  • cli/azd/extensions/azure.ai.agents/internal/synthesis/synthesizer.go
  • cli/azd/extensions/azure.ai.agents/internal/synthesis/synthesizer_test.go
  • cli/azd/extensions/azure.ai.projects/internal/provisioning/foundry_provisioning_provider.go
  • cli/azd/extensions/azure.ai.projects/internal/provisioning/resource_group_location_check.go

The latest commit is "begin merge conflict resolution with main," so this is in-progress. My earlier approval doesn't apply to this state. Once the merge is finished and go build ./... plus the tests pass for both extensions, re-request review and I'll take another pass at the actual logic changes.

Copilot AI review requested due to automatic review settings July 20, 2026 06:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

cli/azd/extensions/azure.ai.agents/internal/synthesis/synthesizer.go:494

  • azd-code-reviewer: This accepts host: azure.ai.agent from the referenced file, but azd core does not resolve service-level $ref: it maps ServiceConfig.Host directly from the inline service entry, and run/deploy select services by that mapped host. The configuration covered by TestSynthesize_ResolvesAgentHostFromRefForAcr can therefore provision an ACR while the agent is invisible to run/deploy. Require the agent host inline (or implement host resolution consistently before core dispatch).
	if err := node.Decode(&selector); err != nil {
		return node, false, fmt.Errorf(
			"decode service %q selector: %w",
			serviceName,
			err,
		)
	}
	return node, selector.Host == expectedHost, nil

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed after the automated merge with main. The remaining blocker here isn't the merge itself. The conflict resolution in 685ecc3 came through clean: no leftover conflict markers, the projectRoot parameter-reorder conflicts (moved to the end of the signature) resolve consistently across every call site, and CI is green on both the agents and projects extension pipelines.

What still needs to land before this is mergeable is the open review feedback, not the merge state: trangevi's request to drop the unnecessary wrapper methods, and the scoping concern Victor raised that tg-msft backed. Those are worth resolving in this PR rather than deferring.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/extensions Extensions (general) ext-agents azure.ai.agents extension ext-connections azure.ai.connections extension ext-demo microsoft.azd.demo extension ext-routines azure.ai.routines extension ext-toolboxes azure.ai.toolboxes extension

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support unified azure.yaml in agent runtime operations

8 participants