Supporting RestChannelServiceClientFactory configuration from ChannelAdapter constructor - #513
Conversation
There was a problem hiding this comment.
Pull request overview
This PR extends the HTTP-based hosting adapters (aiohttp/FastAPI) to allow configuring RestChannelServiceClientFactory construction via a channel_service_client_factory_options dictionary, enabling scenarios like overriding the token_service_endpoint used by UserTokenClient.
Changes:
- Added
channel_service_client_factory_optionsto aiohttp and FastAPICloudAdapterconstructors and forwarded it to the base adapter. - Updated
HttpAdapterBaseto pass the options through when instantiatingRestChannelServiceClientFactory. - Added integration tests to verify
UserTokenClientuses the configured token service endpoint.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| libraries/microsoft-agents-hosting-fastapi/microsoft_agents/hosting/fastapi/cloud_adapter.py | Exposes and forwards factory options from the FastAPI adapter constructor. |
| libraries/microsoft-agents-hosting-aiohttp/microsoft_agents/hosting/aiohttp/cloud_adapter.py | Exposes and forwards factory options from the aiohttp adapter constructor. |
| libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/_http_adapter_base.py | Wires the options into RestChannelServiceClientFactory construction. |
| dev/integration/tests/adapter/test_fastapi_cloud_adapter.py | Adds integration coverage for configured token service endpoint (FastAPI). |
| dev/integration/tests/adapter/test_aiohttp_cloud_adapter.py | Adds integration coverage for configured token service endpoint (aiohttp). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Kyle Rohn (kylerohn-msft)
left a comment
There was a problem hiding this comment.
changelog
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (3)
libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/_http_adapter_base.py:75
- channel_service_client_factory_options is expanded directly into RestChannelServiceClientFactory via **kwargs. If a caller passes an unknown/typo key, this will raise a generic TypeError ("unexpected keyword argument") during adapter construction. Consider validating the allowed option keys and raising a clearer ValueError so API consumers get an actionable error message.
factory = RestChannelServiceClientFactory(
connection_manager,
**(channel_service_client_factory_options or {}),
)
dev/integration/tests/adapter/test_fastapi_cloud_adapter.py:50
- This test asserts against aiohttp ClientSession's private attribute client._base_url. That makes the test brittle across aiohttp versions and also bakes in an internal detail of UserTokenClient. Prefer asserting via a public surface (e.g., expose the configured endpoint on UserTokenClient) so the test validates behavior without depending on private internals.
try:
assert str(client.client._base_url) == f"{token_service_endpoint}/"
dev/integration/tests/adapter/test_aiohttp_cloud_adapter.py:50
- This test asserts against aiohttp ClientSession's private attribute client._base_url. That makes the test brittle across aiohttp versions and also bakes in an internal detail of UserTokenClient. Prefer asserting via a public surface (e.g., expose the configured endpoint on UserTokenClient) so the test validates behavior without depending on private internals.
try:
assert str(client.client._base_url) == f"{token_service_endpoint}/"
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (4)
libraries/microsoft-agents-hosting-fastapi/microsoft_agents/hosting/fastapi/cloud_adapter.py:36
- The docstring doesn’t indicate which keys are valid in
channel_service_client_factory_optionsor that they are forwarded as keyword args toRestChannelServiceClientFactory. Listing supported keys (at leasttoken_service_endpointandtoken_service_audience) will prevent confusing runtimeTypeError: __init__() got an unexpected keyword ...errors for typos.
:param channel_service_client_factory_options: Optional dictionary of options to pass to the channel service client factory
This is only used if channel_service_client_factory is not provided and connection_manager is provided.
libraries/microsoft-agents-hosting-aiohttp/microsoft_agents/hosting/aiohttp/cloud_adapter.py:35
- The docstring doesn’t indicate which keys are valid in
channel_service_client_factory_optionsor that they are forwarded as keyword args toRestChannelServiceClientFactory. Listing supported keys (at leasttoken_service_endpointandtoken_service_audience) will prevent confusing runtimeTypeError: __init__() got an unexpected keyword ...errors for typos.
:param channel_service_client_factory_options: Optional dictionary of options to pass to the channel service client factory
This is only used if channel_service_client_factory is not provided and connection_manager is provided.
changelog.md:4
- The release note says “Added optional argument to
CloudAdapterto configure Token Service endpoint…”, but the actual API added ischannel_service_client_factory_options(a dict forwarded as kwargs toRestChannelServiceClientFactory). Naming the parameter and the supported key(s) will make the changelog accurate and actionable for users.
- **Regionalized UserTokenClient Support**: Added optional argument to `CloudAdapter` to configure Token Service endpoint used by `RestChannelServiceClientFactory` when creating `UserTokenClient` instances.
libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/_http_adapter_base.py:75
- The new wiring that forwards
channel_service_client_factory_optionsintoRestChannelServiceClientFactoryisn’t covered by the default CI test run: rootpytest.inisetstestpaths = tests, so the newly added adapter tests underdev/integration/tests/adapter/won’t execute in CI. To ensure regressions are caught, consider moving/duplicating these assertions intotests/hosting_aiohttp/andtests/hosting_fastapi/, or updating the CI pytest invocation/config to include the dev integration suite.
factory = RestChannelServiceClientFactory(
connection_manager,
**(channel_service_client_factory_options or {}),
)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (7)
libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/_http_adapter_base.py:75
- Using truthiness checks for
channel_service_client_factory/connection_managercan mis-handle valid objects that define falsy__bool__/__len__. Also, ifchannel_service_client_factory_optionscontains invalid keys or non-string keys, the resultingTypeErroris raised fromRestChannelServiceClientFactorywithout any adapter context; wrapping it makes the error easier to diagnose for callers.
factory = RestChannelServiceClientFactory(
connection_manager,
**(channel_service_client_factory_options or {}),
)
libraries/microsoft-agents-hosting-aiohttp/microsoft_agents/hosting/aiohttp/cloud_adapter.py:36
channel_service_client_factory_optionsdoesn’t state what options are accepted. Since this is a new public constructor parameter, it should at least name the primary supported key(s) (e.g.,token_service_endpoint) so users don’t need to read the core factory implementation to discover them.
:param connection_manager: Optional connection manager for OAuth.
:param channel_service_client_factory: Factory for creating channel service clients.
:param channel_service_client_factory_options: Optional dictionary of options to pass to the channel service client factory
This is only used if channel_service_client_factory is not provided and connection_manager is provided.
"""
libraries/microsoft-agents-hosting-core/microsoft_agents/hosting/core/_http_adapter_base.py:44
channel_service_client_factory_optionsis documented as a generic dict, but it doesn’t describe which keys are supported (or that they must matchRestChannelServiceClientFactorykeyword args). This makes the new public API hard to discover and use correctly.
:param connection_manager: Optional connection manager for OAuth.
:param channel_service_client_factory: Factory for creating channel service clients.
:param channel_service_client_factory_options: Optional dictionary of options to pass to the channel service client factory
This is only used if channel_service_client_factory is not provided and connection_manager is provided.
libraries/microsoft-agents-hosting-fastapi/microsoft_agents/hosting/fastapi/cloud_adapter.py:36
channel_service_client_factory_optionsdoesn’t state what options are accepted. Since this is a new public constructor parameter, it should at least name the primary supported key(s) (e.g.,token_service_endpoint) so users don’t need to read the core factory implementation to discover them.
:param connection_manager: Optional connection manager for OAuth.
:param channel_service_client_factory: Factory for creating channel service clients.
:param channel_service_client_factory_options: Optional dictionary of options to pass to the channel service client factory
This is only used if channel_service_client_factory is not provided and connection_manager is provided.
dev/integration/tests/adapter/test_fastapi_cloud_adapter.py:24
- These tests live under
dev/integration/tests, but the repo’s default CI workflow runspytestfrom the repo root and only discoverstestpaths = tests(seepytest.ini). As a result, this coverage won’t run in PR CI unless a separate workflow/job runsdev/integration’s pytest config.
@pytest.mark.asyncio
@pytest.mark.parametrize(
"token_service_endpoint",
[
"https://europe.api.botframework.com",
"https://unitedstates.api.botframework.com",
"https://india.api.botframework.com",
],
)
async def test_cloud_adapter_configures_user_token_client_endpoint(
dev/integration/tests/adapter/test_aiohttp_cloud_adapter.py:24
- These tests live under
dev/integration/tests, but the repo’s default CI workflow runspytestfrom the repo root and only discoverstestpaths = tests(seepytest.ini). As a result, this coverage won’t run in PR CI unless a separate workflow/job runsdev/integration’s pytest config.
@pytest.mark.asyncio
@pytest.mark.parametrize(
"token_service_endpoint",
[
"https://europe.api.botframework.com",
"https://unitedstates.api.botframework.com",
"https://india.api.botframework.com",
],
)
async def test_cloud_adapter_configures_user_token_client_endpoint(
changelog.md:4
- The changelog entry is a bit ambiguous about what the new CloudAdapter argument is called, and it includes a trailing space at the end of the line. Naming the parameter and the primary option key makes the release note more actionable for users.
- **Regionalized UserTokenClient Support**: Added optional argument to `CloudAdapter` to configure Token Service endpoint used by `RestChannelServiceClientFactory` when creating `UserTokenClient` instances.
This pull request adds support for configuring the
token_service_endpointfor the user token client in both theaiohttpandfastapiCloudAdapterclasses. This is achieved by allowing an options dictionary to be passed to the channel service client factory, and by testing that the correct endpoint is used. The main changes are grouped below.Feature: Configurable Token Service Endpoint
channel_service_client_factory_optionsparameter to theCloudAdapterconstructors in bothaiohttpandfastapiadapters, allowing users to specify options such astoken_service_endpoint. [1] [2]_http_adapter_base.py) to accept and forwardchannel_service_client_factory_optionswhen constructing the channel service client factory, ensuring these options are used in client creation. [1] [2]Testing
aiohttpandfastapiadapters to verify that theUserTokenClientis correctly configured with the providedtoken_service_endpoint. [1] [2]…Adapter creation