From c525c9d2da977dd715eaa77de3f90f5d5d4437e5 Mon Sep 17 00:00:00 2001 From: Axel Suarez Date: Thu, 7 Aug 2025 17:07:57 -0700 Subject: [PATCH 1/2] no config agent WIP --- .../hosting/core/app/agent_application.py | 29 +++----- .../hosting/core/app/oauth/authorization.py | 4 + test_samples/app_style/emtpy_agent.py | 73 +++---------------- 3 files changed, 25 insertions(+), 81 deletions(-) diff --git a/libraries/microsoft-agents-hosting-core/microsoft/agents/hosting/core/app/agent_application.py b/libraries/microsoft-agents-hosting-core/microsoft/agents/hosting/core/app/agent_application.py index da0e90ce..142f311c 100644 --- a/libraries/microsoft-agents-hosting-core/microsoft/agents/hosting/core/app/agent_application.py +++ b/libraries/microsoft-agents-hosting-core/microsoft/agents/hosting/core/app/agent_application.py @@ -147,24 +147,17 @@ def __init__( if authorization: self._auth = authorization else: - if not connection_manager: - logger.error( - "ApplicationOptions.authorization requires a Connections instance.", - stack_info=True, - ) - raise ApplicationError( - """ - The `AgentApplication` requires a `Connections` instance to be passed as the - `connection_manager` parameter. - """ - ) - else: - self._auth = Authorization( - storage=self._options.storage, - connection_manager=connection_manager, - handlers=options.authorization_handlers, - **configuration, - ) + auth_options = { + key: value + for key, value in configuration.items() + if key not in ["storage", "connection_manager", "handlers"] + } + self._auth = Authorization( + storage=self._options.storage, + connection_manager=connection_manager, + handlers=options.authorization_handlers, + **auth_options, + ) @property def adapter(self) -> ChannelServiceAdapter: diff --git a/libraries/microsoft-agents-hosting-core/microsoft/agents/hosting/core/app/oauth/authorization.py b/libraries/microsoft-agents-hosting-core/microsoft/agents/hosting/core/app/oauth/authorization.py index ca420393..b49ee253 100644 --- a/libraries/microsoft-agents-hosting-core/microsoft/agents/hosting/core/app/oauth/authorization.py +++ b/libraries/microsoft-agents-hosting-core/microsoft/agents/hosting/core/app/oauth/authorization.py @@ -242,6 +242,10 @@ async def _handle_obo( Returns: The new token response. """ + if not self._connection_manager: + logger.error("Connection manager is not configured", stack_info=True) + raise ValueError("Connection manager is not configured") + auth_handler = self.resolver_handler(handler_id) if auth_handler.flow is None: logger.error("OAuth flow is not configured for the auth handler") diff --git a/test_samples/app_style/emtpy_agent.py b/test_samples/app_style/emtpy_agent.py index 9fa9b420..261ca2f4 100644 --- a/test_samples/app_style/emtpy_agent.py +++ b/test_samples/app_style/emtpy_agent.py @@ -1,92 +1,39 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -import re -import sys -import traceback -from aiohttp.web import Application, Request, Response, run_app -from dotenv import load_dotenv - -from os import environ, path -from microsoft.agents.hosting.aiohttp import ( - CloudAdapter, - jwt_authorization_middleware, - start_agent_process, -) from microsoft.agents.hosting.core import ( - Authorization, AgentApplication, TurnState, TurnContext, MemoryStorage, ) -from microsoft.agents.authentication.msal import MsalConnectionManager -from microsoft.agents.activity import load_configuration_from_env - -load_dotenv(path.join(path.dirname(__file__), ".env")) -agents_sdk_config = load_configuration_from_env(environ) - -STORAGE = MemoryStorage() -CONNECTION_MANAGER = MsalConnectionManager(**agents_sdk_config) -ADAPTER = CloudAdapter(connection_manager=CONNECTION_MANAGER) -AUTHORIZATION = Authorization(STORAGE, CONNECTION_MANAGER, **agents_sdk_config) +from shared import start_server AGENT_APP = AgentApplication[TurnState]( - storage=STORAGE, adapter=ADAPTER, authorization=AUTHORIZATION, **agents_sdk_config + storage=MemoryStorage(), ) -@AGENT_APP.conversation_update("membersAdded") -async def on_members_added(context: TurnContext, _state: TurnState): +async def _help(context: TurnContext, _state: TurnState): await context.send_activity( - "Welcome to the empty agent! " - "This agent is designed to be a starting point for your own agent development." + "Welcome to the Echo Agent sample 🚀. " + "Type /help for help or send a message to see the echo feature in action." ) - return True -@AGENT_APP.message(re.compile(r"^hello$")) -async def on_hello(context: TurnContext, _state: TurnState): - await context.send_activity("Hello!") +AGENT_APP.conversation_update("membersAdded")(_help) + +AGENT_APP.message("/help")(_help) @AGENT_APP.activity("message") -async def on_message(context: TurnContext, _state: TurnState): +async def on_message(context: TurnContext, _): await context.send_activity(f"you said: {context.activity.text}") -@AGENT_APP.error -async def on_error(context: TurnContext, error: Exception): - # This check writes out errors to console log .vs. app insights. - # NOTE: In production environment, you should consider logging this to Azure - # application insights. - print(f"\n [on_turn_error] unhandled error: {error}", file=sys.stderr) - traceback.print_exc() - - # Send a message to the user - await context.send_activity("The bot encountered an error or bug.") - - -# Listen for incoming requests on /api/messages -async def messages(req: Request) -> Response: - agent: AgentApplication = req.app["agent_app"] - adapter: CloudAdapter = req.app["adapter"] - return await start_agent_process( - req, - agent, - adapter, - ) - - -APP = Application(middlewares=[jwt_authorization_middleware]) -APP.router.add_post("/api/messages", messages) -APP["agent_configuration"] = CONFIG -APP["agent_app"] = AGENT_APP -APP["adapter"] = ADAPTER - if __name__ == "__main__": try: - run_app(APP, host="localhost", port=CONFIG.PORT) + start_server(AGENT_APP, None) except Exception as error: raise error From 5c12f32b4ac052f227b72acd45c5cc17eb833743 Mon Sep 17 00:00:00 2001 From: Axel Suarez Date: Mon, 11 Aug 2025 12:58:29 -0700 Subject: [PATCH 2/2] no config agent WIP. testing impact on other scenarios --- .../microsoft/agents/hosting/aiohttp/cloud_adapter.py | 2 +- .../agents/hosting/aiohttp/jwt_authorization_middleware.py | 2 +- test_samples/app_style/emtpy_agent.py | 3 ++- test_samples/app_style/shared/start_server.py | 1 + 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/microsoft-agents-hosting-aiohttp/microsoft/agents/hosting/aiohttp/cloud_adapter.py b/libraries/microsoft-agents-hosting-aiohttp/microsoft/agents/hosting/aiohttp/cloud_adapter.py index d000dd4f..c47d99fe 100644 --- a/libraries/microsoft-agents-hosting-aiohttp/microsoft/agents/hosting/aiohttp/cloud_adapter.py +++ b/libraries/microsoft-agents-hosting-aiohttp/microsoft/agents/hosting/aiohttp/cloud_adapter.py @@ -36,7 +36,7 @@ class CloudAdapter(ChannelServiceAdapter, AgentHttpAdapter): def __init__( self, *, - connection_manager: Connections, + connection_manager: Connections = None, channel_service_client_factory: ChannelServiceClientFactoryBase = None, ): """ diff --git a/libraries/microsoft-agents-hosting-aiohttp/microsoft/agents/hosting/aiohttp/jwt_authorization_middleware.py b/libraries/microsoft-agents-hosting-aiohttp/microsoft/agents/hosting/aiohttp/jwt_authorization_middleware.py index a9b594c6..e0be82d2 100644 --- a/libraries/microsoft-agents-hosting-aiohttp/microsoft/agents/hosting/aiohttp/jwt_authorization_middleware.py +++ b/libraries/microsoft-agents-hosting-aiohttp/microsoft/agents/hosting/aiohttp/jwt_authorization_middleware.py @@ -22,7 +22,7 @@ async def jwt_authorization_middleware(request: Request, handler): print(f"JWT validation error: {e}") return json_response({"error": str(e)}, status=401) else: - if not auth_config.CLIENT_ID: + if not auth_config or not auth_config.CLIENT_ID: # TODO: Refine anonymous strategy request["claims_identity"] = token_validator.get_anonymous_claims() else: diff --git a/test_samples/app_style/emtpy_agent.py b/test_samples/app_style/emtpy_agent.py index 261ca2f4..a0b5e817 100644 --- a/test_samples/app_style/emtpy_agent.py +++ b/test_samples/app_style/emtpy_agent.py @@ -7,11 +7,12 @@ TurnContext, MemoryStorage, ) +from microsoft.agents.hosting.aiohttp import CloudAdapter from shared import start_server AGENT_APP = AgentApplication[TurnState]( - storage=MemoryStorage(), + storage=MemoryStorage(), adapter=CloudAdapter() ) diff --git a/test_samples/app_style/shared/start_server.py b/test_samples/app_style/shared/start_server.py index a75e3d05..417ba637 100644 --- a/test_samples/app_style/shared/start_server.py +++ b/test_samples/app_style/shared/start_server.py @@ -22,6 +22,7 @@ async def entry_point(req: Request) -> Response: APP = Application(middlewares=[jwt_authorization_middleware]) APP.router.add_post("/api/messages", entry_point) + APP.router.add_get("/api/messages", lambda _: Response(status=200)) APP["agent_configuration"] = auth_configuration APP["agent_app"] = agent_application APP["adapter"] = agent_application.adapter