Skip to content

feat(agents): reuse existing agent.yaml on init from existing code#8326

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

feat(agents): reuse existing agent.yaml on init from existing code#8326
hund030 wants to merge 4 commits into
mainfrom
zhihuan/feat-agent-init-reuse-yaml-impl

Conversation

@hund030
Copy link
Copy Markdown
Collaborator

@hund030 hund030 commented May 22, 2026

Closes #7268.

Summary

When azd ai agent init runs in a directory that already contains a bare agent.yaml definition (no template: wrapper), reuse it instead of either prompting to overwrite (interactive) or failing with CodeInvalidAgentManifest: agent.yaml already exists at ... (--no-prompt, added in #8266). Matches the issue's wording: "if it's a definition, then we have less to ask and just setup azure.yaml."

The manifest half of the issue is already handled by upstream detectLocalManifest and is unchanged.

Changes

  • cmd/init.go RunE: new detection block alongside detectLocalManifest. A user with a local agent.yaml skips both the init-mode prompt and the from-code scaffolding. Symmetric confirmation prompt (auto-yes under --no-prompt). Tracks manifestDetectedButDeclined so a declined manifest is not re-discovered and mis-classified.
  • cmd/init_from_code.go: retained the agent.yaml already exists guard from add 'azd ai agent sample list' to browse templates and improve non-interactive init #8266 (using findExistingAgentYaml so it covers all four candidate filenames). The guard now only fires on the decline-reuse fallback path (user declines the RunE prompt and then picks "Use the code in the current directory"); it prevents silent overwrite. Lang detection in addToProject is limited to bare-definition filenames so a leftover manifest cannot short-circuit detection.
  • cmd/init_from_code_reuse.go (new): findExistingAgentYaml, runReuseDefinition, loadAgentDefinitionFile. Runs full agent_yaml.ValidateAgentDefinition (catches missing/invalid kind, name format, kind-specific structural checks), bootstraps project + env, normalizes absolute --src to project-relative, calls existing addToProject. Error/info messages use the actual detected filename so users with agent.yml see agent.yml, not a hardcoded agent.yaml. The on-disk file is never rewritten.
  • Foundry project resolution is intentionally skipped on this path (out of scope per the issue's "less to ask" wording). Users needing it can set AZURE_AI_PROJECT_ID or use the manifest pipeline.

Unit tests in cmd/init_from_code_reuse_test.go cover findExistingAgentYaml (filename precedence, shallow scan), loadAgentDefinitionFile (happy path + reject manifest-shaped, missing kind, invalid name, broken yaml), and the runReuseDefinition failure branches that short-circuit before any azd gRPC calls.

Verification

Manual e2e on Windows against the locally-built CLI:

Scenario Before After
bare agent.yaml + --no-prompt agent.yaml already exists at ... exit 1 reuse, exit 0
bare agent.yaml interactive, accept reuse prompt mode prompt -> overwrite prompt -> proceed single "Use it?" prompt -> reuse
bare agent.yaml interactive, decline reuse prompt -> pick "from code" mode scaffold silently overwrites the file overwrite guard fires; default-no protects the file
agent.manifest.yaml upstream ok upstream ok (unchanged)
broken agent.yaml overwrite-related error structured CodeInvalidAgentManifest referencing the actual filename
no agent.yaml scaffold flow unchanged

Related

Copilot AI review requested due to automatic review settings May 22, 2026 10:58
@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.

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

This PR updates the azd ai agent init flow in the Azure AI Agents extension to detect an existing bare agent.yaml (definition-only, no template: wrapper) and reuse it instead of overwriting/failing, aligning with #7268.

Changes:

  • Add a pre-dispatch detection step in init to find and optionally reuse an existing bare agent definition YAML.
  • Remove the earlier agent.yaml already exists guard from the from-code init path (intended to be handled by the new upstream dispatch).
  • Add a new reuse implementation that loads an existing definition and wires it into azure.yaml without rewriting the definition file.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.

File Description
cli/azd/extensions/azure.ai.agents/internal/cmd/init.go Adds detection/prompting to reuse an existing bare agent definition before prompting for init mode / scaffolding.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code.go Removes the pre-flight overwrite protection for existing agent.yaml in the from-code path.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code_reuse.go New helpers to locate, parse, and reuse an existing definition file and update azure.yaml.
Comments suppressed due to low confidence (1)

cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code.go:87

  • The overwrite guard for an existing agent.yaml was removed, but writeDefinitionToSrcDir still unconditionally writes srcDir/agent.yaml. If the user declines the new “reuse existing definition” prompt upstream, the from-code path will now silently overwrite the existing file (data loss). Reintroduce an overwrite confirmation here (or ensure init.go treats “decline reuse” as a cancellation / requires --force before overwriting).
	// No manifest pointer provided - process local agent code
	// Create a definition based on user prompts
	localDefinition, err := a.createDefinitionFromLocalAgent(ctx)
	if err != nil {
		return fmt.Errorf("failed to create definition from local agent: %w", err)

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code_reuse.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code_reuse.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code_reuse.go Outdated
@github-actions github-actions Bot added the ext-agents azure.ai.{agents,connections,inspector,projects,routines,skills,toolboxes} extensions label May 22, 2026
hund030 added a commit that referenced this pull request May 25, 2026
Five fixes plus targeted unit tests, in response to inline review on
#8326.

- Use go.yaml.in/yaml/v3 in init_from_code_reuse.go so custom
  UnmarshalYAML methods on agent_yaml types (e.g. PropertySchema) are
  honored. The package previously used gopkg.in/yaml.v3 which has an
  incompatible Node type and silently bypassed custom decoders.
- Run agent_yaml.ValidateAgentDefinition on the loaded bytes so missing
  or invalid kind, structural shape, etc. fail fast with the same error
  the manifest pipeline produces, instead of slipping through and
  failing later.
- Walk agentYamlCandidates in addToProject's language-detection block
  instead of hardcoding 'agent.yaml', so dotnet runtimes declared in
  agent.yml are detected correctly.
- Replace hardcoded 'agent.yaml' in user-facing error/info messages
  with displayPath, so the reuse path correctly references agent.yml or
  agent.manifest.yaml when those are the detected file.
- Mirror InitFromCodeAction.Run's absolute --src normalization: convert
  an absolute path to a project-relative path before calling
  addToProject so azure.yaml's RelativePath stays portable.

Unit tests added in init_from_code_reuse_test.go cover findExistingAgentYaml
(filename precedence, shallow scan, dir-vs-file), loadAgentDefinitionFile
(happy path, missing kind, invalid name, manifest-shaped rejection,
broken yaml), and the runReuseDefinition failure paths that surface
CodeInvalidAgentManifest without needing the project gRPC mock.
hund030 added 3 commits May 25, 2026 14:23
Closes #7268. When `azd ai agent init` runs in a directory that already
contains a bare `agent.yaml` definition, the from-code action now detects
and reuses it instead of either prompting to overwrite (interactive) or
failing fast with `CodeInvalidAgentManifest: agent.yaml already exists at
...` (--no-prompt mode, added in #8266).

The reuse path:

- Validates the file as a bare AgentDefinition (rejects manifest-shaped
  files that fail upstream detectLocalManifest validation with a targeted
  error).
- Skips the model / instructions / runtime / entry-point prompt sequence
  in createDefinitionFromLocalAgent.
- Ensures an azd environment exists (the prompt sequence normally bootstraps
  this) and calls the existing addToProject helper.
- Never rewrites the on-disk agent.yaml — it is treated as authoritative.

Valid local manifest files (top-level `template:`) are unchanged: they
continue to be intercepted upstream by detectLocalManifest in init.go and
routed through runInitFromManifest before InitFromCodeAction.Run is reached.

Design spec: cli/azd/docs/design/azure-ai-agent-init-reuse-agent-yaml.md
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.
Five fixes plus targeted unit tests, in response to inline review on
#8326.

- Use go.yaml.in/yaml/v3 in init_from_code_reuse.go so custom
  UnmarshalYAML methods on agent_yaml types (e.g. PropertySchema) are
  honored. The package previously used gopkg.in/yaml.v3 which has an
  incompatible Node type and silently bypassed custom decoders.
- Run agent_yaml.ValidateAgentDefinition on the loaded bytes so missing
  or invalid kind, structural shape, etc. fail fast with the same error
  the manifest pipeline produces, instead of slipping through and
  failing later.
- Walk agentYamlCandidates in addToProject's language-detection block
  instead of hardcoding 'agent.yaml', so dotnet runtimes declared in
  agent.yml are detected correctly.
- Replace hardcoded 'agent.yaml' in user-facing error/info messages
  with displayPath, so the reuse path correctly references agent.yml or
  agent.manifest.yaml when those are the detected file.
- Mirror InitFromCodeAction.Run's absolute --src normalization: convert
  an absolute path to a project-relative path before calling
  addToProject so azure.yaml's RelativePath stays portable.

Unit tests added in init_from_code_reuse_test.go cover findExistingAgentYaml
(filename precedence, shallow scan, dir-vs-file), loadAgentDefinitionFile
(happy path, missing kind, invalid name, manifest-shaped rejection,
broken yaml), and the runReuseDefinition failure paths that surface
CodeInvalidAgentManifest without needing the project gRPC mock.
@hund030 hund030 force-pushed the zhihuan/feat-agent-init-reuse-yaml-impl branch from e5e1c69 to 7fd6728 Compare May 25, 2026 06:28
@hund030 hund030 requested a review from Copilot May 25, 2026 06:37
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

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code_reuse.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code_reuse_test.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code_reuse_test.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code.go
Five Copilot findings on the new reuse path:

- Lang detection in addToProject (init_from_code.go) restricted to
  agent.yaml / agent.yml so a leftover agent.manifest.* does not
  short-circuit detection before the actual definition file is read.
- agentYamlCandidates reordered to match detectLocalManifest in
  init_from_templates_helpers.go (manifest.yaml -> yaml -> manifest.yml -> yml).
- errors.As replaced with errors.AsType[T] in init_from_code_reuse_test.go
  per the cli/azd/AGENTS.md Go 1.26 modernization rule.
- Overwrite guard restored inside InitFromCodeAction.Run so the from-code
  scaffold cannot silently overwrite an existing agent.yaml when the user
  declined the reuse prompt in RunE. Matches the safety invariant from
  #8266 (--no-prompt fails fast; interactive defaults to no).

Also trims verbose doc and inline comments across the touched files.
hund030 added a commit that referenced this pull request May 25, 2026
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