feat(agentserver): FoundryStorage - M365 Storage adapter on Foundry d…#47978
Conversation
…urable state (Activity Protocol) Adds FoundryStorage, an implementation of the M365 Agents SDK Storage interface for azure-ai-agentserver-activity, backed by the durable FoundryStateStore state-store client from azure-ai-agentserver-core (see PR Azure#47763). Design: - Store name = scope: every M365 storage key is already a scope identifier (e.g. "{channel}/conversations/{conversation_id}", "{channel}/users/{user_id}", "proactive/conversations/{conversation_id}"), so FoundryStorage lazily creates and caches one FoundryStateStore per distinct key instead of a shared namespace. The key doubles as both the store name and the item key. - Keys shaped like the M365 UserState key ("/users/" segment) automatically get user_isolation=True on their backing store; override via is_user_scoped=. - Subclasses the M365 SDK's AsyncStorageBase and implements _read_item/_write_item/_delete_item; batching, validation, and concurrent fan-out come from the base class. - The backing store is only created (get_or_create) lazily on first write for a given key; read/delete treat a not-yet-created store as a missing key. - ActivityAgentServerHost gains a storage= override wired through the M365 bridge (falls back to MemoryStorage). Also renumbers/fixes the new FoundryStorage samples (06-08) to match the package's 01-05 sample convention and current host constructor API, and pulls in azure-ai-agentserver-core's storage/ subtree from PR Azure#47763 as-is (no other core changes) since FoundryStorage depends on FoundryStateStore's statestores-protocol shape. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Thank you for your contribution @shanmukha1200! We will review the pull request and get back to you soon. |
|
@shanmukha1200 please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.
Contributor License AgreementContribution License AgreementThis Contribution License Agreement (“Agreement”) is agreed to by the party signing below (“You”),
|
2 similar comments
|
@shanmukha1200 please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.
Contributor License AgreementContribution License AgreementThis Contribution License Agreement (“Agreement”) is agreed to by the party signing below (“You”),
|
|
@shanmukha1200 please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.
Contributor License AgreementContribution License AgreementThis Contribution License Agreement (“Agreement”) is agreed to by the party signing below (“You”),
|
…e-storage spec (foundrysdk_specs#247)
Per the latest commit on coreai-microsoft/foundrysdk_specs#247
("rename route to /storage/state_stores, add store PATCH update, align
object descriptors"), the state-store REST path is /storage/state_stores/*
(snake_case with underscore), not /storage/statestores/*.
- _state.py: store path + create() now target state_stores.
- _policies.py: masked-logging allowlist updated to the new segment name.
- Updated docs/state-store-guide.md, README, and test URL assertions.
- Fixed the core CHANGELOG/README, which still described the earlier
namespace-based design (pre-dating the PR Azure#47763 pull) instead of the
current store-bound statestores-protocol API; also dropped an unused
aiohttp dependency left over from that earlier design.
No functional change beyond the route rename -- the object-type descriptor
changes in the spec commit (state_store / state_store.item) are response-only
fields the SDK does not parse or assert on.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ure#47978 review Addresses violations found auditing PR Azure#47978 against the repo's Constitution: - MyPy (release-blocking): _read_item's `# type: ignore[attr-defined]` didn't match the real error (`union-attr`), so mypy genuinely failed. Fixed by binding StoreItemT to StoreItem (imported under TYPE_CHECKING only, so the optional M365 SDK is still not a hard runtime dependency) and narrowing target_cls to non-None before use -- no type: ignore needed at all now. - Black (Principle III, "No exceptions"): _foundry_storage.py was not Black-formatted; reformatted. - Strong Type Safety (Principle II): replaced typing.Optional/Tuple/Type with PEP 604 str | None / tuple[...] / type[...] (the module already has rom __future__ import annotations). - Pylint directives: removed the file-level blanket # pylint: disable=docstring-missing-param,... (not in the allowed- suppression list) in favor of full Sphinx :param:/:keyword:/:return:/:rtype: docstrings on every public method (__init__, aclose, __aenter__, __aexit__) and the private lifecycle hooks. Moved import-error/ no-name-in-module suppressions to the specific optional-import lines, matching the existing convention in _m365_bridge.py, instead of a blanket file-level disable. Collapsed the unused fallback Storage stub into just AsyncStorageBase (dead code) and added super().__init__() to fix super-init-not-called. - Sample E2E tests (NON-NEGOTIABLE): samples 06-08 had no corresponding e2e tests. Added tests/test_storage_samples_e2e.py, replicating each sample's handler logic inline (not imported from the sample files) and driving it through the real AgentApplication + HttpAdapterBase.process_activity turn pipeline (state load -> handler -> state save -> outbound send), with MemoryStorage standing in for FoundryStorage and a fake ChannelServiceClientFactory capturing outbound sends -- full lifecycle, no network. Verified: black, mypy, and pytest all clean (99 passed). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…urable state (Activity Protocol)
Adds FoundryStorage, an implementation of the M365 Agents SDK Storage interface for azure-ai-agentserver-activity, backed by the durable FoundryStateStore state-store client from azure-ai-agentserver-core (see PR #47763).
Design:
Also renumbers/fixes the new FoundryStorage samples (06-08) to match the package's 01-05 sample convention and current host constructor API, and pulls in azure-ai-agentserver-core's storage/ subtree from PR #47763 as-is (no other core changes) since FoundryStorage depends on FoundryStateStore's statestores-protocol shape.
Description
Please add an informative description that covers that changes made by the pull request and link all relevant issues.
If an SDK is being regenerated based on a new API spec, a link to the pull request containing these API spec changes should be included above.
All SDK Contribution checklist:
General Guidelines and Best Practices
Testing Guidelines