Repository navigation
Python: Fix M365 agent sample startup and anonymous mode - #9598
Naveen Chatlapalli (1aifanatic) wants to merge 2 commits into
Conversation
- aiohttp's Application takes middlewares=, not middleware= (TypeError at startup). - FoundryChatClient needs a credential; pass AzureCliCredential and document the FOUNDRY_* settings the sample actually reads instead of OpenAI ones. - The M365 Agents SDK now requires a connection manager for CloudAdapter and AgentApplication; give anonymous mode an empty service connection. - ClaimsIdentity's signature is now (claims, authentication_type, ...); build a claim-less anonymous identity so the adapter skips token acquisition. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🔵 Needs a closer look
The anonymous identity and empty MSAL connection depend on external SDK behavior that still needs independent verification before approval.
No open issues 🎉
What changed in this PR
This PR fixes startup and anonymous messaging failures in the Python M365 agent sample reported in #9595.
Changes:
- Corrects aiohttp middleware registration and supplies an Azure CLI credential to
FoundryChatClient. - Adds a placeholder connection manager and claim-less identity for anonymous mode while preserving the authenticated configuration path.
- Updates Foundry setup instructions and corrects the run-command and configuration comments.
| File | Description |
|---|---|
python/samples/05-end-to-end/m365-agent/README.md |
Replaces OpenAI settings with Foundry configuration and Azure CLI prerequisites. |
python/samples/05-end-to-end/m365-agent/m365_agent_demo/app.py |
Fixes startup, configures anonymous SDK components, and corrects usage comments. |
Review effort: Balanced
The anonymous-mode identity uses ClaimsIdentity(authentication_type=...), which arrived in microsoft-agents-hosting-core 1.4.0; on 1.0-1.3 the constructor requires claims and is_authenticated. Verified the sample's anonymous message flow on 1.4.0 through 1.10.0.dev1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Following up on the "needs a closer look" note about relying on M365 Agents SDK behavior, I verified the two anonymous-mode pieces against the SDK source and across releases. Why the anonymous path never touches the placeholder connection (
Version matrix: the sample's anonymous flow, run end to end with aiohttp's test client (agent stubbed, local channel endpoint capturing the reply):
Because the claim-less Authenticated mode, with |
Motivation & Context
The M365 Agents SDK sample (
python/samples/05-end-to-end/m365-agent) does not start, and once startup is fixed, anonymous mode still cannot answer a message. Details and reproduction in #9595:web.Application(middleware=...)raisesTypeError, because aiohttp's keyword ismiddlewares. Themiddlewares→middlewarerename (Python: [BREAKING]: removed display_name, renamed context_providers, middleware and AggregateContextProvider #3139) appears to have caught it.FoundryChatClient()is created without a credential, and the README still documents OpenAI variables.CloudAdapterandAgentApplication.ClaimsIdentitynow takes(claims, authentication_type, ...), so the sample's "anonymous" identity was treated as authenticated and the adapter tried to get an MSAL token (TENANT_ID is not set).Description & Review Guide
web.Application(middlewares=[middleware_fn]).FoundryChatClient(credential=AzureCliCredential()). The README now listsFOUNDRY_PROJECT_ENDPOINT/FOUNDRY_MODELandaz login, and the docstring no longer points to a nonexistent.env.example.build_connection_managerreturns anMsalConnectionManagerwith an emptySERVICE_CONNECTION, andbuild_authorizationalways buildsAuthorization. Anonymous requests never request tokens, so the placeholder connection is never used.ClaimsIdentity(authentication_type="Anonymous")with no claims, whichClaimsIdentity.allow_anonymousrecognizes.samples/05-end-to-end/...instead ofsamples/demos/....MsalConnectionManager(**agents_sdk_config)plusAuthorization.SERVICE_CONNECTIONis an acceptable way to satisfy the SDK in anonymous mode, or whether you would rather the sample require connection settings even for local runs.Verified with aiohttp's test client:
create_app(load_app_config())in anonymous mode, with the agent replaced by an echo stub and a local endpoint standing in for the channel service:mainTypeErroratweb.Application(middleware=...)GET /api/health200,GET /api/messages200,POST /api/messages202, and the reply activity reaches the channelI also checked that the real
build_agent()constructs with onlyFOUNDRY_*set. I could not test authenticated mode, which needs an Azure Bot registration.ruff format --checkpasses.ruff checkreports one pre-existingE501(the longapproval_modeNOTE comment), which is also onmain. Pyright's two remaining errors are pre-existing typing nits (anOptionalreturn type and the synclambdaroute handler), and both routes respond correctly at runtime.Related Issue
Fixes #9595
AI Assistance
AI assistance details: Claude Code helped trace the breakages through aiohttp and the M365 Agents SDK, implement the fix, build the test-client verification, and draft this description and the linked issue.
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.🤖 Generated with Claude Code