-
Notifications
You must be signed in to change notification settings - Fork 340
docs(agents): propose explicit init and add commands #9135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,173 @@ | ||
| # PM Review: Explicit agent initialization and addition | ||
|
|
||
| **Status:** Proposed, awaiting approval | ||
|
|
||
| **Tracking issue:** [Azure/azure-dev#8383](https://github.com/Azure/azure-dev/issues/8383) | ||
|
|
||
| ## Problem statement | ||
|
|
||
| `azd ai agent init` currently performs different operations depending on the directory where it runs. | ||
|
|
||
| The same command can: | ||
|
|
||
| - create a new azd project and its first agent; | ||
| - add an agent to an existing project found in the current or a parent directory; | ||
| - initialize from local code, an agent manifest, or a project template; | ||
| - generate Bicep or Terraform when `--infra` is present. | ||
|
|
||
| This contextual behavior makes the command difficult to predict and debug. In particular, a user can intend to create a new project but unknowingly modify a parent project's `azure.yaml`. | ||
|
|
||
| ## Solution | ||
|
|
||
| Separate new-project initialization from adding an agent: | ||
|
|
||
| ```text | ||
| azd ai agent init Create a new agent project | ||
| azd ai agent add Add an agent to an existing project | ||
| ``` | ||
|
|
||
| Keep `--infra` on `init` for backward compatibility: | ||
|
|
||
| ```text | ||
| azd ai agent init <source> --infra # Initialize, then generate Bicep | ||
| azd ai agent init <source> --infra=terraform | ||
| azd ai agent init --infra # Generate IaC for an existing project | ||
| ``` | ||
|
|
||
| The command name determines whether agent setup creates or modifies a project. Filesystem detection may improve interactive choices, but it cannot silently switch `init` into `add`. | ||
|
|
||
| ## Goals | ||
|
|
||
| - Make project creation versus modification explicit. | ||
| - Prevent `init` from silently adding an agent to a current or parent project. | ||
| - Preserve the existing `--infra` workflows. | ||
| - Make interactive and non-interactive behavior predictable. | ||
| - Return actionable replacement commands when users invoke the wrong operation. | ||
| - Preserve existing project configuration when adding another agent. | ||
|
|
||
| ## Scope | ||
|
|
||
| ### In scope | ||
|
|
||
| - Add `azd ai agent add`. | ||
| - Restrict agent setup through `init` to new projects. | ||
| - Retain standalone and post-init `--infra` behavior. | ||
| - Support explicit sources: template, local code, agent manifest, existing definition, and container image. | ||
| - Use one visible source-selection prompt in interactive mode. | ||
| - Require an explicit source in non-interactive setup. | ||
| - Detect current and parent projects consistently. | ||
| - Preserve existing services and shared Foundry configuration when adding an agent. | ||
| - Provide compatibility guidance for existing `init` scripts and arguments. | ||
|
|
||
| ### Non-scope | ||
|
|
||
| - Merging a complete sample `azure.yaml` into an existing project. This remains tracked by [#8884](https://github.com/Azure/azure-dev/issues/8884). | ||
| - Moving agent addition into core `azd add`. | ||
| - Moving `--infra` to a third command. | ||
| - Automatically modifying existing Bicep or Terraform to add Foundry resources. | ||
| - Changing deployment behavior or when a remote Foundry agent is created. | ||
| - Supporting unsafe project shapes such as Aspire projects, multiple Foundry project services, or conflicting shared resources. | ||
|
|
||
| ## Current behavior | ||
|
|
||
| | Context | Current `azd ai agent init` behavior | User risk | | ||
| |---|---|---| | ||
| | Empty directory | Starts from a template | Mode is inferred from directory state. | | ||
| | Non-empty directory | Offers local code or template | The same command follows a different flow. | | ||
| | Existing project in current/parent directory | Adds the agent to that project | A parent project can be modified unintentionally. | | ||
| | Agent manifest/definition detected | Prompts to reuse it; may auto-accept in no-prompt mode | Adding a file changes command semantics. | | ||
| | Existing project plus `--infra` | Generates IaC only | `init` performs no initialization. | | ||
| | New project plus `--infra` | Initializes and then generates IaC | Useful workflow that should remain supported. | | ||
|
|
||
| ## Command contract | ||
|
|
||
| ### Commands | ||
|
|
||
| ```text | ||
| azd ai agent init [source] [--infra[=bicep|terraform]] [options] | ||
| azd ai agent add [source] [options] | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Most of those shape the agent rather than the project, so they either survive on
|
||
| ``` | ||
|
|
||
| ### Sources | ||
|
|
||
| ```text | ||
| --template | ||
|
|
||
| --from-code <directory> | ||
| --manifest <path-or-url> | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On main today The Sources block lists it flat, and Neither table catches this, because both key on Splitting the entry would close it: |
||
| --definition <path> | ||
| --image <registry/image[:tag]> | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Listing it flat here makes Splitting the entry would fix it: |
||
| ``` | ||
|
|
||
| Interactive use may omit the source and select one from a prompt. Non-interactive agent setup must supply a source. Existing-project `init --infra --no-prompt` is the exception because `--infra` completely identifies the requested operation. | ||
|
|
||
| ### Behavioral rules | ||
|
|
||
| | Invocation | Contract | | ||
| |---|---| | ||
| | `init <source>` with no project | Create a project and its initial agent. | | ||
| | `init <source> --infra` with no project | Create the project/agent, then generate Bicep. | | ||
| | `init <source> --infra=terraform` with no project | Create the project/agent, then generate Terraform. | | ||
| | `init --infra` in an existing compatible project | Generate Bicep only; do not add an agent. | | ||
| | `init --infra=terraform` in an existing compatible project | Generate Terraform only; do not add an agent. | | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #9291 landed on main one commit after this PR's base, and it settles the So this row is wider than it reads. Run Worth stating directly whether standalone |
||
| | `init <source>` in an existing project | Fail before mutation and suggest the equivalent `add` command. | | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This rule closes the silent-mutation hole from line 18, but it also closes the path the user in that scenario actually wanted. The problem statement is a user who intends to create a new project and instead modifies a parent's How wide that is depends on how Core Worth a row or an eighth review question: is nested project creation supported, and if so what is the gesture, a flag or cwd-only resolution for |
||
| | `init <source> --infra` in an existing project | Fail and suggest `add <source>`, followed by standalone `init --infra`. | | ||
| | `add <source>` in an existing project | Add the agent without initializing a project. | | ||
| | `add <source>` with no project | Fail and suggest the equivalent `init` command. | | ||
| | `add --infra` | Fail because infrastructure is project-wide and remains an init option. | | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Every other failure in both tables names the replacement: line 113 gives That leaves the goal on line 45 unmet for the case a user is most likely to hit, since |
||
|
|
||
| ## Decision table | ||
|
|
||
| | Command | Project found | Source supplied | `--infra` | Result | | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Both tables key on a single At this PR's base commit (19afc57), the standalone eject gate in Run Scope says "Detect current and parent projects consistently" but doesn't say which semantics win. Worth stating it directly: cwd-only or upward search, whether |
||
| |---|---:|---:|---:|---| | ||
| | `init` | No | Yes | No | Initialize project and agent. | | ||
| | `init` | No | Yes | Yes | Initialize, then generate IaC. | | ||
| | `init` | No | No | No | Interactive: choose source; non-interactive: fail. | | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Behavioral rules table above and this Decision table encode the same init/add contract with different columns, and they've already drifted. Behavioral rules restrict standalone |
||
| | `init` | No | No | Yes | Interactive: choose source, initialize, generate IaC; non-interactive: fail. | | ||
| | `init` | Yes | No | Yes | Generate IaC only. | | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The behavioral rules scope IaC-only to an existing |
||
| | `init` | Yes | Yes | No | Fail with `add` guidance. | | ||
| | `init` | Yes | Yes | Yes | Fail with `add`, then standalone `init --infra` guidance. | | ||
| | `add` | Yes | Yes | No | Add agent. | | ||
| | `add` | Yes | No | No | Interactive: choose source; non-interactive: fail. | | ||
| | `add` | No | Any | No | Fail with `init` guidance. | | ||
| | `add` | Any | Any | Yes | Fail; `--infra` is init-only. | | ||
|
|
||
| ## Architecture | ||
|
|
||
| The implementation separates project setup from agent registration: | ||
|
|
||
| ```text | ||
| init + source -> validate no project -> create project -> register agent | ||
| -> optional --infra | ||
|
|
||
| init --infra -> validate existing project -> generate IaC only | ||
|
|
||
| add + source -> validate existing project -> merge/register agent | ||
| ``` | ||
|
|
||
| Both `init` and `add` share source resolution and agent-registration logic. Registration merges the complete service graph instead of replacing existing Foundry services one at a time. The detailed engineering design defines concurrency, retry, and compatibility mechanics. | ||
|
|
||
|
|
||
| ## Decisions | ||
|
|
||
| 1. **Add a separate `add` command.** Project modification should be explicit instead of inferred from a parent `azure.yaml`. | ||
| 2. **Keep `init` as the new-project workflow.** New users still initialize a project and first agent in one command. | ||
| 3. **Retain `--infra` on init.** It is an explicit, established workflow and avoids a larger breaking change. | ||
| 4. **Do not automatically redirect `init` to `add`.** Automatic routing would preserve contextual mutation and misleading telemetry. | ||
| 5. **Require explicit sources in non-interactive setup.** Directory contents must not silently select code, manifest, or template behavior. | ||
| 6. **Preserve shared project resources.** Adding another agent must not erase existing project settings, deployments, connections, or toolboxes. | ||
| 7. **Reject unsupported existing-project infrastructure changes.** Existing Bicep/Terraform projects may use already provisioned Foundry resources, but setup will not pretend to modify their IaC. | ||
|
|
||
| ## Review questions | ||
|
|
||
| 1. **Is `azd ai agent add` the right command name and location?** Proposed: Yes. It clearly communicates project modification while keeping the change inside the agents extension. | ||
|
|
||
| 2. **Should `--infra` remain on `init`?** Proposed: Yes. Preserve both post-init and standalone behavior with strict argument validation. | ||
|
|
||
| 3. **Should `init` ever automatically call `add` when it finds a project?** Proposed: No. Fail before mutation and print the exact replacement command. | ||
|
|
||
| 4. **Should existing positional and `--src` forms remain temporarily?** Proposed: Yes, with deprecation warnings and deterministic translation to the new source options. | ||
|
|
||
|
|
||
| 5. **Should non-interactive setup require an explicit source?** Proposed: Yes, except standalone existing-project `init --infra`. | ||
|
|
||
| 6. **Should adding to existing Bicep/Terraform projects create new Foundry infrastructure?** Proposed: No. Support existing/brownfield Foundry resources only; automatic IaC composition needs a separate design. | ||
|
|
||
| 7. **Should complete unified-project adoption ship in the first implementation?** Proposed: Yes, for new projects only. Existing-project merge remains out of scope. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[source]is written positionally here and in theaddsignature on the next line, and both tables follow it withinit <source>/add <source>. But none of the five entries in the Sources block is positional. They're all flags. No row in either table can be typed as written.The slot isn't free either. On main, init's
Useisinit [<path>] [-m <manifest pointer>] [--src <source directory>]withArgs: cobra.MaximumNArgs(1), andapplyPositionalArgresolves that one positional into either--manifestor--srcdepending on what it points at. Review question 4 proposes keeping that form temporarily with deprecation warnings, so this signature makes the spelling you're deprecating the canonical one.addhas the sharper version of the problem. It's a new command with no legacy positional to preserve, soadd [source]hands it a slot that nothing in the doc defines.There's also a rule neither table can express. Today the positional and its matching flag are mutually exclusive:
applyPositionalArgreturnsCodeConflictingArgumentsforinit <path> -m <manifest>. If the positional survives on either command, that rule survives with it, and a yes/noSource suppliedcolumn can't say which spelling was used, let alone that both at once is an error.Writing the signatures as
init --<source>/add --<source>and giving the legacy positional its own row would settle all three.