Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions python/openai/sample-agent/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,12 @@ async def setup_mcp_servers(self, auth: Authorization, auth_handler_name: str, c
context=context,
)
else:
# For anonymous mode, don't pass auth/context to avoid token retrieval
self.agent = await self.tool_service.add_tool_servers_to_agent(
agent=self.agent,
auth=auth,
auth_handler_name=auth_handler_name,
context=context,
auth=None,
auth_handler_name=None,
context=None,
auth_token=self.auth_options.bearer_token,
)
Comment on lines +235 to 242

Copilot AI Jan 20, 2026

Copy link

Choose a reason for hiding this comment

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

The comment states "For anonymous mode, don't pass auth/context to avoid token retrieval", but this approach may break MCP server functionality that depends on context for other purposes beyond authentication. Consider documenting the specific MCP server limitations when running in anonymous mode, or verify that all MCP operations can function with just a bearer token and no context.

Copilot uses AI. Check for mistakes.

Expand Down Expand Up @@ -268,8 +269,11 @@ async def process_user_message(
) -> str:
"""Process user message using the OpenAI Agents SDK"""
try:
# Setup MCP servers
await self.setup_mcp_servers(auth, auth_handler_name, context)
# Setup MCP servers only if not already done or if auth is available
# In anonymous mode (USE_AGENTIC_AUTH=false), skip setup to avoid auth errors
use_agentic_auth = os.getenv("USE_AGENTIC_AUTH", "false").lower() == "true"
if use_agentic_auth and auth is not None:
await self.setup_mcp_servers(auth, auth_handler_name, context)
Comment on lines +272 to +276

Copilot AI Jan 20, 2026

Copy link

Choose a reason for hiding this comment

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

The MCP server setup is now conditionally skipped when agentic auth is disabled. However, this means MCP servers will never be set up in anonymous mode, even if they're configured. The condition checks both use_agentic_auth and auth is not None, but if agentic auth is disabled, auth might still be passed as a parameter (just not used). This could result in MCP servers never being initialized in anonymous mode.

Consider calling setup_mcp_servers unconditionally, since the method already handles both authenticated and anonymous modes internally based on the USE_AGENTIC_AUTH environment variable.

Suggested change
# Setup MCP servers only if not already done or if auth is available
# In anonymous mode (USE_AGENTIC_AUTH=false), skip setup to avoid auth errors
use_agentic_auth = os.getenv("USE_AGENTIC_AUTH", "false").lower() == "true"
if use_agentic_auth and auth is not None:
await self.setup_mcp_servers(auth, auth_handler_name, context)
# Setup MCP servers for each message. The setup_mcp_servers method
# internally handles both authenticated and anonymous modes based on
# the USE_AGENTIC_AUTH environment variable.
await self.setup_mcp_servers(auth, auth_handler_name, context)

Copilot uses AI. Check for mistakes.
Comment on lines +272 to +276

Copilot AI Jan 20, 2026

Copy link

Choose a reason for hiding this comment

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

The environment variable check is duplicated - it's read both in process_user_message (line 274) and in setup_mcp_servers (line 226). This creates redundant code and potential inconsistency if the logic changes. Since setup_mcp_servers already handles the conditional logic internally, the check in process_user_message is unnecessary.

Suggested change
# Setup MCP servers only if not already done or if auth is available
# In anonymous mode (USE_AGENTIC_AUTH=false), skip setup to avoid auth errors
use_agentic_auth = os.getenv("USE_AGENTIC_AUTH", "false").lower() == "true"
if use_agentic_auth and auth is not None:
await self.setup_mcp_servers(auth, auth_handler_name, context)
# Setup MCP servers; internal logic handles auth vs. anonymous modes
await self.setup_mcp_servers(auth, auth_handler_name, context)

Copilot uses AI. Check for mistakes.

# Run the agent with the user message
result = await Runner.run(starting_agent=self.agent, input=message, context=context)
Expand Down
4 changes: 2 additions & 2 deletions python/openai/sample-agent/agent_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ def check_agent_inheritance(agent_class) -> bool:
True if the agent inherits from AgentInterface, False otherwise
"""
if not issubclass(agent_class, AgentInterface):
print(f" Agent {agent_class.__name__} does not inherit from AgentInterface")
print(f"ERROR: Agent {agent_class.__name__} does not inherit from AgentInterface")

Copilot AI Jan 20, 2026

Copy link

Choose a reason for hiding this comment

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

The error message format change from emoji (❌) to text ("ERROR:") improves consistency for systems that don't support emoji rendering, such as certain logging systems or terminals. However, this change is inconsistent with other files in the codebase (e.g., agent.py still uses ❌ and ✅). For better maintainability, consider either changing all emoji-based messages to text format across all files, or keeping the emoji format consistently.

Copilot uses AI. Check for mistakes.
return False

print(f" Agent {agent_class.__name__} properly inherits from AgentInterface")
print(f"SUCCESS: Agent {agent_class.__name__} properly inherits from AgentInterface")
return True
35 changes: 20 additions & 15 deletions python/openai/sample-agent/host_agent_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ def __init__(self, agent_class: type[AgentInterface], *agent_args, **agent_kwarg
if not check_agent_inheritance(agent_class):
raise TypeError(f"Agent class {agent_class.__name__} must inherit from AgentInterface")

self.auth_handler_name = "AGENTIC"
# Only use auth handler when agentic auth is enabled
use_agentic_auth = os.getenv("USE_AGENTIC_AUTH", "false").lower() == "true"
self.auth_handler_name = "AGENTIC" if use_agentic_auth else None

Copilot AI Jan 20, 2026

Copy link

Choose a reason for hiding this comment

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

When agentic authentication is disabled (USE_AGENTIC_AUTH=false), the auth handler is set to None, which means messages can be processed without authentication. This creates a potential security risk if the agent is deployed without proper network-level security controls. Consider adding a warning log message when the server starts in anonymous mode to alert developers that authentication is disabled.

Suggested change
self.auth_handler_name = "AGENTIC" if use_agentic_auth else None
if use_agentic_auth:
self.auth_handler_name = "AGENTIC"
else:
self.auth_handler_name = None
logger.warning(
"Agentic authentication is disabled (USE_AGENTIC_AUTH=false). "
"The GenericAgentHost will accept unauthenticated requests; "
"ensure appropriate network-level access controls are in place for this deployment."
)

Copilot uses AI. Check for mistakes.

self.agent_class = agent_class
self.agent_args = agent_args
Expand Down Expand Up @@ -110,8 +112,9 @@ async def help_handler(context: TurnContext, _: TurnState):
self.agent_app.conversation_update("membersAdded")(help_handler)
self.agent_app.message("/help")(help_handler)

handler = [self.auth_handler_name]
@self.agent_app.activity("message", auth_handlers=handler)
# Only require auth handlers if agentic auth is enabled
handler_config = {"auth_handlers": [self.auth_handler_name]} if self.auth_handler_name else {}
@self.agent_app.activity("message", **handler_config)
Comment on lines +116 to +117

Copilot AI Jan 20, 2026

Copy link

Choose a reason for hiding this comment

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

Using **handler_config to conditionally pass auth_handlers is a clean approach, but it relies on the framework accepting an empty dictionary when no auth handlers are needed. While this likely works, consider verifying that the activity decorator properly handles the case when auth_handlers is not provided, especially to ensure backward compatibility with different versions of the Microsoft Agents SDK.

Copilot uses AI. Check for mistakes.
async def on_message(context: TurnContext, _: TurnState):
"""Handle all messages with the hosted agent"""
try:
Expand All @@ -125,18 +128,20 @@ async def on_message(context: TurnContext, _: TurnState):
await context.send_activity(error_msg)
return

exaau_token = await self.agent_app.auth.exchange_token(
context,
scopes=get_observability_authentication_scope(),
auth_handler_id=self.auth_handler_name,
)

# Cache the agentic token for Agent 365 Observability exporter use
cache_agentic_token(
tenant_id,
agent_id,
exaau_token.token,
)
# Only exchange token if agentic auth is enabled
if self.auth_handler_name:
exaau_token = await self.agent_app.auth.exchange_token(
context,
scopes=get_observability_authentication_scope(),
auth_handler_id=self.auth_handler_name,
)

# Cache the agentic token for Agent 365 Observability exporter use
cache_agentic_token(
tenant_id,
agent_id,
exaau_token.token,
)

user_message = context.activity.text or ""
logger.info(f"📨 Processing message: '{user_message}'")
Expand Down
2 changes: 1 addition & 1 deletion python/openai/sample-agent/start_with_generic_host.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def main():
create_and_run_host(OpenAIAgentWithMCP)

except Exception as e:
print(f" Failed to start server: {e}")
print(f"ERROR: Failed to start server: {e}")
import traceback

traceback.print_exc()
Expand Down
Loading