Skip to content

feat(ai.agents): local run + M365 Agents Playground for activity-protocol agents - #8983

Merged
Travis Angevine (trangevi) merged 2 commits into
Azure:mainfrom
v1212:feat/activity-protocol-local-run
Jul 9, 2026
Merged

feat(ai.agents): local run + M365 Agents Playground for activity-protocol agents#8983
Travis Angevine (trangevi) merged 2 commits into
Azure:mainfrom
v1212:feat/activity-protocol-local-run

Conversation

@v1212

@v1212 JianW (v1212) commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Note

Independent of #8939. Earlier revisions were stacked on #8939
(feat/activity-protocol-simple); this PR now detects activity-protocol
agents with a self-contained gate and targets main directly, so it can be
reviewed and merged in parallel with #8939. Closes #8959.

Summary

Extends azd ai agent run so an activity-protocol (Teams) agent can be tested
in a pure-local inner loop — no Foundry deploy, no Azure Bot, no Teams sideload.
Targets the simple use case (Phase 1). The agent startup path is byte-for-byte
the same as today; only the auto-launched local client changes.

  • Non-activity agents (responses/invocations) are completely unaffected
    everything sits behind a self-contained activity gate
    (isActivityProtocolDefinition) that only reads the agent definition, with no
    dependency on the deploy-side provisioning work.
  • Activity agents: run injects AGENT_DIGITAL_WORKER=1 for the local
    process (anonymous auth so the emulator channel round-trips off-box; the default
    "simple" model needs a managed identity that doesn't exist locally and would
    500), then auto-launches the Microsoft 365 Agents Playground instead of the
    Agent Inspector (Inspector only speaks responses/invocations).

Why the two flows differ

Local client Speaks Launch
responses/invocations Agent Inspector responses/invocations ai inspector launch --port
activity (new) M365 Agents Playground activity (emulator) agentsplayground -e http://127.0.0.1:<port>/api/messages -c emulator

Gotchas encoded

  • 127.0.0.1, not localhost — the agent binds IPv4; localhost resolves to
    IPv6 ::1 first and fails with ECONNREFUSED ::1:<port>.
  • Digital-worker/anonymous mode required locally or every message 500s. The
    toggle is set for the local process only; never during azd deploy, so
    production keeps the default simple model.
  • Missing agentsplayground CLI only warns (with a winget install agentsplayground hint) and keeps the agent running — mirrors how run warns
    when the Agent Inspector extension is missing.

What changed (file level)

File Change
internal/cmd/run_activity.go (new) Playground helpers: resolveActivityRunProfile, playgroundCommandArgs, launchPlayground, handlePlaygroundAutoLaunch, startPlaygroundAfterAgentReady, missingPlaygroundWarning; AGENT_DIGITAL_WORKER constant.
internal/cmd/run.go Detect activity from the agent definition (self-contained gate); inject the digital-worker toggle (local only); branch the client auto-launch (Playground vs Inspector). Deprecate --no-inspector in favor of --no-client; add --channel.
internal/cmd/run_test.go New tests: exact playground argv, 127.0.0.1 URL, gate decision, flag parsing, missing-CLI warning, suppression.
cspell.yaml agentsplayground, winget, ECONNREFUSED.

The quickstart-echo sample (in foundry-samples, not this repo) gains an
AGENT_DIGITAL_WORKER toggle in main.py (default unset = simple) plus a
"Local testing" README section.

Flags

  • --no-client — protocol-neutral flag to suppress the auto-launched client (canonical).
  • --no-inspectordeprecated alias for --no-client; still works (back-compat) but hidden from help.
  • --channel — overrides the Playground channel (default emulator; activity only).

How to try it (manual)

Prerequisites (one time):

winget install agentsplayground   # the only local client that speaks Activity

Run the activity echo agent locally from a prepared quickstart-echo project
(activity agent.yaml + an azure.ai.agent service in azure.yaml):

azd ai agent run

Expected:

  1. Prints Activity agent detected: starting in digital-worker (anonymous) mode ....
  2. Agent binds http://0.0.0.0:<port> (default 8088).
  3. Once the port is up, prints and launches
    agentsplayground -e http://127.0.0.1:<port>/api/messages -c emulator;
    a browser tab opens. Type hi -> the agent echoes Echo: hi.

Variations:

  • azd ai agent run --no-client (or --no-inspector): agent starts, no
    Playground is launched.
  • azd ai agent run --channel <name>: overrides the Playground channel.
  • If agentsplayground isn't installed: a warning with the winget install
    hint is printed and the agent keeps running.

No-browser smoke check (inbound routing; the real Playground provides a working
emulator serviceUrl for the outbound reply):

agentsplayground -e "http://127.0.0.1:8088/api/messages" -c "emulator"

Testing

Automated

go build ./..., go vet ./..., and go test ./internal/cmd/... ./internal/project/...
all pass; gofmt clean; cspell 0 issues. New unit tests assert the exact
agentsplayground -e http://127.0.0.1:<port>/api/messages -c emulator argv (like
TestLaunchInspectorUsesWorkflowCommand does for the inspector), the activity gate
decision, flag parsing, the missing-CLI warning, and suppression.

Live (built via azd x pack/publish/install, run through the branch extension)

Scenario Result
activity agent, azd ai agent run Activity agent detected ... printed; agent bound 0.0.0.0:8088; Playground auto-launched with the exact agentsplayground -e http://127.0.0.1:8088/api/messages -c emulator argv. In the browser Playground the full round-trip works: the conversationUpdate greeting Welcome Buddy! appears, and typing hello / hi returns Echo: hello / Echo: hi. Inbound POSTs return HTTP 202 (replies delivered) — confirming the anonymous digital-worker mode is active (the default simple model would 500 locally).
--no-client agent starts, no Playground launched (no process, no launch line).
non-activity (responses) agent no activity message, no Playground; Agent Inspector auto-launched as before — existing behavior unchanged (regression check).

Non-goals

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 extends the azure.ai.agents azd extension to support activity-protocol (Teams) agents across both the cloud deploy lifecycle (Azure Bot + Teams channel provisioning/teardown) and a local inner-loop (azd ai agent run) that auto-launches the Microsoft 365 Agents Playground, while keeping non-activity agents on the existing Agent Inspector flow.

Changes:

  • Add an activity-protocol “gate” (ResolveActivityProfile) and reuse it across init/deploy/run flows.
  • Provision/teardown Azure Bot + Teams channel during postdeploy/postdown for activity agents (with a generated Teams setup guide).
  • Update azd ai agent run to inject the local-only digital-worker toggle for activity agents and launch the Playground client, plus new flags/tests.

Reviewed changes

Copilot reviewed 14 out of 15 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
cli/azd/extensions/azure.ai.agents/internal/project/activity_profile.go Adds activity protocol detection + profile resolution + endpoint helper.
cli/azd/extensions/azure.ai.agents/internal/project/activity_profile_test.go Tests activity protocol detection, resolution, and init round-trip.
cli/azd/extensions/azure.ai.agents/internal/pkg/botservice/botservice.go New BotService client for ensuring/deleting Azure Bot + Teams channel.
cli/azd/extensions/azure.ai.agents/internal/pkg/botservice/botservice_test.go Unit tests for bot provisioning, naming, and delete behavior.
cli/azd/extensions/azure.ai.agents/internal/cmd/run.go Adds activity gating, local-only env injection, and client auto-launch branching + flags.
cli/azd/extensions/azure.ai.agents/internal/cmd/run_test.go Tests Playground argv/URL behavior, gating, flags, and missing-CLI warning.
cli/azd/extensions/azure.ai.agents/internal/cmd/run_activity.go New Playground auto-launch helpers for activity agents.
cli/azd/extensions/azure.ai.agents/internal/cmd/listen.go Wires activity bot provisioning into postdeploy and teardown into postdown.
cli/azd/extensions/azure.ai.agents/internal/cmd/listen_activity.go Implements ensure/teardown + Teams setup guide generation and env helpers.
cli/azd/extensions/azure.ai.agents/internal/cmd/listen_activity_test.go Tests Teams setup guide content and file emission.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code.go Adds activity_protocol to known protocols and prevents mixing with others.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code_test.go Tests activity_protocol flag parsing/exclusivity and known protocol names.
cli/azd/extensions/azure.ai.agents/go.mod Adds Azure BotService ARM SDK dependency.
cli/azd/extensions/azure.ai.agents/go.sum Adds checksums for the new BotService SDK dependency.
cli/azd/extensions/azure.ai.agents/cspell.yaml Adds activity-protocol / Playground related dictionary words.

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/listen_activity.go
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/run.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/run_activity.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/run.go

@jongio Jon Gallant (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.

Verified: activity gate detection is self-contained (reads definition only, no deploy dependency), playground launch lifecycle correctly waits for port + reaps child process, IPv4 loopback (127.0.0.1) is consistent between displayHost, playgroundMessagesURL, and waitForLocalPort, flag deprecation uses MarkDeprecated properly, and suppressClient OR-logic covers both flags. No issues found.

Extend `azd ai agent run` to support local inner-loop testing of
activity-protocol (Teams) agents via the Microsoft 365 Agents Playground,
mirroring how the command already auto-launches Agent Inspector for
responses/invocations agents.

- Detect activity-protocol agents self-contained from the agent definition
  (container protocols or agent_endpoint 'activity'), with no dependency on
  the deploy-side activity provisioning work, so this can ship independently.
- For activity agents, inject a local-only AGENT_DIGITAL_WORKER=1 toggle so
  the Playground emulator channel round-trips off-box (never set on deploy).
- Auto-launch the Playground once the agent binds its port; reap the child
  via cmd.Wait; use 127.0.0.1 (IPv4) consistently to avoid ::1 failures.
- Add --channel (Playground channel) and --no-client (protocol-neutral
  client suppress); deprecate --no-inspector in favor of --no-client while
  keeping it working for back-compat.
- Tests for detection, flags (incl. deprecation), Playground argv/URL, and
  suppressed/missing-CLI paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@v1212
JianW (v1212) force-pushed the feat/activity-protocol-local-run branch from 2e6d48d to d8b9bb0 Compare July 9, 2026 05:08
@v1212

Copy link
Copy Markdown
Contributor Author

Pushed a small robustness fix (single commit amended, still 4 files) after checking interaction with the parallel PR #8939.

Why: #8939 renames the canonical container-level protocol wire value agent_api.AgentProtocolActivityProtocol from "activity_protocol" to "activity" (adding a separate legacy constant). This PR's isActivityProtocolDefinition switch matched string(agent_api.AgentProtocolActivityProtocol) and the literal "activity". Once #8939 lands, both arms collapse to "activity", which is a duplicate case compile error — so whichever PR merges second would break the build.

Fix: match the two container-level names as explicit literals (activityProtocolCanonicalName = "activity", activityProtocolLegacyName = "activity_protocol") instead of binding to the constant whose value shifts. Detection is now stable regardless of merge order and still recognizes both names.

Verified: built this branch's code overlaid on #8939's head (main + #8939) — compiles clean and the activity-detection tests pass. Only residual cross-PR overlap is cspell.yaml (both add words); whoever merges second resolves that trivial text conflict. Closes #8959.

@trangevi
Travis Angevine (trangevi) enabled auto-merge (squash) July 9, 2026 17:02
@trangevi
Travis Angevine (trangevi) merged commit 0557e21 into Azure:main Jul 9, 2026
26 checks passed
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.

[Activity] Local testing: extend 'azd ai agent run' to launch activity agent + Teams playground on localhost

6 participants