Skip to content

azure.ai.agent host strips service-level hooks (and ${ENV} image templating) from azure.yaml on deploy/provision #9152

Description

@qiaozha

Output from azd version

azd version 1.27.0 (commit dcd7c53153bada76c3c9462b57fab53d4f8b69a0) (stable)

Describe the bug

When a service uses the experimental azure.ai.agent host, azd rewrites the agent service block in azure.yaml on deploy/provision and strips any fields it does not model — most notably the service-level hooks block (and ${ENV_VAR} templating in image).

This means a per-service predeploy / postdeploy hook configured on an azure.ai.agent service:

  • runs once for the deploy where it was just added, then
  • disappears from azure.yaml after the agent project handler writes the normalized block back, so it never runs again on subsequent deploys.

Service-level hooks are valid per the base azd schema, so this is surprising and silent (no warning, no error) — the block just vanishes.

Repro steps

azure.yaml:

name: my-app
services:
  agent:
    project: src/my-agent
    host: azure.ai.agent
    language: python
    image: myregistry.azurecr.io/my-agent:${MY_TAG}   # templating also gets flattened
    kind: hosted
    name: my-chat-agent
    protocols:
      - protocol: responses
        version: 2.0.0
    startupCommand: python init.py
    hooks:
      predeploy:
        shell: sh
        run: ./hooks/agent-predeploy.sh
        interactive: true
      postdeploy:
        shell: sh
        run: ./hooks/agent-postdeploy.sh
        interactive: true
  1. azd deploy agent — the predeploy/postdeploy hooks execute for this run.
  2. Inspect azure.yaml afterward (or git diff): the entire hooks: block under services.agent is gone, and image: has been rewritten to a literal value (the ${MY_TAG} template is flattened).
  3. azd deploy agent again — the hooks no longer run, because they were removed from azure.yaml.

The same stripping is observable on preprovision/provision; a log line we captured:

invokeProjectHandler error for event preprovision: failed to update environment
for service "agent": agent.yaml is not valid: validation failed:
  - template.kind must be one of: [hosted workflow], got ''

which shows the agent project handler is (re)writing the composed agent definition.

Expected behavior

azd should preserve user-authored fields on an azure.ai.agent service that it doesn't own — at minimum the service-level hooks block, which is a first-class, schema-valid service field. Round-tripping the agent block through the extension's typed model should not silently drop hooks (or flatten ${ENV_VAR} templating in image).

At the very least, azd should emit a warning when it drops user-authored fields during the agent block rewrite, rather than doing it silently.

Root-cause analysis (what we found)

hooks is schema-valid on the agent service:

  • Base schema schemas/v1.0/azure.yaml.json: every service supports hooks (predeploy, postdeploy, …). The azure.ai.agent host conditional only disables k8s, apiVersion, and networknot hooks.
  • Extension schema cli/azd/extensions/azure.ai.agents/schemas/azure.ai.agent.json: top-level "additionalProperties": true, so extra keys like hooks pass validation.

So this is not a validation rejection. It appears to be the agent project handler's write-back: it deserializes the agent block into the extension's typed model (whose known fields are exactly those in azure.ai.agent.json — which does not include hooks), then re-serializes only the modeled fields back into azure.yaml. additionalProperties: true relaxes validation but the struct-based round-trip doesn't preserve unmodeled keys, so hooks is dropped.

Impact

Any workflow that relies on per-service agent hooks (e.g. granting the hosted agent's runtime managed identity its RBAC in postdeploy, or building/pushing the container image in predeploy) breaks after the first deploy, with no indication why. It's easy to misdiagnose as a formatter or an accidental revert.

Workaround

Move the agent-specific logic out of the (strippable) per-service hooks block and into the top-level command hooks (hooks.predeploy / hooks.postdeploy at the root of azure.yaml), which azd does not rewrite. Because command hooks have no native "which service" signal, gate expensive steps behind an env var (e.g. only build the agent image when the deploy targets the agent).

Environment

  • azd 1.27.0 (stable), macOS
  • Host: azure.ai.agent (hosted Foundry container agent), azure.ai.agents extension

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingext-agentsazure.ai.agents extension

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions