Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
2ebbac7
Add Copilot SDK foundation alongside existing langchaingo agent
wbreza Feb 25, 2026
cbf7d0d
Add 'copilot' as default agent provider type
wbreza Feb 25, 2026
2f5828a
Add diagnostic logging to Copilot SDK agent pipeline
wbreza Feb 25, 2026
b1cd08e
Wire CopilotAgentFactory into AgentFactory for automatic delegation
wbreza Feb 25, 2026
7364d8e
Enable SDK debug logging to diagnose CLI process startup failure
wbreza Feb 25, 2026
88b24ee
Update copilot-sdk to v0.1.26-preview.0
wbreza Feb 25, 2026
80f8be4
Auto-discover native Copilot CLI binary from @github/copilot-sdk npm …
wbreza Feb 26, 2026
bb8fceb
Fix: explicitly allow tools in PreToolUse hook
wbreza Feb 26, 2026
8638c40
Fix: add OnPermissionRequest handler to approve tool permissions
wbreza Feb 26, 2026
5291508
Fix: increase SendAndWait timeout to 10 minutes
wbreza Feb 26, 2026
a314b40
Use Send + idle event instead of SendAndWait to avoid timeout
wbreza Feb 26, 2026
ccf9e2c
Integrate azd consent system and required plugin auto-install
wbreza Feb 27, 2026
feac369
Fix mage namespace discovery for dev:install target
wbreza Mar 9, 2026
7fb113a
Fix OTel schema version conflict causing panic on startup
wbreza Mar 9, 2026
fd5985d
Update copilot-sdk to v0.1.32
wbreza Mar 9, 2026
fffe954
Fix OTel semconv schema mismatch: update to v1.40.0
wbreza Mar 9, 2026
40e6a0c
Fix: approve CLI permission requests, use consent only in PreToolUse
wbreza Mar 9, 2026
4448042
Add AgentDisplay for consolidated Copilot SDK UX rendering
wbreza Mar 9, 2026
d41c5c8
Fix reasoning display and show relative paths in tool summaries
wbreza Mar 9, 2026
2a267f4
Show full reasoning in scrolling window with flush on transitions
wbreza Mar 9, 2026
a74518e
UX: add blank line before spinner and change text to 'Working...'
wbreza Mar 9, 2026
5d8bdc0
Check if plugin is installed before install/update
wbreza Mar 9, 2026
95309df
Simplify init to single prompt + wire OnUserInputRequest handler
wbreza Mar 9, 2026
2b510ca
UX: use intent as spinner text, move reasoning above spinner, set int…
wbreza Mar 9, 2026
b30a465
Strip markdown from ask_user prompts, render reasoning with markdown,…
wbreza Mar 9, 2026
104b45b
Support AllowFreeform in ask_user with 'Other' choice option
wbreza Mar 9, 2026
9d32386
Explicitly invoke @azure-prepare and @azure-validate skills in init p…
wbreza Mar 9, 2026
85307cf
Specify 'azd' recipe for azure-prepare and azure-validate skills
wbreza Mar 9, 2026
25d1e96
Store Copilot session files in .azure/copilot relative to cwd
wbreza Mar 9, 2026
389381d
Fix skill discovery: revert ConfigDir, use qualified skill names
wbreza Mar 9, 2026
e39484f
Pass installed plugins via --plugin-dir for headless mode discovery
wbreza Mar 9, 2026
23c36d6
Scope plugin discovery to Azure plugin only
wbreza Mar 9, 2026
19a8d1a
Use SkillDirectories instead of --plugin-dir for skill loading
wbreza Mar 9, 2026
0ce0d23
Persist intent text in spinner instead of resetting to 'Thinking...'
wbreza Mar 9, 2026
f435865
Add blank line after spinner
wbreza Mar 9, 2026
06701ff
Show relative paths for skill directories in tool summaries
wbreza Mar 9, 2026
32556a0
Capture intent from report_intent tool calls for spinner text
wbreza Mar 9, 2026
a5411c4
Show nested subagent tool calls with rich display
wbreza Mar 9, 2026
bcb2c10
UX polish: blank lines before skill/subagent, suppress internal tools
wbreza Mar 9, 2026
4d4f774
Prompt for reasoning effort and model on first agent run
wbreza Mar 9, 2026
f6cdb3a
Fix: only signal idle when final content exists
wbreza Mar 9, 2026
4051d5b
Load Azure plugin MCP servers into session config
wbreza Mar 9, 2026
33a159d
Suppress 'skill' tool from display, add blank line after Using skill
wbreza Mar 10, 2026
63c5a29
Fix agent exit: reset finalContent per turn, add completion logging
wbreza Mar 10, 2026
2a61919
Add scoped system message and empty directory handling
wbreza Mar 10, 2026
903d270
Consistent whitespace and improved config display
wbreza Mar 10, 2026
d651aea
Add blank lines before/after user prompts, fix extra blank in config …
wbreza Mar 10, 2026
ee5b9c8
Log MCP server details and skill dirs for debugging
wbreza Mar 10, 2026
be2cd72
Print MCP servers and skill dirs to console output for debugging
wbreza Mar 10, 2026
f3573f5
Print available tools to console from session events
wbreza Mar 10, 2026
defe26d
Fix MCP server config: use type 'local' and add tools wildcard
wbreza Mar 10, 2026
e41b3be
Add diagnostic prompt to list all tools including MCP server tools
wbreza Mar 10, 2026
3ef63ca
Dump first 30 session events with details for MCP debugging
wbreza Mar 10, 2026
056c55d
Remove diagnostic prompt, rely on event dump for tool debugging
wbreza Mar 10, 2026
d3ec038
Debugging: disable system message, add diagnostic tools list prompt, …
wbreza Mar 10, 2026
eeb67fa
Add post-init Q&A loop for follow-up questions
wbreza Mar 10, 2026
f2eafd6
Add session resume support for cancelled/crashed agent sessions
wbreza Mar 10, 2026
1e57885
Polish session resume UX: numbers, local time, truncated labels
wbreza Mar 10, 2026
ad92124
Fix session labels: collapse newlines, enforce 120 char max
wbreza Mar 10, 2026
b0f4a1f
Enable line numbers and filtering on all Select prompts
wbreza Mar 10, 2026
2170766
Dynamic model list from SDK with billing and reasoning metadata
wbreza Mar 10, 2026
b61313a
Show session usage metrics at end of init
wbreza Mar 10, 2026
ece2253
Remove post-init Q&A loop
wbreza Mar 10, 2026
d79bf61
Consolidate agent into self-contained CopilotAgent with factory
wbreza Mar 10, 2026
1cc2162
Fix spacing: add blank line after each prompt, remove leading blanks
wbreza Mar 11, 2026
b8f4861
Add unit tests for types.go and display.go pure functions
wbreza Mar 11, 2026
6667e4c
Fix billing display and CI checks
wbreza Mar 11, 2026
3e825e1
Address PR review feedback
wbreza Mar 11, 2026
c41bb92
Address second round PR review feedback
wbreza Mar 11, 2026
24e2513
Add AgentMode enum, remove redundant logging infrastructure
wbreza Mar 11, 2026
2e82eab
Fix: return originalError when user declines fix in error middleware
wbreza Mar 11, 2026
023521e
Document permission handler intent and relationship to PreToolUse
wbreza Mar 11, 2026
a4b0277
Remove docs/specs/copilot-agent-ux (deleted by reviewer)
wbreza Mar 11, 2026
3c2bd0a
Delete dead agent tools and unused consent wrapper
wbreza Mar 11, 2026
d779a65
Remove unused ExecutingTool and related global state from consent
wbreza Mar 11, 2026
a468896
Fix MCP functional tests for remaining tools
wbreza Mar 11, 2026
5e41265
Fix init.go: remove stray backtick, highlight azd up command
wbreza Mar 11, 2026
69c6778
Apply go fix for Go 1.26 compatibility
wbreza Mar 11, 2026
580a428
Remove unused intPtr, floatPtr, strPtr helpers (inlined by go fix)
wbreza Mar 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions cli/azd/cmd/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,12 +580,12 @@ func registerCommonDependencies(container *ioc.NestedContainer) {

// AI & LLM components
container.MustRegisterSingleton(llm.NewManager)
container.MustRegisterSingleton(llm.NewModelFactory)
container.MustRegisterScoped(agent.NewAgentFactory)
container.MustRegisterSingleton(llm.NewSessionConfigBuilder)
container.MustRegisterSingleton(func() *llm.CopilotClientManager {
return llm.NewCopilotClientManager(nil)
})
container.MustRegisterScoped(agent.NewCopilotAgentFactory)
container.MustRegisterScoped(consent.NewConsentManager)
container.MustRegisterNamedSingleton("ollama", llm.NewOllamaModelProvider)
container.MustRegisterNamedSingleton("azure", llm.NewAzureOpenAiModelProvider)
registerGitHubCopilotProvider(container)

// Agent security manager
container.MustRegisterSingleton(func() (*security.Manager, error) {
Expand Down
17 changes: 0 additions & 17 deletions cli/azd/cmd/github_copilot_registration.go

This file was deleted.

16 changes: 0 additions & 16 deletions cli/azd/cmd/github_copilot_registration_stub.go

This file was deleted.

226 changes: 64 additions & 162 deletions cli/azd/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/azure/azure-dev/cli/azd/internal"
"github.com/azure/azure-dev/cli/azd/internal/agent"
"github.com/azure/azure-dev/cli/azd/internal/agent/consent"
"github.com/azure/azure-dev/cli/azd/internal/agent/feedback"
"github.com/azure/azure-dev/cli/azd/internal/repository"
"github.com/azure/azure-dev/cli/azd/internal/tracing"
"github.com/azure/azure-dev/cli/azd/internal/tracing/fields"
Expand All @@ -40,7 +39,6 @@ import (
"github.com/azure/azure-dev/cli/azd/pkg/workflow"
"github.com/fatih/color"
"github.com/joho/godotenv"
"github.com/mark3labs/mcp-go/mcp"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
Expand Down Expand Up @@ -140,7 +138,7 @@ type initAction struct {
featuresManager *alpha.FeatureManager
extensionsManager *extensions.Manager
azd workflow.AzdCommandRunner
agentFactory *agent.AgentFactory
agentFactory *agent.CopilotAgentFactory
consentManager consent.ConsentManager
configManager config.UserConfigManager
}
Expand All @@ -157,7 +155,7 @@ func newInitAction(
featuresManager *alpha.FeatureManager,
extensionsManager *extensions.Manager,
azd workflow.AzdCommandRunner,
agentFactory *agent.AgentFactory,
agentFactory *agent.CopilotAgentFactory,
consentManager consent.ConsentManager,
configManager config.UserConfigManager,
) actions.Action {
Expand Down Expand Up @@ -283,8 +281,9 @@ func (i *initAction) Run(ctx context.Context) (*actions.ActionResult, error) {
output.WithLinkFormat("%s", "https://aka.ms/azd-third-party-code-notice"))

if i.featuresManager.IsEnabled(llm.FeatureLlm) {
followUp += fmt.Sprintf("\n%s Run azd up to deploy project to the cloud.`",
color.HiMagentaString("Next steps:"))
followUp += fmt.Sprintf("\n%s Run %s to deploy project to the cloud.",
color.HiMagentaString("Next steps:"),
output.WithHighLightFormat("azd up"))
}

switch initTypeSelect {
Expand Down Expand Up @@ -401,198 +400,101 @@ func (i *initAction) Run(ctx context.Context) (*actions.ActionResult, error) {
}

func (i *initAction) initAppWithAgent(ctx context.Context) error {
// Warn user that this is an alpha feature
// Show alpha warning
i.console.MessageUxItem(ctx, &ux.MessageTitle{
Title: fmt.Sprintf("Agentic mode init is in alpha mode. The agent will scan your repository and "+
"attempt to make an azd-ready template to init. You can always change permissions later "+
"by running `azd mcp consent`. Mistakes may occur in agent mode. "+
"To learn more, go to %s\n", output.WithLinkFormat("https://aka.ms/azd-feature-stages")),
"To learn more, go to %s", output.WithLinkFormat("https://aka.ms/azd-feature-stages")),
TitleNote: "CTRL C to cancel interaction \n? to pull up help text",
})

// Check read only tool consent
readOnlyRule, err := i.consentManager.CheckConsent(ctx,
consent.ConsentRequest{
ToolID: "*/*",
ServerName: "*",
Operation: consent.OperationTypeTool,
Annotations: mcp.ToolAnnotation{
ReadOnlyHint: new(true),
},
},
// Create agent
copilotAgent, err := i.agentFactory.Create(ctx,
agent.WithMode(agent.AgentModeInteractive),
agent.WithDebug(i.flags.global.EnableDebugLogging),
)
if err != nil {
return err
}
defer copilotAgent.Stop()

if !readOnlyRule.Allowed {
consentChecker := consent.NewConsentChecker(i.consentManager, "")
err = consentChecker.PromptAndGrantReadOnlyToolConsent(ctx)
if err != nil {
return err
}
i.console.Message(ctx, "")
}

azdAgent, err := i.agentFactory.Create(
ctx,
agent.WithDebug(i.flags.global.EnableDebugLogging),
)
// Initialize — prompts on first run, returns config on subsequent
initResult, err := copilotAgent.Initialize(ctx)
if err != nil {
return err
}

defer azdAgent.Stop()
// Show current config
modelDisplay := initResult.Model
if modelDisplay == "" {
modelDisplay = "default"
}
i.console.Message(ctx, output.WithGrayFormat(" Agent: model=%s, reasoning=%s",
modelDisplay, initResult.ReasoningEffort))
if !initResult.IsFirstRun {
i.console.Message(ctx, output.WithGrayFormat(
" To change, run %s or %s",
output.WithHighLightFormat("azd config set ai.agent.model <model>"),
output.WithHighLightFormat("azd config set ai.agent.reasoningEffort <level>")))
}
i.console.Message(ctx, "")

type initStep struct {
Name string
Description string
SummaryTitle string
// Session picker — resume previous or start fresh
selected, err := copilotAgent.SelectSession(ctx)
if err != nil {
return err
}

taskInput := `Your task: %s
// Build send options
opts := []agent.SendOption{}
if selected != nil {
opts = append(opts, agent.WithSessionID(selected.SessionID))
i.console.Message(ctx, output.WithSuccessFormat("Session resumed"))
i.console.Message(ctx, "")
}

Break this task down into smaller steps if needed.
If new information reveals more work to be done, pursue it.
Do not stop until all tasks are complete and fully resolved.
`
// Init prompt
prompt := `Prepare this application for deployment to Azure.

initSteps := []initStep{
{
Name: "Step 1: Running Discovery & Analysis",
Description: "Run a deep discovery and analysis on the current working directory.",
SummaryTitle: "Step 1 (discovery & analysis)",
},
{
Name: "Step 2: Generating Architecture Plan",
Description: "Create a high-level architecture plan for the application.",
SummaryTitle: "Step 2 (architecture plan)",
},
{
Name: "Step 3: Generating Dockerfile(s)",
Description: "Generate a Dockerfile for the application components as needed.",
SummaryTitle: "Step 3 (dockerfile generation)",
},
{
Name: "Step 4: Generating infrastructure",
Description: "Generate infrastructure as code (IaC) for the application.",
SummaryTitle: "Step 4 (infrastructure generation)",
},
{
Name: "Step 5: Generating azure.yaml file",
Description: "Generate an azure.yaml file for the application.",
SummaryTitle: "Step 5 (azure.yaml generation)",
},
{
Name: "Step 6: Validating project",
Description: "Validate the project structure and configuration.",
SummaryTitle: "Step 6 (project validation)",
},
}
First, check if the current directory contains application code. If the directory is empty
or has no application code, ask the user what type of Azure application they would like to
build (e.g., web app, API, function app, static site, containerized service) before proceeding.

var stepSummaries []string
Then invoke the following skills in order:

for idx, step := range initSteps {
// Collect and apply feedback for next steps
if idx > 0 {
if err := i.collectAndApplyFeedback(
ctx,
azdAgent,
"Any changes before moving to the next step?",
); err != nil {
return err
}
} else if idx == len(initSteps)-1 {
if err := i.collectAndApplyFeedback(
ctx,
azdAgent,
"Any changes before moving to the next completing interaction?",
); err != nil {
return err
}
}
1. Invoke the azure-prepare skill using the "azd" recipe to analyze the project,
generate infrastructure (Bicep or Terraform), Dockerfiles, and azure.yaml configuration.

// Run Step
i.console.Message(ctx, color.MagentaString(step.Name))
fullTaskInput := fmt.Sprintf(taskInput, strings.Join([]string{
step.Description,
"Provide a brief summary in around 6 bullet points format about what was scanned" +
" or analyzed and key actions performed:\n" +
"Keep it concise and focus on high-level accomplishments, not implementation details.",
}, "\n"))
2. Invoke the azure-validate skill using the "azd" recipe to run pre-deployment
validation checks and verify everything is ready for deployment.

agentOutput, err := azdAgent.SendMessageWithRetry(ctx, fullTaskInput)
if err != nil {
if agentOutput != "" {
i.console.Message(ctx, output.WithMarkdown(agentOutput))
}
Always select the "azd" recipe when prompted for recipe selection.

return err
}
Ask the user for input when you need clarification about architecture choices,
service selection, or configuration options.

stepSummaries = append(stepSummaries, agentOutput)
When complete, provide a brief summary of what was accomplished.`

i.console.Message(ctx, "")
i.console.Message(ctx, color.HiMagentaString(fmt.Sprintf("◆ %s Summary:", step.SummaryTitle)))
i.console.Message(ctx, output.WithMarkdown(agentOutput))
i.console.Message(ctx, "")
}
i.console.Message(ctx, color.MagentaString("Preparing application for Azure deployment..."))

// Post-completion summary
if err := i.postCompletionSummary(ctx, azdAgent, stepSummaries); err != nil {
result, err := copilotAgent.SendMessageWithRetry(ctx, prompt, opts...)
if err != nil {
return err
}

return nil
}

// collectAndApplyFeedback prompts for user feedback and applies it using the agent in a loop
func (i *initAction) collectAndApplyFeedback(
ctx context.Context,
azdAgent agent.Agent,
promptMessage string,
) error {
AIDisclaimer := output.WithGrayFormat("The following content is AI-generated. AI responses may be incorrect.")
collector := feedback.NewFeedbackCollector(i.console, feedback.FeedbackCollectorOptions{
EnableLoop: true,
FeedbackPrompt: promptMessage,
FeedbackHint: "Enter to skip",
RequireFeedback: false,
AIDisclaimer: AIDisclaimer,
})

return collector.CollectFeedbackAndApply(ctx, azdAgent, AIDisclaimer)
}

// postCompletionSummary provides a final summary after all steps complete
func (i *initAction) postCompletionSummary(
ctx context.Context,
azdAgent agent.Agent,
stepSummaries []string,
) error {
i.console.Message(ctx, "")
i.console.Message(ctx, "🎉 All initialization steps completed!")
// Show summary
i.console.Message(ctx, "")
i.console.Message(ctx, color.HiMagentaString("◆ Azure Init Summary:"))
i.console.Message(ctx, output.WithMarkdown(result.Content))

// Combine all step summaries into a single prompt
combinedSummaries := strings.Join(stepSummaries, "\n\n---\n\n")
summaryPrompt := fmt.Sprintf(`Based on the following summaries of the azd init process, please provide
a comprehensive overall summary of what was accomplished in bullet point format:\n%s`, combinedSummaries)

agentOutput, err := azdAgent.SendMessageWithRetry(ctx, summaryPrompt)
if err != nil {
if agentOutput != "" {
i.console.Message(ctx, output.WithMarkdown(agentOutput))
}

return err
// Show usage
if usage := result.Usage.Format(); usage != "" {
i.console.Message(ctx, "")
i.console.Message(ctx, usage)
}

i.console.Message(ctx, "")
i.console.Message(ctx, color.HiMagentaString("◆ Agentic init Summary:"))
i.console.Message(ctx, output.WithMarkdown(agentOutput))
i.console.Message(ctx, "")

return nil
}

Expand Down Expand Up @@ -651,7 +553,7 @@ func promptInitType(
console.Message(ctx, "\nThe azd agent feature has been enabled to support this new experience."+
" To turn off in the future run `azd config unset alpha.llm`.")

err = azdConfig.Set("ai.agent.model.type", "github-copilot")
err = azdConfig.Set("ai.agent.model.type", "copilot")
if err != nil {
return initUnknown, fmt.Errorf("failed to set ai.agent.model.type config: %w", err)
}
Expand Down
8 changes: 0 additions & 8 deletions cli/azd/cmd/mcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,14 +227,6 @@ func (a *mcpStartAction) Run(ctx context.Context) (*actions.ActionResult, error)
mcpServer.EnableSampling()

azdTools := []server.ServerTool{
tools.NewAzdPlanInitTool(),
tools.NewAzdDiscoveryAnalysisTool(),
tools.NewAzdArchitecturePlanningTool(),
tools.NewAzdAzureYamlGenerationTool(),
tools.NewAzdDockerGenerationTool(),
tools.NewAzdInfrastructureGenerationTool(),
tools.NewAzdIacGenerationRulesTool(),
tools.NewAzdProjectValidationTool(),
tools.NewAzdYamlSchemaTool(),
tools.NewAzdErrorTroubleShootingTool(),
tools.NewAzdProvisionCommonErrorTool(),
Expand Down
Loading
Loading