Skip to content

doc: design spec for azd ai agent init reuse of existing agent.yaml#8325

Open
hund030 wants to merge 4 commits into
mainfrom
zhihuan/feat-agent-init-reuse-yaml
Open

doc: design spec for azd ai agent init reuse of existing agent.yaml#8325
hund030 wants to merge 4 commits into
mainfrom
zhihuan/feat-agent-init-reuse-yaml

Conversation

@hund030
Copy link
Copy Markdown
Collaborator

@hund030 hund030 commented May 22, 2026

Adds the design spec for #7268: when azd ai agent init runs in a directory that already contains a bare agent.yaml definition, reuse it instead of prompting to overwrite (interactive) or failing fast (--no-prompt, behavior added in #8266).

The manifest half of the issue is documented as already handled by upstream detectLocalManifest; this work fills only the bare-definition gap.

Highlights for review

  • §3 / §9 decision 1: detection lives at RunE next to detectLocalManifest, not inside InitFromCodeAction.Run (avoids forcing users through the init-mode prompt before reuse fires).
  • §2 / §9 decision 2: Foundry project resolution is intentionally out of scope, matching the issue's "less to ask and just setup azure.yaml" wording. Tracked as a follow-up.
  • §4.6 / §9 decision 8: the original add 'azd ai agent sample list' to browse templates and improve non-interactive init #8266 fail-fast guard inside InitFromCodeAction.Run is retained as a safety net for the decline-reuse fallback path (user declines the reuse prompt and then picks "Use the code in the current directory").
  • §4.2 / §9 decision 7: loadAgentDefinitionFile runs full ValidateAgentDefinition (kind + name + structural checks), not just name validation.
  • §9 decision 6: documents the implementation discovery that the manifest case is already covered upstream, so our helper only handles bare definitions and malformed manifests.

Related

hund030 added 2 commits May 21, 2026 17:27
During implementation we discovered the manifest case is already
handled upstream by detectLocalManifest in init.go, and our reuse
helper only owns the bare-definition case. Update the spec to
reflect that — narrow the scope, remove the dead reuseLocalManifest
sub-section, and update file references to current main.
Copilot AI review requested due to automatic review settings May 22, 2026 10:57
@hund030 hund030 changed the title doc: design spec for zd ai agent init reuse of existing agent.yaml doc: design spec for azd ai agent init reuse of existing agent.yaml May 22, 2026
@hund030 hund030 linked an issue May 22, 2026 that may be closed by this pull request
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a design spec documenting the planned change to azd ai agent init (Azure AI Agents extension) to detect and reuse an existing bare agent.yaml definition in the target directory, avoiding overwrite prompts/fail-fast behavior and only writing the azure.yaml service entry.

Changes:

  • Introduces a new design document describing dispatch ordering, reuse flow, and error handling for existing bare agent.yaml.
  • Documents key design decisions (where detection happens, non-goals like Foundry project resolution, and why manifest reuse is left to existing logic).
  • Provides a decision tree and test plan guidance for the intended behavior.

Comment thread cli/azd/docs/design/azure-ai-agent-init-reuse-agent-yaml.md

This change adds **definition reuse**: when the user has a bare `agent.yaml` (a YAML file without a top-level `template:` wrapper) in the target directory and runs `azd ai agent init`, the command treats that file as the source of truth, skips the from-code prompts, and writes only the `azure.yaml` service entry, matching the issue's wording: *"if it's a definition, then we have less to ask and just setup azure.yaml."*

Manifest reuse (the other half of the issue) is already handled by upstream `detectLocalManifest` in `init.go`, which intercepts valid local manifests (regardless of filename) and routes them through `runInitFromManifest`. This spec does **not** touch that path; it only fills the bare-definition gap.
Comment on lines +56 to +59
1. `detectLocalManifest(srcDir)`: existing helper, runs first. If it returns a valid manifest path, `flags.manifestPointer` is set (with an optional confirmation prompt in interactive mode) and the manifest pipeline runs as today.
2. **If `flags.manifestPointer` is still empty**, the new step runs: `findExistingAgentYaml(srcDir)` does a shallow `os.Stat` against the four candidate filenames. Any hit at this point is guaranteed to either be a bare definition (rejected by `detectLocalManifest` for lacking `template:`) or a malformed manifest (rejected for failing manifest validation).
3. On a hit, a confirmation prompt ("An existing agent definition was found at ... Use it?") is shown; in `--no-prompt` mode the answer auto-defaults to yes.
4. On confirmation, `runReuseDefinition(ctx, flags, azdClient, httpClient, srcDir, existingPath)` is called and the command returns. The init-mode prompt and the from-code scaffolding sequence are both skipped.
Comment on lines +40 to +44
| Upstream manifest detection | `cmd/init.go` (`detectLocalManifest`) | **Unchanged**. |
| Manifest pipeline | `cmd/init.go` (`runInitFromManifest`) | **Unchanged**. |
| Definition reuse helpers | `cmd/init_from_code_reuse.go` (new file) | `findExistingAgentYaml`, `runReuseDefinition`, `loadAgentDefinitionFile`. |
| `azure.yaml` writer | `cmd/init_from_code.go` (`addToProject`) | **Reused as-is** by `runReuseDefinition`. |
| Project / environment bootstrap | `cmd/init.go` (`ensureProject`, `getExistingEnvironment`, `createNewEnvironment`) | **Reused as-is**: the reuse path runs the same setup `runInitFromManifest` does. |
Comment on lines +120 to +126
## 7. Test Plan

- **Pre-existing unit tests** in `cli/azd/extensions/azure.ai.agents/internal/cmd/*_test.go` continue to pass. The no-yaml regression is covered by today's `init_from_code_test.go`.
- **Manual e2e** against the locally-built `azd` + extension. Three scenarios:
- **Definition reuse**: write a bare `agent.yaml`, run `azd ai agent init --no-prompt`; assert no init-mode prompt, `Detected existing agent definition: ...` printed, `azure.yaml` contains the agent's `name:`, on-disk `agent.yaml` byte-identical to input.
- **Manifest reuse**: write `agent.manifest.yaml`, run with `AZURE_SUBSCRIPTION_ID` and `AZURE_AI_PROJECT_ID` set; assert the existing upstream manifest path runs unchanged and `azure.yaml` ends up with the manifest's `template.name`.
- **Invalid yaml**: write broken YAML; assert non-zero exit, error references `agent.yaml`, `azure.yaml` not mutated.

1. `loadAgentDefinitionFile(path)`: reads the file, rejects anything with a top-level `template:` (manifest-shaped but invalid, produces a targeted error), unmarshals to `agent_yaml.ContainerAgent` so `CodeConfiguration` is preserved, and validates the name via `agent_yaml.ValidateAgentName`.
2. Prints `Detected existing agent definition: <relative-path> (name: <def.Name>).`
3. Bootstraps project + env using the same helpers `runInitFromManifest` uses: `ensureProject`, then `getExistingEnvironment` / `createNewEnvironment` (the env is named `<def.Name>-dev` when none was supplied via `-e`).
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 22, 2026

📋 Prioritization Note

Thanks for the contribution! The linked issue isn't in the current milestone yet.
Review may take a bit longer — reach out to @rajeshkamal5050 or @kristenwomack if you'd like to discuss prioritization.

@github-actions github-actions Bot added the ext-agents azure.ai.{agents,connections,inspector,projects,routines,skills,toolboxes} extensions label May 22, 2026
- Tighten manifest-detection wording: detectLocalManifest scans four fixed
  filenames, not arbitrary ones.
- Correct file-location references in the touch-points table
  (detectLocalManifest lives in init_from_templates_helpers.go;
  createNewEnvironment lives in init_foundry_resources_helpers.go).
- Document the declined-manifest edge case: when detectLocalManifest finds
  a valid manifest that the user declines, the reuse scan must be skipped
  so the declined file is not mis-classified as an invalid definition.
- Note that the derived env name goes through sanitizeAgentName to match
  the existing from-code path.
- Test plan: remove the inaccurate claim that init_from_code_test.go covers
  the no-yaml regression; clarify the existing unit tests cover unrelated
  helpers and that the new paths are exercised by manual e2e instead.
hund030 added a commit that referenced this pull request May 25, 2026
Copilot review of #8325 caught an edge case in the lifted dispatch: when
detectLocalManifest finds a valid manifest in srcDir but the user declines
the 'Use it?' prompt, flags.manifestPointer stays empty and the new
definition reuse scan would re-discover the same on-disk file. The bare
definition loader rejects files with a top-level 'template:' key, so the
declined manifest would be reported as an invalid definition with
CodeInvalidAgentManifest, blocking init and contradicting the user's
choice to start fresh.

Track the decline explicitly with a manifestDetectedButDeclined flag and
gate the definition reuse scan on it being false. Non-interactive mode is
unaffected because --no-prompt auto-accepts the manifest.
@hund030
Copy link
Copy Markdown
Collaborator Author

hund030 commented May 25, 2026

Thanks for the careful review. Summary of how each comment was addressed:

  • Line 9 (current --no-prompt error) — replied inline. The spec is accurate as written; the exterrors.Cancelled path you referenced is the interactive-decline path, not the --no-prompt path.
  • Line 13 (manifest detection filename scope) — tightened wording to call out the four fixed candidate filenames.
  • Line 44 (file locations) — corrected detectLocalManifest to cmd/init_from_templates_helpers.go and createNewEnvironment to cmd/init_foundry_resources_helpers.go.
  • Line 59 (declined-manifest edge case) — added an explicit edge-case sub-bullet in §4.1 plus a one-line note on the implementation guard. Implementation guard pushed to the companion PR feat(agents): reuse existing agent.yaml on init from existing code #8326 as commit 32b8331e8 (manifestDetectedButDeclined flag).
  • Line 67 (env name sanitization) — clarified the derived env name goes through sanitizeAgentName.
  • Line 126 (test plan) — removed the inaccurate claim that init_from_code_test.go covers no-yaml regression; clarified the existing unit tests cover unrelated helpers and the new paths are exercised by manual e2e.

hund030 added a commit that referenced this pull request May 25, 2026
Copilot review of #8325 caught an edge case in the lifted dispatch: when
detectLocalManifest finds a valid manifest in srcDir but the user declines
the 'Use it?' prompt, flags.manifestPointer stays empty and the new
definition reuse scan would re-discover the same on-disk file. The bare
definition loader rejects files with a top-level 'template:' key, so the
declined manifest would be reported as an invalid definition with
CodeInvalidAgentManifest, blocking init and contradicting the user's
choice to start fresh.

Track the decline explicitly with a manifestDetectedButDeclined flag and
gate the definition reuse scan on it being false. Non-interactive mode is
unaffected because --no-prompt auto-accepts the manifest.
Updates the spec to match what was actually shipped in PR #8326:

- §3 / §9 #8: overwrite guard inside InitFromCodeAction.Run is now
  documented as retained (covering all four candidate filenames), not
  removed. §4.6 added to describe the decline-reuse fallback path.
- §3 / §4.2 / §6 / §9 #7: validation switched from ValidateAgentName to
  ValidateAgentDefinition so missing/invalid kind, name format, and
  kind-specific structural checks are caught.
- §3: language detection inside addToProject is limited to bare-definition
  filenames; lookup table updated to reflect that.
- §4.2: runReuseDefinition now includes the absolute-src normalization
  step and a displayPath-aware `Reusing existing <file>` message.
- §4.3 / §6: error suggestion text uses displayPath, not hardcoded
  `agent.yaml`.
- §5: new row for the declined-reuse fallback; --src row notes abs->rel.
- §7: documents the actual unit tests that now ship in
  init_from_code_reuse_test.go.
- §10: decision tree expanded to cover the manifest-decline branch, the
  init-mode prompt with the overwrite guard, and the abs-src step.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ext-agents azure.ai.{agents,connections,inspector,projects,routines,skills,toolboxes} extensions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow azd ai agent init to detect and reuse an existing agent.yaml

2 participants