Skip to content

feat(ai.agents): native Azure Bot + Teams channel for activity-protocol agents#8939

Open
v1212 wants to merge 13 commits into
Azure:mainfrom
v1212:feat/activity-protocol-simple
Open

feat(ai.agents): native Azure Bot + Teams channel for activity-protocol agents#8939
v1212 wants to merge 13 commits into
Azure:mainfrom
v1212:feat/activity-protocol-simple

Conversation

@v1212

@v1212 v1212 commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Closes #8955

Summary

Adds native azd support for provisioning the Azure Bot and Microsoft Teams channel that front an activity-protocol (Teams) hosted agent. This replaces the previous setup-instance-bot.ps1 / post-deploy.ps1 postdeploy scripts with first-class behavior wired into the azure.ai.agents extension's postdeploy / postdown lifecycle handlers.

The end-to-end user journey is now fully native:

azd ai agent init      # azure.yaml keeps the activity declarations
azd provision          # Foundry project + ACR
azd deploy             # agent version active  ->  Azure Bot created + Teams channel enabled
azd down               # agent + Azure Bot torn down

Non-activity agents are completely unaffected — every Teams/bot-specific code path sits behind a single gate on the agent's activity profile, so existing responses / invocations agents behave exactly as before.

What changed (file level)

File Change
internal/cmd/listen.go Wire the two new hooks: ensureActivityBot in postdeployHandler, teardownActivityBots in postdownHandler.
internal/cmd/listen_activity.go (new) ensureActivityBot (postdeploy bot provisioning), teardownActivityBots (best-effort postdown cleanup), printTeamsNextSteps, readEnvValue.
internal/project/activity_profile.go (new, + test) IsActivityProtocol / ResolveActivityProfile — the single gate that detects activity opt-in (via protocols: activity_protocol or agent_endpoint.protocols: activity).
internal/pkg/botservice/botservice.go (new, + test) EnsureBot (create/update Azure Bot), ensureTeamsChannel, DeleteBot, BotName, MessagingEndpoint. Narrow interfaces over armbotservice so tests use fakes (7 tests).
go.mod / go.sum Add resourcemanager/botservice/armbotservice v1.2.0.

Design

  • Scope boundary — azd owns the Azure resource plane only. It creates the Azure Bot, binds it to the agent instance identity, enables the Teams channel, and points the messaging endpoint at the agent. Teams app packaging and install stay on the M365/Graph plane and are out of scope; postdeploy prints a short next-steps guide for those manual steps.
  • Bot identity (Phase 1 "simple" use case). The bot msaAppId is the agent instance identity client id, which only exists after the agent version is created — so bot provisioning runs in postdeploy, after the version is active. msaAppType = SingleTenant, sku = F0, location = global, kind = azurebot.
  • Naming + teardown. The bot is named <agent-name>-bot-uai. BotService names are globally unique, so postdown deletes the bot to free the name for future redeploys (best-effort — failures are logged, never block azd down).
  • Messaging endpoint is pinned to …/agents/<agent-name>/endpoint/protocols/activityProtocol?api-version=2025-05-15-preview.
  • Idempotent. The bot is created via create-or-update, so re-running azd deploy neither duplicates nor errors.

Testing

Unitgo build ./..., go vet ./... clean; internal/project (activity round-trip) and internal/pkg/botservice (7 fake-backed tests) pass.

Live E2E — full journey validated in a real subscription (new resource group, greenfield Foundry, North Central US):

Stage Result
azd ai agent init Generated azure.yaml preserves the activity declarations (protocols: activity_protocol, agentEndpoint.protocols: [activity], authorizationSchemes: [BotServiceRbac]).
azd provision Foundry project + ACR created via the microsoft.foundry provider.
azd deploy Agent version active; Azure Bot <agent>-bot-uai created — msaAppType=SingleTenant, msaAppId = instance identity client id, sku=F0, location=global, kind=azurebot, Teams channel enabled, messaging endpoint = pinned activityProtocol URL, provisioningState=Succeeded. Verified directly against ARM.
re-azd deploy Idempotent — no duplicate bot, no error.
azd down Resource group deleted; bot removed and its global name freed.

Out of scope / follow-ups

Notes for reviewers

  • After an activity deploy, postdeploy writes a generic TEAMS_APP_SETUP.md next to the agent source. It is built only from runtime values (agent name, bot name, msaAppId) and links to the official Microsoft Learn docs for packaging and sideloading a Teams app, so it works for any activity agent (init-from-manifest or init-from-code) and is never written for non-activity deployments. A file is used rather than stdout because azd's progress UI does not surface postdeploy handler output.

Update: activity-protocol support in init-from-code

The init-from-local-code path now supports activity-protocol agents (previously only the init-from-manifest path did). Bringing your own activity code and running azd init (choosing activity_protocol, or --protocol activity_protocol) now produces an azure.yaml identical to the manifest path and fully satisfies azd deploy.

  • activity_protocol/v1 added to knownProtocols (opt-in; no-prompt default stays responses/2.0.0)
  • injects the activity agentEndpoint (protocols: [activity], authorizationSchemes: [BotServiceRbac]) when the selection is activity, so the postdeploy bot gate fires for code-initialized agents too
  • validateProtocolSelection rejects combining activity_protocol with other protocols (an activity agent exposes only the activity endpoint), enforced in flag + interactive paths
  • the azd init flow is otherwise unchanged for non-activity agents

Scope: simple use case (Phase 1). Digital worker is Phase 2.


Testing & validation

Automated

  • Full azure.ai.agents extension suite: go build ./..., go vet ./..., go test ./... — green. (The only failures locally are internal/synthesis TestARMTemplate_MatchesBicepBuild / TestBrownfieldARMTemplate_MatchesBicepBuild, which are stale-ARM-vs-local-bicep environmental failures — templates/ and internal/synthesis/ are byte-identical to main, so unrelated to this PR.)
  • New unit tests: botservice (EnsureBot create/idempotent, Teams channel, DeleteBot), activity_profile (IsActivityProtocol / ResolveActivityProfile / ActivityAgentEndpoint), init_from_code (activity_protocol flag path + exclusivity + KnownProtocolNames).

Local azd init (built via azd x build, run through branch azd)

Scenario Result
init from manifest (activity) azure.yaml carries agentEndpoint{protocols:[activity], authorizationSchemes:[BotServiceRbac]} + protocols:[activity_protocol/v1]
init from code (--protocol activity_protocol) activity declaration byte-identical to the manifest path
init from code (default, no --protocol) protocols:[responses/2.0.0], no agentEndpoint — non-activity flow unchanged (regression check)
init from code (activity_protocol + responses) rejected with a clear error; only the base project scaffold is written

Live end-to-end (init-from-code activity project; sub ActivityProtocol-Dev, North Central US)

azd provision (2m24s, Foundry project + ACR) → azd deploy (3m7s, agent active) → postdeploy auto-provisioned the Azure Bot echocode-bot-uai (SingleTenant, msaAppId = agent instance identity, F0/global, endpoint pinned to the activityProtocol endpoint, MsTeams + WebChat + DirectLine channels enabled, provisioningState: Succeeded) → azd down --purge (1m45s, resource group deleted and bot name freed). Bot state verified directly via ARM (Microsoft.BotService/botServices, api-version 2022-09-15). The equivalent manifest-path project was validated the same way in earlier testing.

Two live reference environments (Teams-verified)

To exercise both azd ai agent init entry points, the same quickstart-echo activity agent was deployed twice — identical in every respect except the init entry point — and both were sideloaded into Microsoft Teams and confirmed to echo replies. Both deploys use ACR remote build (docker.remoteBuild: true), not ZIP code-deploy. Subscription: ActivityProtocol-Dev, region northcentralus. The flow was fully non-interactive with no manual patches (azd ai agent init -> azd provision -> azd deploy).

Env A — init from manifest Env B — init from code
Init command azd ai agent init -m agent.manifest.yaml --deploy-mode container azd ai agent init --deploy-mode container (from source, no manifest)
Foundry agent echomani07031202 echocode07031202
Resource group rg-mani07031202-69e12725 rg-code07031202-f68e547e
Foundry project mani07031202 code07031202
Azure Bot echomani07031202-bot-<salt> echocode07031202-bot-<salt>
Deploy mode container / ACR remote build container / ACR remote build
Teams reply verified verified

Each deploy auto-created the Foundry project + hosted agent, the Azure Bot with the Teams channel enabled, and the Azure AI User role for the instance identity. Both agents were sideloaded via a per-agent Teams app package and replied successfully in Teams, confirming the native manifest and code init paths are functionally equivalent end-to-end.


Follow-up: ship quickstart-echo as an azd ai agent init template

Add the quickstart-echo (simple activity/Teams) sample to the azd ai agent init template gallery so users can scaffold it directly. Not possible yet — the sample (foundry-samples: samples/python/hosted-agents/bring-your-own/activity/echo) is not merged yet. Once it lands, ship it as a native template with the changes below. Tracked in #8960.

To ship the sample as an azd template (native flow)

  • Remove azure.yaml, infra/, and the old scripts (post-deploy.ps1 / setup-instance-bot.ps1) — azd ai agent init scaffolds the native azure.yaml (foundry provider) and the extension handles the Bot + Teams channel in postdeploy.
  • Pin azure-ai-agentserver-core in requirements.txt to the same datestamp as ...-activity (avoids pulling an incompatible core -> container crash -> no Teams reply).
  • (Optional) Parameterize manifest.json name.short so multiple installs are distinguishable.

To just use the sample directly

  • Interactive azd ai agent init -> provision -> deploy (sub/location are picked in the init prompts — no manual env setup).
  • If core isn't pinned, pin it yourself to avoid the version risk.
  • Teams packaging + install is manual either way — azd deploy just emits a guide (TEAMS_APP_SETUP.md).

Bottom line: templating ~= drop azure.yaml/infra/old scripts + pin core; direct use is basically ready to run, with core-pinning the only real gotcha.

…ol agents

Provision the Azure Bot and Microsoft Teams channel for activity-protocol
(Teams) hosted agents natively during `azd deploy`, replacing the
setup-instance-bot.ps1 postdeploy script. The bot is bound to the agent
instance identity (msaAppId = instance identity client id), enabled on the
Teams channel, and its messaging endpoint is pointed at the agent's activity
protocol endpoint. Teardown deletes the bot so its globally unique name is
freed for redeploys. Non-activity agents are completely unaffected (single
gate on the activity profile).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added the ext-agents azure.ai.agents extension label Jul 2, 2026
Jian Wu and others added 2 commits July 2, 2026 16:31
Extend the init-from-local-code path so activity-protocol agents can be
initialized without a manifest, producing an azure.yaml identical to the
init-from-manifest path and fully satisfying azd deploy.

- add activity_protocol/v1 to knownProtocols (opt-in via --protocol or
  interactive multiselect; no-prompt default unchanged: responses/2.0.0)
- inject activity agentEndpoint (protocols: [activity], authorizationSchemes:
  [BotServiceRbac]) when IsActivityProtocol matches, so postdeploy bot gate
  fires for code-initialized activity agents just like manifest agents
- add validateProtocolSelection to reject combining activity_protocol with
  other protocols (activity agent exposes only the activity endpoint);
  enforced in both flag and interactive paths
- add ActivityAgentEndpoint helper + unit tests

The azd init flow is otherwise unchanged for non-activity agents.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- go fix: use new(x) for pointer-to-value and range-over-int (go 1.26)
  in botservice.go / botservice_test.go
- cspell: add activity/bot terms (botservice, armbotservice, Azurebot,
  idempotently, sideload, behaviour) to the extension dictionary

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@v1212 v1212 removed their assignment Jul 2, 2026
Jian Wu and others added 7 commits July 2, 2026 17:47
…eploy

Replace the sample-specific, console-only Teams next-steps hint with a generic TEAMS_APP_SETUP.md written next to the agent source during postdeploy. The guide is built only from runtime values (agent name, bot name, msaAppId) and links to official Microsoft Learn docs for packaging and sideloading a Teams app, so it works for any activity agent regardless of source (init-from-manifest or init-from-code) and is a no-op for non-activity deployments. Writing a file (not stdout) guarantees the user reliably receives the guidance, since azd's progress UI does not surface postdeploy handler stdout.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Address peer-review feedback on the activity-protocol bot flow:

- Salt the Azure Bot resource name with a hash of the deployment scope (subscription + resource group). BotService names are globally unique, so two environments deploying an agent with the same name previously collided; the name stays deterministic per scope so redeploys still update the same bot. Long agent names are truncated to the BotService handle limit. Create and teardown share BotScopeSalt so the names match.

- On postdeploy bot-config failure, make the error state that the agent version deployed successfully and only the Teams channel binding failed (commonly permissions/quota), and to re-run 'azd deploy'.

- Rename TestEnsureBotIsIdempotentAcrossRuns to TestEnsureBotIssuesUpsertOnEveryRun and clarify it asserts an upsert each run, not server-side idempotency; expand TestBotName to cover determinism, per-scope uniqueness, and length capping.

- Clarify the messaging-endpoint api-version constant is intentionally independent of the deploy api-version.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…d guide

Rewrite the generated TEAMS_APP_SETUP.md to include direct, minimal steps instead of only linking out: an easiest path (Teams Developer Portal, reuse the existing Azure bot by Bot ID, download a ready .zip) and a by-hand path (three-file list, a copy-paste minimal manifest.json noting that app id is a new GUID distinct from botId), plus numbered sideload steps (Apps -> Manage your apps -> Upload an app -> Upload a custom app). Each step keeps a link to the official Microsoft Learn doc for detail.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… fallback

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@v1212 v1212 marked this pull request as ready for review July 3, 2026 06:53
@v1212 v1212 requested a review from JeffreyCA as a code owner July 3, 2026 06:53
Copilot AI review requested due to automatic review settings July 3, 2026 06:53
…l-simple

# Conflicts:
#	cli/azd/extensions/azure.ai.agents/internal/cmd/listen.go

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 native azd support for provisioning the Azure Bot and Microsoft Teams channel that front an activity-protocol (Teams) hosted agent, replacing the previous setup-instance-bot.ps1 / post-deploy.ps1 postdeploy scripts. Bot provisioning is wired into the azure.ai.agents extension's postdeploy/postdown lifecycle handlers, and all Teams/bot-specific behavior sits behind a single activity-profile gate so non-activity agents are unaffected. It also extends the init-from-code path to support activity_protocol so it produces an azure.yaml identical to the manifest path.

Changes:

  • New botservice package (create/update Azure Bot, enable Teams channel, delete on teardown) with narrow SDK interfaces for fake-backed unit tests.
  • New activity-profile gate (IsActivityProtocol/ResolveActivityProfile) and postdeploy/postdown hooks (ensureActivityBot/teardownActivityBots) plus a generated TEAMS_APP_SETUP.md guide.
  • init-from-code now recognizes activity_protocol/v1, injects the activity agentEndpoint, and rejects combining it with other protocols.

Reviewed changes

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

Show a summary per file
File Description
internal/project/activity_profile.go (+test) Single gate detecting activity opt-in and the injected activity endpoint declaration.
internal/pkg/botservice/botservice.go (+test) Azure Bot create-or-update, Teams channel enable, delete, deterministic naming/messaging endpoint.
internal/cmd/listen.go Wires ensureActivityBot into postdeploy and teardownActivityBots into postdown.
internal/cmd/listen_activity.go (+test) Bot provisioning/teardown handlers, next-steps output, and Teams setup guide generation.
internal/cmd/init_from_code.go (+test) Adds activity_protocol, injects activity endpoint, enforces protocol exclusivity.
go.mod / go.sum Adds armbotservice v1.2.0 (verified to exist).
cspell.yaml Adds bot/Teams-related dictionary terms.

Findings are limited to a misleading bots[].id reference (should be bots[].botId) in the user-facing next-steps message and matching test comment, a errors.Aserrors.AsType convention nit, and a British-spelling ("behaviour") consistency nit. The core provisioning logic, gating, idempotency, and teardown look correct and are backed by unit tests and the described live E2E validation.

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/listen_activity.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/listen_activity_test.go Outdated
Comment thread cli/azd/extensions/azure.ai.agents/internal/project/activity_profile.go Outdated
…avior spelling

- Fix runtime/test message to reference Teams manifest bots[].botId (not bots[].id)
- Use Go 1.26 errors.AsType helper in botservice.isNotFound for consistency
- Use American spelling 'behavior' and drop the cspell behaviour allow-entry

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@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.

Activity-protocol bot provisioning is well-gated behind IsActivityProtocol, idempotent via PUT, and correctly scoped to Phase 1 (simple use case). Teardown is properly best-effort. Test coverage looks solid across botservice, activity_profile, and init_from_code paths.

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code.go Outdated
var knownProtocols = []protocolInfo{
{Name: "responses", Version: "2.0.0"},
{Name: "invocations", Version: "1.0.0"},
{Name: "activity_protocol", Version: "v1"},

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.

I don't suppose this is something we can push on elsewhere for the version to be consistent with the other protocols?

@v1212 v1212 Jul 7, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done — bumped to 1.0.0 for consistency with the other protocols (routing-equivalent to v1 on the platform). For context: neither value originated in this PR — v1 came from Vienna and the activity_protocol name from a pre-existing definition. Both are now defined in one central place and changed there.

@trangevi trangevi Jul 7, 2026

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.

We should be consistent with the service (for both the name and the version), otherwise there's potential for confusion as things change or are updated in the future. If there were going to be a change, it should be in the service, but without that this doesn't feel like something we should be customizing.

@therealjohn , any preference?

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.

If the service uses v1 we should use that - and if it does, where do we file a bug to track updating it to 1.0.0 like the other protocols?

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/init_from_code.go Outdated
// protocol. An activity-protocol (Teams) agent exposes only the activity
// endpoint, matching how such agents are declared in a manifest; mixing it with
// responses/invocations would produce an azure.yaml that does not match the
// manifest shape and is not a supported activity configuration.

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.

This surprises me, I don't understand this limitation. What "manifest" is being mentioned, and why does having other endpoints somehow break the activity protocol integration?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Sorry, that comment was misleading — dropped the "manifest" wording. It isn't a platform limit, it's azd scoping: an activity agent's ActivityAgentEndpoint replaces the whole AgentEndpoint, so it can't be composed with other protocols in one definition. Rewrote the comment and error accordingly.

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.

@therealjohn, tagging you here as well, as we talked about this briefly.

I still don't understand this. If this isn't a service side limitation, I don't understand why we're introducing it in AZD (apologies if I misunderstand your comment). But if there are two different properties, why not have two different properties, instead of limiting the functionality for the sake of reuse?

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.

@v1212 Please explain the limitation - I also do not understand this.

I'm reading it to mean that an agent with Activity protocol support can't support any other protocol and I don't think that is true. What needs to change in AZD to support that Activity is just another protocol used?

Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/listen_activity.go
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/listen_activity.go
return fmt.Errorf("botservice: creating/updating bot %q: %w", cfg.BotName, err)
}

return c.ensureTeamsChannel(ctx, cfg.ResourceGroup, cfg.BotName)

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.

This seems to contradict my comment above about the code giving instructions for setting up the Teams channel. If we set it up here, what are the instructions that we print for?

I'm still also of the opinion that we shouldn't be doing this by default, there should have to be some kind of opt in process

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Same clarification as above: ensureTeamsChannel enables the required resource-plane Teams channel connector (bound to the agent identity via MsaAppID); it does not create or publish the Teams app. Updated both docs to be consistent.

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.

@therealjohn , any issues with this?

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.

No issues with this - doing it by default is expected. @v1212, should we also enable the M365 channel?

What does the Foundry Portals experience for publishing expect to be set?

- Drop Teams-specific wording from protocol/endpoint-layer comments; the
  Activity protocol is not unique to Teams
- Use activity protocol version 1.0.0 for consistency with other protocols
  (routing-equivalent to v1)
- Emit canonical protocol name "activity" instead of redundant
  "activity_protocol"; keep the legacy value accepted for back-compat
- Rewrite validateProtocolSelection doc/error to state the real reason
  (ActivityAgentEndpoint replaces AgentEndpoint wholesale, cannot compose)
- Clarify ensureActivityBot / EnsureBot / ensureTeamsChannel docs: azd
  provisions the Azure Bot + resource-plane Teams channel (a required
  connector bound to the agent identity), not the M365 Teams app
- Move the embedded Teams setup guide into assets/teams_app_setup_guide.md
  rendered via go:embed + text/template; rendered output is byte-identical

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@v1212 v1212 force-pushed the feat/activity-protocol-simple branch from fc785fc to ea1abee Compare July 7, 2026 04:08

@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.

Incremental review of the review-feedback commit (ea1abee). Changes cleanly address trangevi's feedback:

  • Protocol renamed to canonical activity with backward-compat IsActivityProtocolName() accepting the legacy activity_protocol value
  • Version aligned to 1.0.0 semver style with routing semantics documented
  • Template extracted to embedded assets/teams_app_setup_guide.md (lintable, editor-friendly)
  • Comments clarified: Azure Bot "Teams channel" (resource toggle) vs Teams "app" (M365 packaging/sideload) distinction is now explicit throughout
  • validateProtocolSelection comment rewritten to explain the Phase-1 scoping choice vs platform limitation
  • Test coverage properly updated for both old and new protocol names

No new issues. Backward compat is solid. CI lint/cspell/golangci-lint all green.

v1212 pushed a commit to v1212/azure-dev that referenced this pull request Jul 7, 2026

@RickWinter RickWinter 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.

This adds native provisioning of the Azure Bot and Microsoft Teams channel for activity-protocol agents, wired into the extension's postdeploy/postdown handlers, and extends the init-from-code path to emit the same activity declaration the manifest path already produced. The shape is right. A single ResolveActivityProfile gate keeps every Teams/bot code path off non-activity deploys, the botservice client is fronted by narrow botsAPI/channelsAPI interfaces so the seven tests run against fakes, and EnsureBot is a create-or-update so redeploys stay idempotent. The protocol constant rename from "activity_protocol" to "activity" is low-risk here: the canonical constant has no non-test caller, and detection flows through IsActivityProtocolName, which still accepts the legacy value.

One thing worth resolving before merge: the postdeploy bot provisioning is placed after the optimization-reporting early returns (missing FOUNDRY_PROJECT_ENDPOINT, missing AZURE_TENANT_ID, or a credential failure each return nil with a "skipping optimization reporting" log). For an activity agent those guards silently skip the required Teams bot while deploy reports success, which also contradicts the hard-fail path immediately below where an EnsureBot error fails the deploy. The happy path is fine because provision sets both values, so this is a failure-mode and coupling concern, not a common-case bug.

Leaving Teams app packaging and sideload out of azd is the correct scope boundary, and TEAMS_APP_SETUP.md being built only from runtime values keeps it generic. Build, vet, and the botservice/project/cmd tests pass locally.

Disposition: address the postdeploy coupling before merge; the rest can proceed.


// For activity agents, provision the Azure Bot + Teams
// channel bound to the agent instance identity. No-op for other agents.
if err := ensureActivityBot(

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.

ensureActivityBot runs only after the three early return nil guards above (FOUNDRY_PROJECT_ENDPOINT missing at line 320, AZURE_TENANT_ID missing at line 336, credential creation failing at line 348), all of which were written for optimization reporting. For an activity agent those guards silently skip the Teams bot as well, and the only trace is a "skipping optimization reporting" log line that never mentions the bot, so a required connector can quietly go unprovisioned while azd deploy reports success. That is also inconsistent with the branch just below, where a real EnsureBot error hard-fails the deploy. Can we resolve the activity profile first and then fetch endpoint/tenant with bot-specific error handling, so the skip-versus-fail decision for the bot is made on its own terms rather than inheriting optimization's preconditions? In the happy path both values are set by provision, so this is about the failure modes, not the common case.

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] Support activity protocol

7 participants