Skip to content

azure_ai_search dependent resource fails when storage is not also requested #62

@rogerbarreto

Description

@rogerbarreto

Summary

When provisioning Azure AI Search as a dependent resource (via AI_PROJECT_DEPENDENT_RESOURCES containing {"resource":"azure_ai_search","connectionName":"search"}), infra/core/search/azure_ai_search.bicep requires a co-provisioned storage account and silently fails when one is not also requested.

The bicep takes storageAccountResourceId as a required param and uses it for an existing Storage Account reference plus a Storage Blob Data Reader role assignment and a knowledge container. If the consumer only requests azure_ai_search (not also storage), infra/main.bicep passes an empty string for storageAccountResourceId, which makes the existing reference resolve to last(split('', '/')) → empty name and the deployment fails.

Why this matters

The companion azd ai agent init flow in Azure/azure-dev (init.go ToolKindAzureAiSearch block) only auto-prompts for two tool ids when scanning the agent manifest:

if toolResource.Id == "bing_grounding" || toolResource.Id == "azure_ai_search" {
    // prompt for connection name, append to project.Resource entries
}

There is no auto-prompt for storage, so an agent author who declares kind: tool / id: azure_ai_search in their agent.manifest.yaml ends up with a generated azure.yaml that requests only azure_ai_search → provision blows up.

End users have to manually edit the generated azure.yaml after azd ai agent init and append a storage entry, which is fragile and surprising. We hit this in microsoft-foundry/foundry-samples-pr#283 (Azure AI Search RAG sample for .NET Agent Framework).

Repro

  1. Author an agent.manifest.yaml with kind: tool / id: azure_ai_search (no storage).
  2. azd ai agent init -m <manifest> (accept the prompt for the search connection name).
  3. azd provision.
  4. Bicep deployment of azure-ai-search module fails resolving the existing storage account.

Proposed fix (pick one)

Option A: Make storage optional in azure_ai_search.bicep. Skip the Storage Blob Data Reader role assignment and the knowledge container creation when storageAccountResourceId is empty:

@description('Optional. Azure storage account resource ID for the search-to-storage indexer scenario. When empty, the search-to-storage RBAC and knowledge container are skipped.')
param storageAccountResourceId string = ''

// gate the existing storage reference + container + role assignment behind a non-empty check
var hasStorage = !empty(storageAccountResourceId)

resource storageAccount '...' existing = if (hasStorage) {
  name: last(split(storageAccountResourceId, '/'))
}

resource storageContainer '...' = if (hasStorage) { ... }
resource searchToStorageRoleAssignment '...' = if (hasStorage) { ... }

This matches how ai-project.bicep already gates the azureAiSearch module behind hasSearchConnection and how it treats other dependent resources as independent.

Option B: In Azure/azure-dev, also auto-add a storage dependent resource whenever azure_ai_search is requested. Less ideal because (1) it forces a Storage Account on agents that don't need indexer scenarios, and (2) it puts knowledge of starter internals into the extension.

Option C: Both. Make storage optional in the bicep (Option A) and have the extension auto-pair them only when the user actually wants the indexer scenario (future azd ai agent init UX, e.g. a follow-up prompt).

Option A is the smallest, most local fix and unblocks the manifest-only flow today. Happy to send a PR if that direction is preferred.

Workaround (for users hitting this today)

After azd ai agent init, manually append storage to the agent service's resources: array in the generated azure.yaml:

services:
  <agent-name>:
    config:
      resources:
        - resource: azure_ai_search
          connectionName: search
        - resource: storage
          connectionName: storage

Context

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions