Skip to content

feat(agents): support private non-ACR registry connections - #9586

Open
Wei Meng (m5i-work) wants to merge 12 commits into
Azure:m5i/9588-image-passthrough-basefrom
m5i-work:m5i/9582-private-registry
Open

feat(agents): support private non-ACR registry connections#9586
Wei Meng (m5i-work) wants to merge 12 commits into
Azure:m5i/9588-image-passthrough-basefrom
m5i-work:m5i/9582-private-registry

Conversation

@m5i-work

@m5i-work Wei Meng (m5i-work) commented Aug 14, 2026

Copy link
Copy Markdown
Member

Summary

  • add optional registryConnectionId authoring for hosted container agents
  • map it to definition.container_configuration.registry_connection_id
  • add non-interactive azd ai agent init --registry-connection <name-or-id> support
  • verify external connections by Foundry connection name or ID when an existing project is available
  • validate sibling azure.ai.connection dependencies through uses
  • use core docker.imagePassthrough for flag-based, manifest-based, and private-registry pre-built images
  • delegate passthrough Package and Publish artifact handling to core azd without a Docker build or prompt
  • keep ACR build and code-deploy behavior unchanged when image passthrough is not enabled
  • preserve the property through unified azure.yaml and legacy agent-definition round trips

The implementation is registry-neutral: it does not inspect registry vendors, hostnames, token-exchange semantics, or vendor-specific credential fields.

Fixes #9582

Important

This PR is stacked on #9588 and now adopts its core image-passthrough capability. Both existing BYO-image flows and private non-ACR registry flows generate docker.imagePassthrough: true and delegate the container artifact lifecycle to core azd.

Tested scenarios

A real E2E was run in westus2 using a private JFrog Docker repository, a brownfield Foundry project, and JFrog OIDC token exchange bound to the Foundry project managed identity. Anonymous manifest access returned 401 before deployment, confirming that the image was private.

1. Initialize from a pre-created registry connection

Prerequisite: This scenario requires an existing Microsoft Foundry project and connection. Before running init, create the connection through the Foundry portal or Azure CLI (az rest). The private image, JFrog OIDC provider and identity binding, and Entra audience application must also already exist. azd references the connection but does not bootstrap these prerequisites.

The original live run used a pre-created connection. After the portal or Azure CLI creates it, reference its name during non-interactive agent init:

PROJECT_ID="<foundry-project-resource-id>"
CONNECTION_NAME="private-registry-init"

azd ai agent init --no-prompt \
  --agent-name private-registry-init-agent \
  --image <private-jfrog-host>/<repository>/echo-agent:<tag> \
  --project-id "$PROJECT_ID" \
  --registry-connection "$CONNECTION_NAME"

azd deploy --no-prompt

azd ai agent invoke private-registry-init-agent \
  --protocol invocations \
  --new-session \
  --input-file request.json

Key generated azure.yaml output:

services:
  private-registry-init-agent:
    host: azure.ai.agent
    image: <private-jfrog-host>/<repository>/echo-agent:<tag>
    docker:
      imagePassthrough: true
    uses:
      - existing-foundry-project
    registryConnectionId: private-registry-init

The existing external connection was not added to uses. azd provision is intentionally omitted after init because both the Foundry project and the connection now exist; init records the existing project deployment context and the agent can deploy directly.

Key deployed-agent output:

{
  "version": "1",
  "status": "active",
  "definition": {
    "container_configuration": {
      "image": "<private-jfrog-host>/<repository>/echo-agent:<tag>",
      "registry_connection_id": "private-registry-init"
    },
    "protocol_versions": [
      { "protocol": "invocations", "version": "1.0.0" }
    ]
  }
}

Key invocation output:

Agent:    private-registry-init-agent (remote, invocations protocol)
Session:  <session-id> (assigned by server)
Trace ID: <trace-id>

"reply": "Hello! You said: 'Hello from the azd init private-registry demo'."
Server responded in 2.484s

The Foundry session logstream showed container startup, GET /readiness returning 200, and both invocation requests returning 200.

2. Declarative brownfield project and sibling connection

Configuration:

infra:
  provider: microsoft.foundry

services:
  existing-foundry-project:
    host: azure.ai.project
    endpoint: https://<account>.services.ai.azure.com/api/projects/<project>

  private-registry-declarative:
    host: azure.ai.connection
    uses:
      - existing-foundry-project
    category: CustomKeys
    target: ${REGISTRY_URL}
    authType: CustomKeys
    credentials:
      keys:
        audience: ${REGISTRY_AUDIENCE}
        tokenEndpoint: ${REGISTRY_TOKEN_ENDPOINT}
        body.provider_name: ${REGISTRY_PROVIDER}
    metadata:
      type: registry_connection
      mode: oauth_token_exchange

  private-registry-yaml-agent:
    host: azure.ai.agent
    uses:
      - existing-foundry-project
      - private-registry-declarative
    kind: hosted
    name: private-registry-yaml-agent
    image: <private-jfrog-host>/<repository>/echo-agent:<tag>
    docker:
      imagePassthrough: true
    registryConnectionId: private-registry-declarative
    protocols:
      - protocol: invocations
        version: 1.0.0

Commands:

azd env set AZURE_AI_PROJECT_ID <foundry-project-resource-id>
azd env set REGISTRY_URL https://<private-jfrog-host>
azd env set REGISTRY_AUDIENCE <entra-audience-app-id>
azd env set REGISTRY_TOKEN_ENDPOINT /access/api/v1/oidc/token
azd env set REGISTRY_PROVIDER <oidc-provider-name>

azd provision --no-prompt
azd deploy --no-prompt

azd ai agent invoke private-registry-yaml-agent \
  --protocol invocations \
  --new-session \
  --input-file request.json

Key provisioning output:

SUCCESS: Your application was provisioned in Azure in 36 seconds.

The provisioned project connection reported:

{
  "name": "private-registry-declarative",
  "properties": {
    "category": "CustomKeys",
    "authType": "CustomKeys",
    "metadata": {
      "type": "registry_connection",
      "mode": "oauth_token_exchange"
    }
  }
}

Key deployment and invocation output:

private-registry-declarative  Done
private-registry-yaml-agent   Done
SUCCESS: Your application was deployed to Azure in 48 seconds.

Agent:    private-registry-yaml-agent (remote, invocations protocol)
Session:  <session-id> (assigned by server)
Trace ID: <trace-id>

"reply": "Hello! You said: 'Hello from the declarative brownfield private-registry demo'."
Server responded in 2.562s

The deployed definition contained container_configuration.registry_connection_id: private-registry-declarative, and the Foundry session logstream showed readiness and invocation HTTP 200 responses.

Core image passthrough integration

The original declarative E2E exposed a core lifecycle gap before the extension deploy phase:

Pulling container source image
Error response from daemon: ... Authentication is required

Without an explicit passthrough signal, the core Docker framework treated the top-level image as an external source image and attempted to pull and tag it locally before the extension could deploy it by reference. The earlier E2E used docker.remoteBuild to avoid that pull, but remoteBuild describes an ACR Tasks build rather than an already-published image and was not the intended contract.

The current implementation is stacked on #9588 and replaces that workaround:

  • normal init, adopted-project init, and init-from-code all use a shared container decision: pre-built image means docker.imagePassthrough: true; source build means docker.remoteBuild, disabled for VNET-injected projects;
  • flag-based, manifest-defined, and private-registry pre-built images remain in their source registry and never enable remote build;
  • extension Package and Publish delegate to the core passthrough lifecycle and preserve the original remote image reference;
  • AZD_AGENT_SKIP_ACR remains only as a legacy provisioning signal; new configurations do not use it to select the container lifecycle;
  • pre-passthrough projects retain a narrow compatibility bridge for the old image + docker + AZD_AGENT_SKIP_ACR=true shape;
  • registry-backed images require an explicit registry host and repository for every authoring path before Foundry deployment.

The live JFrog results above validate the Foundry connection, registry token exchange, hosted-container startup, and invocation path. They were captured before the final core passthrough wiring, while the current lifecycle integration is covered by the automated tests listed below.

Trace capture

The E2E retained sanitized local artifacts for CLI demo preparation:

  • PTY transcripts for init, provision, deploy, and invoke
  • generated and declarative azure.yaml files
  • deployed agent-version JSON
  • raw invocation response headers and bodies
  • CLI trace IDs and APIM/request/invocation/session correlation IDs
  • hosted-agent session SSE logstreams

No Application Insights connection was configured for this temporary project, so runtime traces came from Foundry hosted-session logstreams rather than App Insights. The artifact bundle passed a scan against the JFrog username and administrator token.

All temporary Foundry, Entra, JFrog, session, and image resources were deleted after the run; the test resource group was empty afterward.

Automated validation

cd cli/azd/extensions/azure.ai.agents
go build ./...
go test ./... -short
go fix ./...

# Repository/schema checks
git diff --check
jq empty schemas/azure.ai.agent.json

Focused coverage includes:

  • authoring and legacy round trips
  • schema constraints
  • exact REST placement and omission
  • code-deploy omission
  • public non-ACR and ACR behavior without a registry connection
  • non-interactive flag validation and generated configuration
  • flag-based, manifest-based, adopted-project, and private-registry image passthrough generation
  • source-build remote-build behavior, including VNET-injected projects
  • passthrough Package and Publish delegation without a build or prompt
  • provisioning-only ACR skip behavior and the narrow legacy compatibility bridge
  • fully qualified private-registry image validation across init and deploy
  • external connection name/ID lookup
  • sibling connection uses validation
  • arbitrary credentials.keys.body.* pass-through

@m5i-work Wei Meng (m5i-work) added feature Feature request area/extensions Extensions (general) ext-agents azure.ai.agents extension labels Aug 14, 2026
@azure-pipelines

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

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
6 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

Adds registry-neutral private container registry support for hosted Foundry agents, backed by core image passthrough.

Changes:

  • Adds docker.imagePassthrough across core lifecycle, schemas, protobuf, and targets.
  • Adds registry connection authoring, validation, REST mapping, and dependency checks.
  • Updates init flows, documentation, and tests.

Reviewed changes

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

Show a summary per file
File Description
schemas/v1.0/azure.yaml.json Adds passthrough schema.
schemas/alpha/azure.yaml.json Adds alpha passthrough schema.
docs/reference/azure-yaml-schema.md Documents Docker options.
cli/azd/pkg/project/service_target_containerapp.go Routes passthrough publishing.
cli/azd/pkg/project/service_target_containerapp_test.go Tests Container Apps passthrough.
cli/azd/pkg/project/service_target_appservice.go Routes App Service passthrough.
cli/azd/pkg/project/service_target_appservice_test.go Tests App Service passthrough.
cli/azd/pkg/project/service_target_aks.go Supports AKS passthrough.
cli/azd/pkg/project/mapper_registry.go Maps the new Docker field.
cli/azd/pkg/project/mapper_registry_test.go Tests protobuf mappings.
cli/azd/pkg/project/framework_service_docker.go Defines ImagePassthrough.
cli/azd/pkg/project/framework_service_docker_test.go Tests Docker lifecycle behavior.
cli/azd/pkg/project/container_helper.go Implements passthrough artifacts.
cli/azd/pkg/project/container_helper_test.go Tests passthrough validation.
cli/azd/pkg/azdext/models.pb.go Regenerates protobuf models.
cli/azd/grpc/proto/models.proto Adds the wire field.
cli/azd/extensions/azure.ai.agents/schemas/azure.ai.agent.json Adds registry connection schema.
cli/azd/extensions/azure.ai.agents/internal/synthesis/synthesizer_test.go Tests arbitrary credential keys.
cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go Integrates connection deployment.
cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent_test.go Tests agent lifecycle integration.
cli/azd/extensions/azure.ai.agents/internal/project/image_passthrough.go Bridges the new protobuf field.
cli/azd/extensions/azure.ai.agents/internal/project/foundry_dependencies.go Validates sibling connections.
cli/azd/extensions/azure.ai.agents/internal/project/foundry_dependencies_test.go Tests dependency validation.
cli/azd/extensions/azure.ai.agents/internal/project/doc_examples_test.go Extends schema example checks.
cli/azd/extensions/azure.ai.agents/internal/project/agent_definition.go Preserves connection authoring.
cli/azd/extensions/azure.ai.agents/internal/project/agent_definition_test.go Tests definition round trips.
cli/azd/extensions/azure.ai.agents/internal/pkg/containerref/reference.go Validates image references.
cli/azd/extensions/azure.ai.agents/internal/pkg/containerref/reference_test.go Tests reference validation.
cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_yaml/yaml.go Adds the YAML property.
cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_yaml/parse_test.go Tests YAML round trips.
cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_yaml/map.go Maps to the REST request.
cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_yaml/map_test.go Tests request mapping.
cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_api/models.go Adds the REST field.
cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_api/models_test.go Tests JSON placement.
cli/azd/extensions/azure.ai.agents/internal/cmd/init.go Adds registry init support.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_test.go Tests init validation and generation.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_reuse_project_agent_test.go Covers reuse flag detection.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code.go Selects passthrough for images.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_foundry_resources_helpers.go Verifies existing connections.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_foundry_resources_helpers_test.go Tests connection lookup.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go Updates adopted image lifecycles.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt_deploymode_test.go Tests adopted deploy modes.
cli/azd/extensions/azure.ai.agents/internal/cmd/hosted_container_config.go Centralizes lifecycle selection.
cli/azd/extensions/azure.ai.agents/internal/cmd/hosted_container_config_test.go Tests lifecycle selection.
cli/azd/extensions/azure.ai.agents/internal/cmd/helpers.go Clarifies the legacy ACR signal.
cli/azd/extensions/azure.ai.agents/docs/private-networking.md Updates private ACR examples.
cli/azd/docs/environment-variables.md Updates skip-ACR documentation.
Suppressed comments (2)

cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go:1866

  • [azd-code-reviewer] This is not the narrow legacy-shape check described in the PR: core's ServiceConfig-to-proto mapper always converts the value-typed Docker options into a non-nil pointer (cli/azd/pkg/project/mapper_registry.go:129-132), even when docker was absent. Consequently any hand-authored image can still be forced onto the pre-built path whenever the environment-level AZD_AGENT_SKIP_ACR is true. Preserve actual docker-property presence (or another reliable legacy marker) before using this compatibility branch.
	if p.serviceConfig.GetDocker() != nil &&
		!DockerImagePassthrough(p.serviceConfig.GetDocker()) &&
		p.shouldSkipACRForEnvironment(ctx) {

cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go:1632

  • [azd-code-reviewer] This image check runs before the existing-config check below, so a service with authoritative codeConfiguration plus a leftover top-level image is silently switched back to container deploy and its code configuration is removed. Keep the documented “respect sample code config” behavior by only enabling passthrough when code deploy is not configured.
	if strings.TrimSpace(svc.GetImage()) != "" {

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go Outdated
Copilot AI review requested due to automatic review settings August 18, 2026 10:28
@m5i-work
Wei Meng (m5i-work) force-pushed the m5i/9582-private-registry branch from a6d4726 to cd58991 Compare August 18, 2026 10:28

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 51 out of 52 changed files in this pull request and generated 1 comment.

Suppressed comments (4)

cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go:726

  • [azd-code-reviewer] The Docker framework has already run ContainerHelper.Package and appended its passthrough artifact before the service target's Package method is called (service_manager.go:421-431). Calling the container package RPC again returns a second identical artifact, so normal azd package results contain duplicates. Let the target return an empty result here and retain the framework-owned artifact already in serviceContext.Package.
	if DockerImagePassthrough(serviceConfig.GetDocker()) {
		progress("Packaging pre-built container image")
		artifacts, err := p.packageContainer(ctx, serviceConfig, serviceContext)
		if err != nil {
			return nil, err
		}
		return &azdext.ServicePackageResult{Artifacts: artifacts}, nil

cli/azd/extensions/azure.ai.agents/internal/pkg/containerref/reference.go:16

  • [azd-code-reviewer] This alternation accepts either a tag or a digest, but rejects the valid OCI form registry.example.com/team/agent:v1@sha256:.... Core passthrough explicitly preserves tag-and-digest references, so registry-backed agents currently reject an image that the underlying lifecycle supports. Make the tag and digest independent optional groups and add this case to the table test.
		`(?::[\w][\w.-]{0,127}|@sha256:[0-9a-fA-F]{64})?$`,

cli/azd/extensions/azure.ai.agents/internal/cmd/init.go:4514

  • [azd-code-reviewer] Manifest-backed registry images are only checked for presence here. Unlike --image, a manifest containing image: agent:v1 plus registryConnectionId completes init and writes an invalid project, then fails later during package/deploy when validateRegistryConnectionDefinition requires an explicit registry host. Apply the same fully-qualified reference validation during init so all authoring paths fail before mutating the project.
	if preBuiltImageForInit(agentManifest, a.flags.image) == "" {
		return exterrors.Validation(
			exterrors.CodeInvalidParameter,
			"a registry connection requires a pre-built image",
			"Pass --image <registry/image:tag> or provide an image in the hosted-agent manifest",
		)
	}

cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go:1715

  • [azd-code-reviewer] Adoption detects a pre-built image only from the core service-level image. AgentDefinitionFromResolvedService also supports images supplied by an inline/file-referenced legacy definition, and the registry-connection branch above accepts that resolved image, but this check then misses it and configures a source build/ACR instead of passthrough. Derive the effective image from resolvedAgent.Image when the service field is empty.
	// An adopted service that already declares an image also uses passthrough,
	// even when --image was not supplied during this init. An explicit code mode
	// overrides a leftover image.
	if strings.TrimSpace(svc.GetImage()) != "" && flags.deployMode != "code" {
		if err := applyContainerDeployToService(ctx, azdClient, serviceName, svc, svc.GetImage()); err != nil {
			return false, err
		}
		return false, nil

Comment thread cli/azd/extensions/azure.ai.agents/internal/project/image_passthrough.go Outdated
Copilot AI review requested due to automatic review settings August 18, 2026 10:39

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 52 out of 53 changed files in this pull request and generated 1 comment.

Suppressed comments (3)

cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go:1653

  • [azd-code-reviewer] The adopted-project path also treats any nonempty existing service/definition image as valid when --registry-connection is supplied. Because early flag validation defers to the manifest when --image is absent, an unqualified or URL-form image is persisted with passthrough and only fails later during deployment. Validate effectiveImage with the shared container-reference validator here.
		if effectiveImage == "" && hasDefinition {

cli/azd/extensions/azure.ai.agents/internal/cmd/init.go:4514

  • [azd-code-reviewer] This only checks that a manifest-supplied image is nonempty. Unlike --image, an image such as agent:v1 or https://registry.example.com/agent:v1 passes init and is not rejected until deployment. Apply the same fully-qualified-reference validation to the effective image before persisting the registry connection.
	if preBuiltImageForInit(agentManifest, a.flags.image) == "" {

cli/azd/extensions/azure.ai.agents/internal/pkg/containerref/reference.go:16

  • [azd-code-reviewer] This grammar hard-codes SHA-256 digests, so otherwise valid fully qualified OCI references using another digest algorithm (for example registry.example.com/team/agent@sha512:<digest>) are rejected by init and deployment. Reuse the standard distribution/reference parser and separately require an explicit registry component rather than maintaining a narrower custom grammar.
		`(?::[\w][\w.-]{0,127})?(?:@sha256:[0-9a-fA-F]{64})?$`,

Copilot AI review requested due to automatic review settings August 18, 2026 14:12

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 52 out of 53 changed files in this pull request and generated no new comments.

Suppressed comments (2)

cli/azd/extensions/azure.ai.agents/internal/cmd/init.go:4514

  • [azd-code-reviewer] This only checks that a manifest supplies some image. --registry-connection -m agent.yaml therefore accepts an unqualified value such as agent:v1, even though the init contract requires a fully qualified registry/repository and deployment later rejects it. Run the same image validation used for --image against the effective manifest image before modifying the project.
	if preBuiltImageForInit(agentManifest, a.flags.image) == "" {

cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go:1711

  • [azd-code-reviewer] The adopted definition was resolved above, but passthrough considers only the service-level image. For a supported local $ref/legacy definition whose image exists only in resolvedAgent.Image, this falls through to a source build (and an explicit registry connection can be written with remoteBuild: true), so core never receives the required service image/passthrough pair. Promote the resolved image to the service-level image and use it when selecting the Docker lifecycle, or reject this authoring shape during adoption.
	// An adopted service that already declares an image also uses passthrough,
	// even when --image was not supplied during this init. An explicit code mode
	// overrides a leftover image.
	if strings.TrimSpace(svc.GetImage()) != "" && flags.deployMode != "code" {
		if err := applyContainerDeployToService(ctx, azdClient, serviceName, svc, svc.GetImage()); err != nil {

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 32 out of 32 changed files in this pull request and generated no new comments.

Suppressed comments (4)

cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go:214

  • [azd-code-reviewer] This early guard only detects a literal inline registryConnectionId. Supported $ref and legacy agent.yaml definitions can carry the property while ServiceConfigProps contains only $ref or no definition, so Initialize returns successfully and core can pull/build the private image before Package resolves and rejects the configuration. Make registry-backed file definitions visible to pre-framework validation, or explicitly reject/migrate this shape before core container processing.
	if props == nil || props.GetFields()["registryConnectionId"] == nil {
		return nil

cli/azd/extensions/azure.ai.agents/internal/project/service_target_agent.go:1871

  • [azd-code-reviewer] References accepted by the shared validator can still fail earlier in AgentDefinitionFromService: agent_definition.go:773 uses containerImageRefRe, which rejects registry ports and tag-plus-digest references. Thus --image localhost:5000/agent:v1 or agent:v1@sha256:... passes init but fails deployment before reaching this check. Replace the legacy loader checks with the shared validator and add loader-level coverage.
	if !containerref.IsFullyQualified(image) {

cli/azd/extensions/azure.ai.agents/internal/cmd/init.go:2089

  • [azd-code-reviewer] This verifies every manifest-provided registry reference as if it were external. If the manifest also declares a matching ConnectionResource, that connection is intentionally created later by emitResourceServices, so lookup against an existing project fails before init can generate the sibling azure.ai.connection service. Skip remote verification for locally declared connection resources and let uses enforce their provisioning order.
		if err := a.verifyRegistryConnection(ctx); err != nil {
			return err

cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go:1710

  • [azd-code-reviewer] Explicit code mode bypasses the existing-image branch, but applyCodeDeployToService removes only docker and leaves an existing registryConnectionId. The adopted project is therefore rewritten to an invalid code-plus-registry configuration, and the next command fails schema/Initialize validation. Clear the registry reference when switching to code deploy, or reject the switch before mutating the service.
	// An adopted service that already declares an image also uses passthrough,
	// even when --image was not supplied during this init. An explicit code mode
	// overrides a leftover image.
	if strings.TrimSpace(svc.GetImage()) != "" && flags.deployMode != "code" {

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init.go
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init.go
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/pkg/containerref/reference.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/pkg/containerref/reference.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/project/image_passthrough.go Outdated
@github-actions github-actions Bot added the ext-projects azure.ai.projects extension label Aug 20, 2026

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.

approving, obviously pending the underlying core changes

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-projects azure.ai.projects extension feature Feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[azure.ai.agents] Support private non-ACR registry connections for hosted agents

3 participants