Skip to content

feat(agents): write unified microsoft.foundry config from init#8675

Open
huimiu wants to merge 13 commits into
huimiu/foundry-service-targetfrom
huimiu/foundry-unified-init
Open

feat(agents): write unified microsoft.foundry config from init#8675
huimiu wants to merge 13 commits into
huimiu/foundry-service-targetfrom
huimiu/foundry-unified-init

Conversation

@huimiu

@huimiu huimiu commented Jun 16, 2026

Copy link
Copy Markdown
Member

Closes #8676

What

Consolidates the "unify Foundry config in azure.yaml" work to a code-complete state for a single hosted agent. Builds on the design spec in #8590 (§2.1, §2.3, §2.7).

Stacking

This branch is stacked on #8629 (huimiu/foundry-service-target). It contains #8629's commits (the microsoft.foundry service target) plus the additions below. Merge #8629 first, then rebase/merge this — or merge this and close #8629.

Changes

1. init now writes the unified host: microsoft.foundry entry

  • azd ai agent init writes a single azure.yaml with the agent declared inline under the service agents: array and model deployments: at the project level — no more agent.yaml / agent.manifest.yaml.
  • The Foundry keys travel on ServiceConfig.AdditionalProperties (not config:), and no service-level project/language is set — each agent owns its project and deploy mode. No azd core change: the gRPC ServiceConfig already carries additional_properties, AddService maps it to project.ServiceConfig.AdditionalProperties, and Save serializes it inline.
  • Maps the manifest/code definition onto the service target's FoundryAgent shape (runtime/image deploy modes, env, protocols, container resources). A shared buildFoundryServiceConfig helper covers both the manifest (InitAction) and from-code (InitFromCodeAction) paths.
  • New unit tests in init_foundry_test.go, including one that round-trips init's output through the service target's own FoundryProjectConfig.Validate().

Validation

  • Extension (azure.ai.agents): go build, go vet, gofmt, golangci-lint run (0 issues), full go test ./..., and cspell — all clean.
  • azd core schema tests (internal/mcp/tools, TestHandleAzdYamlSchema) pass.
  • The existing simple/complex examples validate against the composed microsoft.foundry schema (offline ajv), exercising the core host: microsoft.foundry conditional."

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

This PR completes the extension-side work to have azd ai agent init emit a unified host: microsoft.foundry service entry in azure.yaml, aligning init output with the new Foundry service target shape (single hosted agent) and removing the legacy agent.yaml/manifest outputs.

Changes:

  • Add a new microsoft.foundry service target provider that binds inline Foundry config from ServiceConfig.AdditionalProperties and deploys a single hosted agent (image or code-zip runtime).
  • Refactor init flows (init + init-from-code) to write the unified Foundry service entry (deployments at service level + agent inline), and keep emitting .agentignore for packaging.
  • Introduce Foundry config parsing/validation utilities and unit tests (config validation, endpoint parsing, and init-to-project wiring).

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
cli/azd/extensions/azure.ai.agents/internal/project/service_target_foundry.go Implements host: microsoft.foundry deploy lifecycle for a single hosted agent and reuses shared agent deploy helpers.
cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go Extracts shared auth setup and ZIP packaging helper for reuse by the Foundry target.
cli/azd/extensions/azure.ai.agents/internal/project/foundry_project_resolve.go Adds endpoint → ARM project ID resolution and endpoint parsing helpers.
cli/azd/extensions/azure.ai.agents/internal/project/foundry_project_resolve_test.go Unit tests for Foundry endpoint parsing.
cli/azd/extensions/azure.ai.agents/internal/project/foundry_config.go Defines/validates the unified Foundry config shapes (service + agent) and maps to deploy request types.
cli/azd/extensions/azure.ai.agents/internal/project/foundry_config_test.go Unit tests for Foundry config validation and binding from AdditionalProperties.
cli/azd/extensions/azure.ai.agents/internal/cmd/listen.go Registers the new microsoft.foundry service target.
cli/azd/extensions/azure.ai.agents/internal/cmd/init.go Updates init to stop writing agent.yaml and to emit unified Foundry service config + .agentignore.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code.go Updates init-from-code to emit unified Foundry service config and derive runtime/entrypoint from on-disk definition.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_foundry.go Adds helper to build unified Foundry service config + helper mappers + .agentignore writer.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_foundry_test.go Unit tests for the unified Foundry service config builder helpers.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_foundry_addtoproject_test.go End-to-end-ish tests asserting init writes the unified Foundry service shape via gRPC AddService.
cli/azd/extensions/azure.ai.agents/extension.yaml Registers the microsoft.foundry provider in the extension manifest.

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_foundry.go
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_foundry.go
@huimiu huimiu force-pushed the huimiu/foundry-unified-init branch from bc38428 to 15ef2ed Compare June 16, 2026 09:18
@huimiu huimiu changed the base branch from huimiu/foundry-azure-yaml to huimiu/foundry-service-target June 16, 2026 09:18
@glharper

Copy link
Copy Markdown
Member

Review: unified microsoft.foundry config from init

Switches azd ai agent init (manifest + from-code paths) to write a single unified host: microsoft.foundry service entry with the agent inline under agents: and model deployments: at project level, carried on ServiceConfig.AdditionalProperties instead of config:. Drops the separate agent.yaml write, extracts a shared buildFoundryServiceConfig helper, and adds solid tests. Build, go vet, gofmt, and the new tests pass locally; line lengths are within the lll limit.

The design is clean and the test coverage is genuinely good — TestBuildFoundryServiceConfig_ValidatesAsHostedAgent round-trips the writer''s output through the reader''s FoundryProjectConfig.Validate(), and splitRuntime is verified as the correct inverse of the service target''s runtimeString.

Issues

1. (High) nextstep no longer recognizes the service init just wrote.
init.go calls nextstep.AssembleStateResolveAfterInit at the end of addToProject (init.go:2679-2680), but nextstep/state.go:438 filters services by svc.Host != agentHost where agentHost = "azure.ai.agent" (state.go:30). Since init now writes microsoft.foundry, the just-initialized service is skipped, so init''s own "next steps" output silently loses protocol-aware azd ai agent run guidance, azd env set <KEY> hints, and edit agent.yaml placeholder hints. doctor/checks_project.go:24 matches the same stale literal. These filters should also accept microsoft.foundry.

2. (Medium, by design) Container/docker agents become undeployable.
For a hosted agent with no codeConfiguration and no image (the default remote-build container path), buildFoundryServiceConfig falls into the default branch and sets agent.Docker — but validateHostedAgent (foundry_config.go:276) hard-rejects deployModeDocker. So init writes an azure.yaml that fails only later at deploy/provision. It''s acknowledged in comments, but consider emitting a warning at init time so users aren''t surprised at deploy.

3. (Low) Stale comment. init.go:2666-2674 still says the resolver "inspects … each azure.ai.agent service''s agent.yaml" — the host is now microsoft.foundry and init no longer writes agent.yaml.

4. (Low) foundryAgentInput.instructions is never populated. A prompt-kind agent (set when agentDef.Kind != AgentKindHosted) would be written with empty instructions. Latent only because prompt agents are rejected by the target today.

Minor: the container branch hardcodes Docker.Path: "Dockerfile" regardless of the actual Dockerfile name (no impact while docker mode is non-deployable).

Item #1 is the one I''d want addressed (or explicitly deferred with a tracking note) before merge, since it regresses init''s own UX immediately.

@therealjohn

Copy link
Copy Markdown
Contributor

This fixes #7962

@therealjohn therealjohn 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.

After more review, some changes:

  • each resource needs to be it's own service entry
  • each extension would own the schema for that service entry, similar to how the agents ext owns the schema for host: azure.ai.agents
  • each extension would need a hook on doing dataplane operations, similar to how the agents ext has a post-deploy hook to create an agent

Right now, AZD does not support different extensions contributing to the same service host - so separating them makes that possible, but it also means we can more easily manipulate each resource as a service.

Example: https://github.com/therealjohn/foundry-azd-config-preview/blob/separate-services/REFERENCE.md#project-basics

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

Labels

ext-agents azure.ai.agents extension

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ext-agents]: azd ai agent init writes unified microsoft.foundry config in azure.yaml

4 participants