Skip to content

feat(ai): add agent mode to emit instructions and skills#270

Draft
dmcilvaney wants to merge 8 commits into
microsoft:mainfrom
dmcilvaney:damcilva/new_skills_v2
Draft

feat(ai): add agent mode to emit instructions and skills#270
dmcilvaney wants to merge 8 commits into
microsoft:mainfrom
dmcilvaney:damcilva/new_skills_v2

Conversation

@dmcilvaney

Copy link
Copy Markdown
Contributor

No description provided.

Copilot AI review requested due to automatic review settings July 8, 2026 22:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 adds a new azldev docs agent command surface and an embedded agentskill registry so azldev can emit (and serve via MCP) version-matched AI agent skills and instruction wrappers, while tightening MCP server behavior to better support agent usage.

Changes:

  • Add docs agent install/show commands to emit agent scaffolding and expose a read-only MCP tool (docs-agent-show) for loading skill content on demand.
  • Introduce internal/app/azldev/agentskill/ as the single embedded source of truth for skills/instructions (templates + registries + rendering).
  • Update MCP server implementation to serialize tool calls and propagate a read-only hint from Cobra annotations into MCP tool schemas.

Reviewed changes

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

Show a summary per file
File Description
scenario/snapshots/TestMCPServerMode_1.snap.json Updates MCP snapshot for the new read-only docs-agent-show tool and schema changes.
internal/app/azldev/core/mcp/mcpserver.go Serializes MCP tool execution and propagates read-only tool hints from command annotations.
internal/app/azldev/command.go Adds read-only MCP annotation support via ExportAsReadOnlyMCPTool.
internal/app/azldev/cmds/docs/markdown.go Stops exporting docs-markdown as an MCP tool.
internal/app/azldev/cmds/docs/docs.go Registers the new docs agent command subtree.
internal/app/azldev/cmds/docs/agent.go Implements azldev docs agent install/show and .vscode/mcp.json upsert logic.
internal/app/azldev/cmds/docs/agent_test.go Adds unit tests for agent file emission and .vscode/mcp.json behavior.
internal/app/azldev/cmds/docs/agent_internal_test.go Adds internal tests for binding resolution and skill drift guards.
internal/app/azldev/agentskill/doc.go Documents the agentskill architecture and rendering model.
internal/app/azldev/agentskill/content/update-component.md.tmpl Adds embedded skill template content for updating component locks.
internal/app/azldev/agentskill/content/skill-wrapper.md.tmpl Adds wrapper template that redirects to the read-only MCP tool for full skill text.
internal/app/azldev/agentskill/content/remove-component.md.tmpl Adds embedded skill template content for removing components.
internal/app/azldev/agentskill/content/overlays.md.tmpl Adds embedded skill template content for overlays workflows and rules.
internal/app/azldev/agentskill/content/mock.md.tmpl Adds embedded skill template content for mock chroot usage.
internal/app/azldev/agentskill/content/instruction-wrapper.md.tmpl Adds instruction wrapper template for path-scoped guidance.
internal/app/azldev/agentskill/content/image.md.tmpl Adds embedded skill template content for image workflows.
internal/app/azldev/agentskill/content/comp-toml.md.tmpl Adds embedded skill template content for component TOML authoring.
internal/app/azldev/agentskill/content/build-component.md.tmpl Adds embedded skill template content for build/debug workflows.
internal/app/azldev/agentskill/content/azldev.md.tmpl Adds primary azldev overview skill template content.
internal/app/azldev/agentskill/content/add-component.md.tmpl Adds embedded skill template content for adding components.
internal/app/azldev/agentskill/agentskill.go Implements registries, rendering, layouts, and file emission for skills/instructions.
internal/app/azldev/agentskill/agentskill_test.go Adds tests validating skill/instruction rendering and invariants.
docs/user/reference/cli/azldev_docs.md Regenerates CLI docs to include azldev docs agent.
docs/user/reference/cli/azldev_docs_agent.md Adds generated CLI docs for azldev docs agent.
docs/user/reference/cli/azldev_docs_agent_show.md Adds generated CLI docs for azldev docs agent show.
docs/user/reference/cli/azldev_docs_agent_install.md Adds generated CLI docs for azldev docs agent install.
docs/user/README.md Adds user-docs index entry for AI agent setup.
docs/user/how-to/set-up-ai-agents.md Adds user guide for emitting agent files and wiring MCP.
docs/developer/prds/agent-scaffolding.prd.md Adds PRD describing broader agent scaffolding roadmap.
.github/instructions/agent-skills.instructions.md Adds maintainer instructions for editing/validating embedded skills.
.github/copilot-instructions.md Updates contributor guidance to note the new agentskill single source of truth.

Comment on lines +191 to +195
// LIMITATION: the [azldev.Env] here is created once when the MCP server starts and is reused
// for every tool call. Per-call global flags parsed by this Execute (e.g. '--dry-run',
// '--project') update the App's flag fields but are NOT re-threaded into this reused Env, so
// env.DryRun() and the loaded config still reflect the server's startup values. As a result a
// mutating tool invoked with '--dry-run=true' would still write. Until the MCP rework gives
Comment on lines +191 to +195
// LIMITATION: the [azldev.Env] here is created once when the MCP server starts and is reused
// for every tool call. Per-call global flags parsed by this Execute (e.g. '--dry-run',
// '--project') update the App's flag fields but are NOT re-threaded into this reused Env, so
// env.DryRun() and the loaded config still reflect the server's startup values. As a result a
// mutating tool invoked with '--dry-run=true' would still write. Until the MCP rework gives
Comment on lines +149 to +152
// Skills returns the registered skills in emission order.
func Skills() []Skill {
return skills
}
Comment on lines +258 to +261
// Instructions returns the registered instruction files in emission order.
func Instructions() []Instruction {
return instructions
}
Accept the skill as a positional argument with shell completion, so `azldev docs
agent show <TAB>` lists the valid skills instead of forcing you to guess and hit
an error. Running with no skill now lists the available skills (browse) rather
than erroring, and an unknown name reports the valid choices. The --skill flag is
kept (it gives the docs-agent-show MCP tool a typed parameter and preserves
back-compat) and also completes.
The add-component skill told agents to write prep-sources inspection output to
`$(mktemp -d)`, which lands in /tmp and conflicts with repos (e.g. azurelinux)
whose conventions forbid bare mktemp and require an in-project scratch dir. Add
a WorkDir binding resolved from Project.WorkDir (default build/work) and template
the scratch path as `{{ .WorkDir }}/scratch/<name>`, so the skill follows each
repo's configured, gitignored work directory instead of steering agents off it.
Copilot AI review requested due to automatic review settings July 9, 2026 19:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 31 out of 31 changed files in this pull request and generated 5 comments.

Comment on lines +191 to +195
// LIMITATION: the [azldev.Env] here is created once when the MCP server starts and is reused
// for every tool call. Per-call global flags parsed by this Execute (e.g. '--dry-run',
// '--project') update the App's flag fields but are NOT re-threaded into this reused Env, so
// env.DryRun() and the loaded config still reflect the server's startup values. As a result a
// mutating tool invoked with '--dry-run=true' would still write. Until the MCP rework gives
Comment on lines +191 to +197
// LIMITATION: the [azldev.Env] here is created once when the MCP server starts and is reused
// for every tool call. Per-call global flags parsed by this Execute (e.g. '--dry-run',
// '--project') update the App's flag fields but are NOT re-threaded into this reused Env, so
// env.DryRun() and the loaded config still reflect the server's startup values. As a result a
// mutating tool invoked with '--dry-run=true' would still write. Until the MCP rework gives
// each call its own Env, only expose read-only commands as MCP tools (do not add
// [azldev.ExportAsMCPTool] to commands that mutate state).
Comment on lines +149 to +152
// Skills returns the registered skills in emission order.
func Skills() []Skill {
return skills
}
Comment on lines +258 to +261
// Instructions returns the registered instruction files in emission order.
func Instructions() []Instruction {
return instructions
}
Comment on lines +53 to +55
3. A little hand-written prose here is fine, if it helps direct agents to the right skill. Keep it short, and avoid
repeating the skill content.
3. Keep the count-based tests happy: `Files()` emits one file per skill plus one per instruction.
Copilot AI review requested due to automatic review settings July 10, 2026 00:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 31 out of 31 changed files in this pull request and generated 2 comments.

Comment on lines +191 to +195
// LIMITATION: the [azldev.Env] here is created once when the MCP server starts and is reused
// for every tool call. Per-call global flags parsed by this Execute (e.g. '--dry-run',
// '--project') update the App's flag fields but are NOT re-threaded into this reused Env, so
// env.DryRun() and the loaded config still reflect the server's startup values. As a result a
// mutating tool invoked with '--dry-run=true' would still write. Until the MCP rework gives
Comment on lines +252 to +253
// ponytail: plain JSON only. A JSONC file with comments fails here with a clear error
// rather than being silently rewritten and losing the comments.
Copilot AI review requested due to automatic review settings July 10, 2026 18:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 31 out of 31 changed files in this pull request and generated 4 comments.

Comment on lines +191 to +195
// LIMITATION: the [azldev.Env] here is created once when the MCP server starts and is reused
// for every tool call. Per-call global flags parsed by this Execute (e.g. '--dry-run',
// '--project') update the App's flag fields but are NOT re-threaded into this reused Env, so
// env.DryRun() and the loaded config still reflect the server's startup values. As a result a
// mutating tool invoked with '--dry-run=true' would still write. Until the MCP rework gives
Comment on lines +269 to +270
// ponytail: plain JSON only. A JSONC file with comments fails here with a clear error
// rather than being silently rewritten and losing the comments.
Comment on lines +405 to +406
return "", nil, fmt.Errorf("unknown skill %q; choose one of: %s",
requested, strings.Join(names, ", "))
Comment on lines +53 to +55
3. A little hand-written prose here is fine, if it helps direct agents to the right skill. Keep it short, and avoid
repeating the skill content.
3. Keep the count-based tests happy: `Files()` emits one file per skill plus one per instruction.
Copilot AI review requested due to automatic review settings July 11, 2026 00:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 31 out of 31 changed files in this pull request and generated 2 comments.

Comment on lines +191 to +195
// LIMITATION: the [azldev.Env] here is created once when the MCP server starts and is reused
// for every tool call. Per-call global flags parsed by this Execute (e.g. '--dry-run',
// '--project') update the App's flag fields but are NOT re-threaded into this reused Env, so
// env.DryRun() and the loaded config still reflect the server's startup values. As a result a
// mutating tool invoked with '--dry-run=true' would still write. Until the MCP rework gives
Comment on lines +277 to +280
servers, _ := config[serversKey].(map[string]any)
if servers == nil {
servers = map[string]any{}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants