Azure-Samples / Azure-Samples/azd-ai-starter-basic

azure_ai_search dependent resource fails when storage is not also requested

Open
#62 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Bicep
Stars
16
Forks
20
PR merge metrics
No merged PRs in 30d

Description

## 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](https://github.com/Azure/azure-dev/blob/main/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go)) only auto-prompts for two tool ids when scanning the agent manifest:

```go
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](https://github.com/microsoft-foundry/foundry-samples-pr/pull/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 ` (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:

```bicep
@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`:

```yaml
services:
:
config:
resources:
- resource: azure_ai_search
connectionName: search
- resource: storage
connectionName: storage
```

## Context

- Sample triggering this: [microsoft-foundry/foundry-samples-pr#283](https://github.com/microsoft-foundry/foundry-samples-pr/pull/283)
- Related upstream extension code: [`init.go`](https://github.com/Azure/azure-dev/blob/main/cli/azd/extensions/azure.ai.agents/internal/cmd/init.go), [`listen.go`](https://github.com/Azure/azure-dev/blob/main/cli/azd/extensions/azure.ai.agents/internal/cmd/listen.go), [`parse.go`](https://github.com/Azure/azure-dev/blob/main/cli/azd/extensions/azure.ai.agents/internal/pkg/agents/agent_yaml/parse.go)
- Cross-reference with in-flight starter PR [#61 (flat module library)](https://github.com/Azure-Samples/azd-ai-starter-basic/pull/61) so the fix lands cleanly on whichever layout wins.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.