Skip to content

Support invocations_ws in agent init#9009

Open
v1212 wants to merge 35 commits into
Azure:mainfrom
v1212:users/wujia/invocations-ws-init
Open

Support invocations_ws in agent init#9009
v1212 wants to merge 35 commits into
Azure:mainfrom
v1212:users/wujia/invocations-ws-init

Conversation

@v1212

@v1212 v1212 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds invocations_ws as a selectable protocol for azd ai agent init while keeping the default protocol as responses.
  • Honors --protocol invocations_ws for bring-your-own-image --image init.
  • Documents invocations_ws in agent help/schema descriptions.
  • Adds focused regression coverage for protocol selection, image init protocol propagation, and code deploy serialization via protocol_versions.

Sample used for validation

Official sample:
https://github.com/microsoft-foundry/foundry-samples/tree/main/samples/python/hosted-agents/bring-your-own/invocations_ws/hello-world

Validation

  • go test ./internal/cmd/... from cli/azd/extensions/azure.ai.agents
  • go test ./... from cli/azd/extensions/azure.ai.agents
  • go build ./... from cli/azd/extensions/azure.ai.agents
  • cspell lint "extensions/**/*.go" "extensions/**/*.md" --config ./.vscode/cspell.yaml --no-progress from cli/azd

Fixes #9173

@github-actions github-actions Bot added the ext-agents azure.ai.agents extension label Jul 7, 2026
@v1212
v1212 marked this pull request as ready for review July 16, 2026 04:38
Copilot AI review requested due to automatic review settings July 16, 2026 04:38
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
21 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

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

Adds invocations_ws support and improves non-interactive agent initialization.

Changes:

  • Adds protocol support for code and image deployments.
  • Adds Azure context flags and region fallback updates.
  • Enhances unified sample adoption and model configuration.

Reviewed changes

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

Show a summary per file
File Description
schemas/azure.ai.agent.json Documents invocations_ws.
internal/pkg/agents/agent_yaml/map_test.go Tests API protocol serialization.
internal/cmd/init.go Adds flags and image protocol synthesis.
internal/cmd/init_test.go Tests image protocol handling.
internal/cmd/init_locations.go Merges live and embedded regions.
internal/cmd/init_locations_test.go Tests region merging.
internal/cmd/init_from_code.go Adds protocol and Azure context support.
internal/cmd/init_from_code_test.go Tests protocol selection.
internal/cmd/init_foundry_resources_helpers.go Applies Azure context flags and adjusts model resolution.
internal/cmd/init_adopt.go Applies agent and model overrides during adoption.
internal/cmd/hosted-agent-regions.json Adds westus2.
cspell.yaml Adds VOICELIVE spelling.

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_locations.go Outdated
Copilot AI review requested due to automatic review settings July 16, 2026 05:41

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

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_locations.go Outdated
Copilot AI review requested due to automatic review settings July 16, 2026 07: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

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_adopt.go Outdated

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 12 out of 12 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

cli/azd/extensions/azure.ai.agents/internal/cmd/nextstep/resolver.go:694

  • azd-code-reviewer: nil is how appendInvokeLocalSecondary represents every multi-service project, so returning true here still emits an unqualified local invoke hint when all services are invocations_ws/activity, and in mixed projects the runtime prompt can select a non-invocable service and fail. Inspect the service list in the multi-service path: suppress the hint when none are locally invocable, and otherwise ensure the suggestion targets only an invocable service (or avoid the ambiguous unqualified hint). Add all-non-invocable and mixed-protocol init tests.
func serviceSupportsAzdInvoke(svc *ServiceState) bool {
	return svc == nil || (svc.Protocol != ProtocolInvocationsWS &&
		svc.Protocol != ProtocolActivity &&
		svc.Protocol != ProtocolActivityLegacy)

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/nextstep/state.go
Copilot AI review requested due to automatic review settings July 20, 2026 06:57

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

Comments suppressed due to low confidence (1)

cli/azd/extensions/azure.ai.agents/internal/cmd/nextstep/state.go:477

  • azd-code-reviewer: This only reads the deprecated config: bag, but newly initialized services—including the linked sample—store kind and protocols in AdditionalProperties. AgentDefinitionFromService explicitly prefers that unified inline shape (internal/project/agent_definition.go:182-201), so these invocations_ws services resolve to an empty protocol and the resolver still emits unsupported azd ai agent invoke hints. Prefer AdditionalProperties when it has a non-empty kind, then fall back to Config; the new “inline” tests should populate AdditionalProperties so they exercise the real shape.
func loadServiceProtocolFromConfig(svc *azdext.ServiceConfig) string {
	if svc == nil || svc.Config == nil {
		return ""
	}
	data, err := yaml.Marshal(svc.Config.AsMap())

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Re-reviewed the four commits since my last pass, and my earlier notes are resolved. The image manifest test now defers cleanup() so it reads the file after the assertions, which was what turned BuildAndTest red. Next-step resolution treats both activity and the legacy activity_protocol spelling as non-invocable across the init, run, and deploy resolvers, so no unusable azd ai agent invoke hints are emitted. Protocol detection now reads the inline azure.yaml service config before falling back to the on-disk agent.yaml, which covers the image flow that stores the definition inline. Local build and the internal/cmd/... test suite pass, and CI is green.

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Re-reviewed the changes since my last approval (the inline-config protocol loading, activity handling, and invoke-hint suppression).

loadServiceProtocol now checks the inline service config before falling back to agent.yaml on disk, and loadServiceProtocolFromBytes keeps the precedence order-independent: responses > invocations > activity > invocations_ws. serviceSupportsAzdInvoke consistently suppresses the local/deploy invoke hints for invocations_ws, activity, and activity_protocol across ResolveAfterRun, ResolveAfterDeploy, and appendInvokeLocalSecondary, with the mixed multi-agent case keeping invocable services. The image-manifest path now accepts activity and the --protocol help is driven by knownProtocolNames(), so the earlier questions about activity support and a static help list are handled.

Build and the nextstep, cmd, and agent_yaml test packages all pass locally. Looks good to me.

Copilot AI review requested due to automatic review settings July 20, 2026 07:32

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 12 out of 12 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

cli/azd/extensions/azure.ai.agents/internal/cmd/nextstep/state.go:466

  • azd-code-reviewer: When an inline/config definition exists but declares no recognized protocol, this falls through to the legacy agent.yaml. Runtime resolution does not do that: AgentDefinitionFromService uses the inline definition directly (internal/project/agent_definition.go:182-201), and an empty protocol list defaults to responses (internal/pkg/agents/agent_yaml/map.go:393-397). A stale file declaring invocations_ws would therefore suppress valid invoke hints for an agent that actually deploys as responses. Only consult disk when no service definition exists.
	if protocol := loadServiceProtocolFromConfig(svc); protocol != "" {
		return protocol

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/nextstep/state.go
Copilot AI review requested due to automatic review settings July 20, 2026 07:50

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

Comments suppressed due to low confidence (2)

cli/azd/extensions/azure.ai.agents/internal/cmd/nextstep/state.go:545

  • azd-code-reviewer: The new protocol selection omits the supported a2a protocol. For a valid mixed definition such as invocations_ws plus a2a, this scan selects invocations_ws, and ResolveAfterDeploy suppresses the invoke hint even though a2a is remotely invocable (agent_api.AgentProtocol.IsInvocable). Track local and remote invocability separately so deploy can select a2a while local hints remain suppressed, and add this mixed-protocol case.
	for _, p := range hosted.Protocols {
		switch strings.TrimSpace(p.Protocol) {
		case ProtocolResponses:
			return ProtocolResponses, multiProtocol
		case ProtocolInvocationsWS:

cli/azd/extensions/azure.ai.agents/internal/cmd/nextstep/state.go:474

  • azd-code-reviewer: Falling back based on protocol != "" breaks the inline-definition precedence. If an authoritative inline service has an empty, malformed, or currently unrecognized protocol list, runtime resolution still uses that inline definition, but this code reads a stale agent.yaml and may emit commands for a different protocol. Return whether an inline/config definition was found separately from whether a recognized protocol was selected, and only consult disk when no inline definition exists.
func loadServiceProtocolInfo(projectPath string, svc *azdext.ServiceConfig) (string, bool) {
	if protocol, multiProtocol := loadServiceProtocolFromConfig(svc); protocol != "" {
		return protocol, multiProtocol
	}

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/nextstep/state.go

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Left one inline note on the multi-protocol invoke-hint path. It is a narrow edge case and partly pre-existing, so non-blocking, but worth a look before merge. The protocol-selection precedence and the activity/activity_protocol handling in this push line up with the earlier feedback.

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/nextstep/state.go
Copilot AI review requested due to automatic review settings July 20, 2026 08:04

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Re-reviewed the incremental changes since my last look. The mixed-protocol handling I flagged is sorted: precedence stays responses > invocations > activity > invocations_ws regardless of the order the manifest declares them, activity and the legacy activity_protocol both suppress invoke hints, and invokeProtocolFlag now emits an explicit --protocol on all three invoke paths (ResolveAfterRun, ResolveAfterDeploy, appendInvokeLocalSecondary) for multi-protocol services.

The build break from the missing ServiceState.MultiProtocol field is fixed in e610152. go build ./... and go test ./internal/cmd/... both pass locally for the extension.

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

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/nextstep/state.go
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/nextstep/state_test.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/nextstep/state_test.go Outdated

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Re-reviewed the incremental changes since my last look. The mixed-protocol handling I flagged is sorted: precedence stays responses > invocations > activity > invocations_ws regardless of the order the manifest declares them, activity and the legacy activity_protocol both suppress invoke hints, and invokeProtocolFlag now emits an explicit --protocol on all three invoke paths (ResolveAfterRun, ResolveAfterDeploy, appendInvokeLocalSecondary) for multi-protocol services.

The build break from the missing ServiceState.MultiProtocol field is fixed in e610152. go build ./... and go test ./internal/cmd/... both pass locally for the extension.

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Re-reviewed the incremental changes since my last look. The mixed-protocol handling I flagged is sorted: precedence stays responses > invocations > activity > invocations_ws regardless of the order the manifest declares them, activity and the legacy activity_protocol both suppress invoke hints, and invokeProtocolFlag now emits an explicit --protocol on all three invoke paths (ResolveAfterRun, ResolveAfterDeploy, appendInvokeLocalSecondary) for multi-protocol services.

The build break from the missing ServiceState.MultiProtocol field is fixed in e610152. go build ./... and go test ./internal/cmd/... both pass locally for the extension.

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Re-reviewed the next-step changes layered on since my last pass.

The multi-protocol path now qualifies the emitted command with --protocol when a service declares more than one protocol, so a responses + invocations_ws service no longer produces an unqualified azd ai agent invoke that protocolFromContainerAgent would reject. Legacy activity_protocol is handled alongside the canonical activity value in both classification and invoke suppression, and protocol resolution now reads inline azure.yaml config before falling back to the service manifest. The test-cleanup ordering bug is fixed and BuildAndTest is green.

One non-blocking note: a hand-authored manifest declaring invocations_ws + a2a classifies as websocket-only and drops the post-deploy a2a invoke hint, since a2a isn't in the classifier switch. That isn't reachable through init today (a2a isn't an offered protocol), so it's fine to handle separately if it ever becomes one.

Replace context.Background() with t.Context() in the two new
inline AdditionalProperties assemble-state tests, per the Go 1.26
test-context convention.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 480247f9-174e-40ba-ab27-9a688d0675bf

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

Comments suppressed due to low confidence (2)

cli/azd/extensions/azure.ai.agents/internal/cmd/nextstep/resolver.go:341

  • azd-code-reviewer: This early return leaves azd ai agent run with a dangling prompt for invocations_ws: run.go:1094 prints “Agent ready. In another terminal, try:” before calling this resolver, while printNextIfTerminal emits nothing for an empty list. Resolve the suggestions before printing that header (or return a protocol-appropriate next step) so WebSocket runs do not end with an empty instruction.
	if !serviceSupportsAzdInvoke(svc) {
		return nil

cli/azd/extensions/azure.ai.agents/internal/cmd/nextstep/resolver.go:694

  • azd-code-reviewer: In the multi-service init path, svc is deliberately left nil, so treating nil as supported still emits azd ai agent invoke --local when every service is invocations_ws or Activity. Selecting any service then fails because none is locally invocable. Handle the multi-service case explicitly and suppress the hint when no service supports local invocation; add an all-WebSocket regression case.
func serviceSupportsAzdInvoke(svc *ServiceState) bool {
	return svc == nil || (svc.Protocol != ProtocolInvocationsWS &&
		svc.Protocol != ProtocolActivity &&
		svc.Protocol != ProtocolActivityLegacy)

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The follow-up commits since my last pass resolve the non-invocable-protocol handling I flagged. loadServiceProtocolFromBytes now applies a stable, order-independent priority (responses > invocations > activity > invocations_ws), and serviceSupportsAzdInvoke suppresses the invoke hint for invocations_ws and both activity / activity_protocol spellings. Multi-protocol services emit an explicit --protocol flag via invokeProtocolFlag so the suggested invoke command is unambiguous, and inline azure.yaml definitions are picked up through loadServiceProtocolFromConfig in addition to agent.yaml. The --protocol help text is generated from knownProtocolNames() so it stays in sync with the known set.

Verified go build ./... and go test ./internal/cmd/... pass against the current HEAD.

}
out = append(out, Suggestion{
Command: fmt.Sprintf("azd ai agent invoke --local %s", invokeArg),
Command: fmt.Sprintf("azd ai agent invoke --local %s%s", invokeProtocolFlag(svc), invokeArg),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Formatting, does there need to be a space between the "%s" fields?

@jongio jongio left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The follow-up I flagged earlier is resolved: non-invocable protocols (activity, activity_protocol, invocations_ws) now suppress the azd ai agent invoke next-step hint, and serviceSupportsAzdInvoke gates every emission path (ResolveAfterRun, ResolveAfterDeploy, appendInvokeLocalSecondary). Protocol precedence responses > invocations > activity > invocations_ws is order-independent and locked by the reversed-order tests. Multi-protocol services emit an explicit --protocol flag with the resolved protocol, and inline service config now feeds detection with an agent.yaml fallback. Coverage across suppression, multi-protocol flag emission, inline-config precedence, and legacy activity is solid.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ext-agents azure.ai.agents extension

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support invocations_ws hosted agent initialization

6 participants