feat(agents): deploy using an existing acr image#8104
feat(agents): deploy using an existing acr image#8104huimiu wants to merge 9 commits intoAzure:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support in the azure.ai.agents azd extension for deploying hosted/container agents using a pre-built container image specified in agent.yaml, optionally skipping Dockerfile-based build/package/publish steps.
Changes:
- Introduces an
imagefield onagent_yaml.ContainerAgentand wires it through hosted-agent API request mapping. - Updates hosted-agent deployment flow to prompt once per deploy whether to use the configured pre-built image vs. building/publishing, and uses that choice to skip package/publish and resolve the final image URL.
- Adds unit tests covering image parsing, prompt caching, and package/publish skipping behavior.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go | Adds pre-built image selection/caching and uses it to skip package/publish and resolve deploy image URL. |
| cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent_test.go | Adds prompt-service stubs and tests for pre-built image behavior in package/publish and helper methods. |
| cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_yaml/yaml.go | Adds Image field to ContainerAgent YAML/JSON model and documents intended behavior. |
| cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_yaml/parse_test.go | Adds parse/round-trip coverage for the new image field in manifest/template YAML. |
| cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_yaml/map.go | Defaults hosted-agent image URL from agent.yaml (still allowing buildConfig override) and updates error messaging. |
| cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_yaml/map_test.go | Adds tests validating agent image usage and buildConfig override precedence. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
wbreza
left a comment
There was a problem hiding this comment.
Code Review — PR #8104
Overall: ✅ Well-structured PR — no blockers. Caching logic is correct, image priority works properly, and test coverage is solid for happy paths.
Findings
🟡 Medium
M1 — getPreBuiltImageURL silently swallows parse errors (service_target_agent.go ~lines 638–649)
Returns "" on both file-read and YAML-unmarshal errors. If agent.yaml exists but has a syntax error around the image: field, the pre-built image prompt is silently skipped with no user indication. Other paths in the same file (Deploy flow) properly propagate parse errors.
Suggestion: Distinguish "file not found" (acceptable silent empty) from "file exists but parse failed" (should warn or propagate).
M2 — Missing test for prompt cancellation/error path (service_target_agent_test.go)
shouldUsePreBuiltImage wraps prompt errors with exterrors.FromPrompt(...), but this path is untested. Should verify error propagates and cache stays nil for retries.
M3 — Missing complementary test cases (service_target_agent_test.go)
No test for Publish proceeding normally when user chose Dockerfile (usePreBuiltImage = false), and no test for getPreBuiltImageURL with malformed YAML.
🔵 Low
L1 — Redundant YAML re-read (service_target_agent.go)
getPreBuiltImageURL independently reads and parses agent.yaml; the Deploy flow re-reads it. Could accept the parsed struct or cache the parse result to avoid TOCTOU inconsistency.
L2 — Implicit non-interactive behavior (service_target_agent.go)
When running with --no-prompt, Prompt().Select() may default to pre-built (index 0) or error. The intended CI/CD behavior should be documented.
L3 — No empty-endpoint guard (service_target_agent.go)
registerAgentEnvironmentVariables doesn't guard against empty AZURE_AI_PROJECT_ENDPOINT, though the deploy path validates it upstream.
What Looks Good 👍
- Caching pattern (
*booltri-state) is correct and idiomatic - Image priority (YAML image > published artifact) works properly
- Prompt UX displays actual image URL with sensible default
- YAML/JSON tags follow existing conventions
- Solid test coverage for parse, caching, and skip behaviors
| func (p *AgentServiceTargetProvider) shouldUsePreBuiltImage( | ||
| ctx context.Context, | ||
| ) (bool, error) { | ||
| // Return cached decision if already prompted |
There was a problem hiding this comment.
@therealjohn, do we actually want this cached? Without some way to detect underlying code changes, this could possibly lead to unexpected behavior, or multiple deployments when a user realizes they won't be prompted again.
There was a problem hiding this comment.
Safer for now to not cache it - but provide a way to --no-prompt so an agent can deploy or CI/CD can work.
There was a problem hiding this comment.
Worth noting: the prompt default is index 0 (pre-built image). In --no-prompt mode, the host returns the default, so CI/CD would silently use the pre-built image instead of building. If "build" is the safer CI default, swap the choice order or set defaultIndex to 1.
There was a problem hiding this comment.
Thanks for catching this. I've updated the prompt so that:
In both interactive and non-interactive (AZD_NO_PROMPT=true) mode, build from Dockerfile is always the default, interactive mode prompts the user to explicitly opt into the pre-built image, while non-interactive mode skips the prompt entirely and always builds.
jongio
left a comment
There was a problem hiding this comment.
One test gap I didn't see covered in existing feedback:
TestShouldUsePreBuiltImage_PromptsForConfiguredImage exercises the "build" path (index 1) but not the pre-built path (index 0). The feature's happy path through the prompt isn't tested - only via preset caching in TestShouldUsePreBuiltImage_CachesDecision.
… cache prompt decision
#7988
This pull request adds support for using pre-built container images when deploying hosted agents, allowing users to skip Dockerfile builds and pushes if an image is specified in agent.yaml. The implementation prompts the user to choose between using the pre-built image or building a new one, and this decision is cached per deployment.
Imagefield to theContainerAgentstruct, allowing users to specify a pre-built container image in agent.yaml. If set, this image is used for deployment instead of building from a Dockerfile.Test