Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
7c1cbc9
Update README title from '.NET SDK' to 'SDK Samples' (#1)
pontemonti Nov 5, 2025
d81af2c
Added CODEOWNERS and .gitignore files (#2)
pontemonti Nov 5, 2025
c3c1e74
Add .NET Semantic Kernel Sample Agent (#3)
pontemonti Nov 5, 2025
1d90369
Update License to MIT License (#4)
rahuldevikar761 Nov 5, 2025
39a239c
Added Python OpenAI sample (#5)
pontemonti Nov 5, 2025
6f236de
Add LangChain Sample (#7)
JesuTerraz Nov 5, 2025
4cbd949
Add Node.js Claude Sample Agent (#6)
pontemonti Nov 6, 2025
1c0b548
Fix Agent Notifs and update env (#8)
JesuTerraz Nov 6, 2025
ea11209
[Python][AgentFramework] Adding Python Agent Framework Sample (#9)
JesuTerraz Nov 6, 2025
9b124ba
Add TM (#11)
rahuldevikar761 Nov 7, 2025
e99aa17
Revise README for Agent 365 Sample Agent (#13)
pontemonti Nov 7, 2025
d221266
Add TM (#14)
rahuldevikar761 Nov 7, 2025
e733e9c
Update Agents SDK for LangChain Sample (#15)
JesuTerraz Nov 7, 2025
45fffa8
Adding Notifications on AF (#16)
mrunalhirve128 Nov 10, 2025
0b9adea
Add Copilot instructions for code review and validation (#21)
rahuldevikar761 Nov 11, 2025
db60215
Update Sample with API Change (#19)
JesuTerraz Nov 11, 2025
1b01b67
Adding Vercel AI SDK sample with claude model (#23)
dbezic Nov 11, 2025
7716ce5
Add n8n sample agent (#24)
rbrighenti Nov 12, 2025
75e3a7d
Correct example agent name to use correct casing in line with n8n (#26)
rbrighenti Nov 12, 2025
cadc62f
Introducing perplexity Sample Agent (#18)
aubreyquinn Nov 12, 2025
d521cf1
Add OpenAI Nodejs Sample (#28)
JesuTerraz Nov 12, 2025
fea98e1
Rename "Microsoft Agents A365" to "Microsoft Agent 365" in documentat…
Copilot Nov 12, 2025
51edfde
Add Devin Agent Sample (#22)
walterluna Nov 12, 2025
45854e9
Fix OpenAI JS ToolingManifest (#33)
JesuTerraz Nov 13, 2025
35b4a33
add updated nodejs claude implementation (#32)
msftairaamane Nov 13, 2025
224b2dc
Quickstart LangChain Agent (#25)
JesuTerraz Nov 13, 2025
2398b60
Introducing Playground notification handling in Perplexity agent (#34)
aubreyquinn Nov 13, 2025
000ff20
Add Cursor IDE Prompt Guide for Agent365 (#29)
shinsi-fathima-rahman Nov 13, 2025
348b4a9
Update samples to remove environment id from calls and settings (#10)
joratz Nov 13, 2025
6c78dbe
Fix formatting of 'Microsoft Agent365' to 'Microsoft Agent 365' (#39)
pontemonti Nov 13, 2025
292c85c
add quickstart claude agent before A365 extension (#42)
msftairaamane Nov 14, 2025
a5b3168
Update package.json description for clarity (#45)
pontemonti Nov 14, 2025
e8dccd5
Update devin agent sample (#48)
walterluna Nov 14, 2025
42e7d80
updating samples read me docs (#47)
abdulanu0 Nov 15, 2025
df4e892
Update Node.js OpenAI sample (#50)
pontemonti Nov 17, 2025
03f59e9
Introducing thinking indicator in Perplexity sample agent (#37)
aubreyquinn Nov 17, 2025
4112c7a
updating auth handler (#53)
abdulanu0 Nov 18, 2025
2430fd0
Update Python Agent Framework sample (#58)
pontemonti Nov 18, 2025
684a02c
Update Python OpenAI sample agent (#57)
pontemonti Nov 18, 2025
251c405
Introducing observability in Perplexity agent (#44)
aubreyquinn Nov 18, 2025
acc29c9
Add prompt injection defense to agent system prompt (#40)
efpiva Nov 18, 2025
8d931c9
Update Package References to Use npm Registry + Remove local preinsta…
JesuTerraz Nov 18, 2025
0971787
Add temporariy thumbnails to the related samples (#63)
Alive-Fish Nov 18, 2025
7bbfda7
Update .NET Semantic Kernel Sample Agent (#61)
pontemonti Nov 19, 2025
df82639
Update tooling manifest (#60)
pontemonti Nov 19, 2025
f473a8a
Introducing Microsoft Teams manifest file for Perplexity (#51)
aubreyquinn Nov 19, 2025
004f8a2
Add manifest template for n8n Sample (#49)
rbrighenti Nov 19, 2025
6dc7d20
Potential fix for code scanning alert no. 1: Workflow does not contai…
pontemonti Nov 19, 2025
9e8d76d
Add CI workflow for Node.js OpenAI sample agent (#65)
pontemonti Nov 19, 2025
ffaa2ea
Remove local reference in python samples (#62)
JesuTerraz Nov 19, 2025
132d1c3
Google ADK Sample with Tooling (#70)
JesuTerraz Nov 20, 2025
9794391
Updated formatting on readme file (#71)
aubreyquinn Nov 20, 2025
1611d2e
Perplexity: introducing the published agents-a365 packages (#72)
aubreyquinn Nov 20, 2025
c086ffc
Add Devin Agent's manifest sample (#52)
walterluna Nov 20, 2025
c44f444
reference public package dependencies (#64)
walterluna Nov 20, 2025
805f9ae
Perplexity: added telemetry markers to all paths in the code (#73)
aubreyquinn Nov 20, 2025
aa4c676
Updated the scope for messaging. (#78)
Reza-sh Nov 21, 2025
29c31bf
post public documentation changes (#80)
shinsi-fathima-rahman Nov 21, 2025
c1fa6a8
Add agent hosting to google adk sample
Nov 21, 2025
61433b1
Add agent hosting to google adk sample
Nov 21, 2025
4b638e7
add notifications
Nov 21, 2025
79ed3d1
add notifications
Nov 21, 2025
5e69956
fix notifications
Nov 21, 2025
5b4204b
fix notifications
Nov 21, 2025
bb1a9fd
rename wrapper
Nov 21, 2025
cf69e82
rename wrapper
Nov 21, 2025
6218d8f
remove unused fields
Nov 21, 2025
98c67d0
remove unused fields
Nov 21, 2025
23f57eb
get ids from context
Nov 21, 2025
c5ddece
get ids from context
Nov 21, 2025
3b13cfc
use scope in message handler
Nov 21, 2025
944ea25
use scope in message handler
Nov 21, 2025
c7ae173
remove workaround
Nov 21, 2025
7c84daf
remove workaround
Nov 21, 2025
7d801cf
copilot comments
Nov 22, 2025
b5672be
copilot comments
Nov 22, 2025
0c225cd
move email response to only email handling
Dec 4, 2025
f413b32
move email response to only email handling
Dec 4, 2025
84a6b67
pass auth handler name down from hosting
Dec 4, 2025
5f1b85a
pass auth handler name down from hosting
Dec 4, 2025
ce9c3c0
add default response
Dec 4, 2025
4ef2c3d
add default response
Dec 4, 2025
c48db5c
restructure notification handling
Dec 5, 2025
95366b5
restructure notification handling
Dec 5, 2025
f75a4e8
Merge branch 'main' into users/jterrazas/update-google-adk
Dec 15, 2025
719fc85
Merge branch 'main' into users/jterrazas/update-google-adk
Jan 22, 2026
c1e6ca0
Merge branch 'users/jterrazas/update-google-adk' of https://github.co…
Jan 22, 2026
719b55d
Merge branch 'main' into users/jterrazas/update-google-adk
Jan 22, 2026
704db20
removed added files
Jan 22, 2026
0469324
readd MyAgent.cs
Jan 22, 2026
cc48add
checkout myagent file
Jan 22, 2026
b27d584
update default instructions
Jan 22, 2026
df94f5b
Merge branch 'main' into users/jterrazas/update-google-adk
JesuTerraz Jan 23, 2026
561739a
Merge branch 'main' into users/jterrazas/update-google-adk
JesuTerraz Jan 23, 2026
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
234 changes: 129 additions & 105 deletions python/google-adk/sample-agent/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

import asyncio
Comment thread
JesuTerraz marked this conversation as resolved.
Outdated
import os
from typing import Optional
from google.adk.agents import Agent
from dotenv import load_dotenv
Comment thread
JesuTerraz marked this conversation as resolved.
Outdated

# Load environment variables from .env file
load_dotenv()

from mcp_tool_registration_service import McpToolRegistrationService

from microsoft_agents_a365.observability.core.config import configure
Comment thread
JesuTerraz marked this conversation as resolved.
Outdated
Expand All @@ -18,106 +16,132 @@
from google.adk.runners import Runner
from google.adk.sessions.in_memory_session_service import InMemorySessionService

from microsoft_agents.activity import load_configuration_from_env, Activity, ChannelAccount, ActivityTypes
from microsoft_agents.hosting.core import Authorization, MemoryStorage, TurnContext, ClaimsIdentity, AuthenticationConstants
from microsoft_agents.hosting.aiohttp import CloudAdapter
from microsoft_agents.authentication.msal import MsalConnectionManager

agents_sdk_config = load_configuration_from_env(os.environ)

async def main():
# Google ADK expects root_agent to be defined at module level
# Create the base agent synchronously
my_agent = Agent(
name="my_agent",
model="gemini-2.0-flash",
description=(
"Agent to test Mcp tools."
),
instruction=(
"You are a helpful agent who can use tools. If you encounter any errors, please provide the exact error message you encounter."
),
)

auth = Authorization(
storage=MemoryStorage(),
connection_manager=MsalConnectionManager(**agents_sdk_config),
**agents_sdk_config
)

turnContext = TurnContext(
adapter_or_context=CloudAdapter(),
request=Activity(
type=ActivityTypes.message,
text="",
from_property=ChannelAccount(
id='user1',
name='User One'
),
recipient=ChannelAccount(
id=os.getenv("AGENTIC_UPN", ""),
name=os.getenv("AGENTIC_NAME", ""),
agentic_user_id=os.getenv("AGENTIC_USER_ID", ""),
agentic_app_id=os.getenv("AGENTIC_APP_ID", ""),
tenant_id=os.getenv("AGENTIC_TENANT_ID", ""),
role="agenticUser"
)
),
identity=ClaimsIdentity(
{
AuthenticationConstants.AUDIENCE_CLAIM: "anonymous",
AuthenticationConstants.APP_ID_CLAIM: "anonymous-app",
},
False,
"Anonymous",
from microsoft_agents.hosting.core import Authorization, TurnContext

class GoogleADKAgent:
"""Wrapper class for Google ADK Agent with Microsoft Agent 365 integration."""

def __init__(
self,
agent_name: str = "my_agent",
model: str = "gemini-2.0-flash",
description: str = "Agent to test Mcp tools.",
instruction: str = "You are a helpful agent who can use tools. If you encounter any errors, please provide the exact error message you encounter.",
Comment thread
pontemonti marked this conversation as resolved.
Outdated
):
"""
Initialize the Google ADK Agent Wrapper.

Args:
agent_name: Name of the agent
model: Google ADK model to use
description: Agent description
instruction: Agent instruction/prompt
"""
self.agent_name = agent_name
self.model = model
self.description = description
self.instruction = instruction
self.agent: Optional[Agent] = None

self.agent = Agent(
name=self.agent_name,
model=self.model,
description=self.description,
instruction=self.instruction,
)

async def invoke_agent(
self,
message: str,
auth: Authorization,
auth_handler_name: str,
context: TurnContext
) -> str:
"""
Invoke the agent with a user message.

Args:
message: The message from the user

Returns:
List of response messages from the agent
"""
agent = await self._initialize_agent(auth, auth_handler_name, context)

# Create the runner
runner = Runner(
app_name="agents",
agent=agent,
session_service=InMemorySessionService(),
)
)

if not (await auth._start_or_continue_sign_in(turnContext, None, 'AGENTIC')).sign_in_complete():
print("Sign-in required. Exiting.")
return

tool_service = McpToolRegistrationService()

my_agent = await tool_service.add_tool_servers_to_agent(
agent=my_agent,
agentic_app_id=os.getenv("AGENTIC_APP_ID", "agent123"),
auth=auth,
context=turnContext,
auth_token=os.getenv("BEARER_TOKEN", ""),
)

# Create runner
runner = Runner(
app_name="agents",
agent=my_agent,
session_service=InMemorySessionService(),
)

# Run agent
try:
user_message = input("Enter your message to the agent: ")
with BaggageBuilder().tenant_id("your-tenant-id").agent_id("agent123").build():
_ = await runner.run_debug(
user_messages=[user_message]
)
finally:
agent_tools = my_agent.tools
for tool in agent_tools:
if hasattr(tool, "close"):
await tool.close()

if __name__ == "__main__":
configure(
service_name="GoogleADKSampleAgent",
service_namespace="GoogleADKTesting",
)

try:
asyncio.run(main())
except KeyboardInterrupt:
print("\nShutting down gracefully...")
except Exception as e:
# Ignore cleanup errors during shutdown
if "cancel scope" not in str(e) and "RuntimeError" not in type(e).__name__:
raise

responses = []
result = await runner.run_debug(
user_messages=[message]
)

# Extract text responses from the result
if not hasattr(result, '__iter__'):
return responses
Comment thread
JesuTerraz marked this conversation as resolved.
Outdated

for event in result:
if not (hasattr(event, 'content') and event.content):
continue

if not hasattr(event.content, 'parts'):
continue

for part in event.content.parts:
if hasattr(part, 'text') and part.text:
responses.append(part.text)

await self._cleanup_agent(agent)

return responses[-1] if responses else "I couldn't get a response from the agent. :("

async def invoke_agent_with_scope(
self,
message: str,
auth: Authorization,
auth_handler_name: str,
context: TurnContext
) -> str:
"""
Invoke the agent with a user message within an observability scope.

Args:
message: The message from the user

Returns:
List of response messages from the agent
"""
tenant_id = context.activity.recipient.tenant_id
agent_id = context.activity.recipient.agentic_user_id
with BaggageBuilder().tenant_id(tenant_id).agent_id(agent_id).build():
return await self.invoke_agent(message=message, auth=auth, auth_handler_name=auth_handler_name, context=context)

async def _cleanup_agent(self, agent: Agent):
"""Clean up agent resources."""
if agent and hasattr(agent, 'tools'):
for tool in agent.tools:
if hasattr(tool, "close"):
await tool.close()

async def _initialize_agent(self, auth, auth_handler_name, turn_context):
"""Initialize the agent with MCP tools and authentication."""
try:
# Perform sign-in
if not (await auth._start_or_continue_sign_in(turn_context, None, auth_handler_name)).sign_in_complete():
raise RuntimeError("Sign-in required but not completed")

# Add MCP tools to the agent
tool_service = McpToolRegistrationService()
return await tool_service.add_tool_servers_to_agent(
Comment thread
JesuTerraz marked this conversation as resolved.
agent=self.agent,
agentic_app_id=os.getenv("AGENTIC_APP_ID", "agent123"),
auth=auth,
context=turn_context,
auth_token=os.getenv("BEARER_TOKEN", ""),
)
except Exception as e:
print(f"Error during agent initialization: {e}")
Comment thread
JesuTerraz marked this conversation as resolved.
Outdated
31 changes: 31 additions & 0 deletions python/google-adk/sample-agent/agent_interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright (c) Microsoft. All rights reserved.

"""
Agent Base Class
Defines the abstract base class that agents must inherit from to work with the generic host.
"""

from abc import ABC, abstractmethod
from microsoft_agents.hosting.core import Authorization, TurnContext


class AgentInterface(ABC):
"""
Abstract base class that any hosted agent must inherit from.

This ensures agents implement the required methods at class definition time,
providing stronger guarantees than a Protocol.
"""
@abstractmethod
async def invoke_agent(
self, message: str, auth: Authorization, auth_handler_name: str, context: TurnContext
) -> str:
"""Process a user message and return a response."""
pass

@abstractmethod
async def invoke_agent_with_scope(
self, message: str, auth: Authorization, auth_handler_name: str, context: TurnContext
) -> str:
"""Process a user message within an observability scope and return a response."""
pass
Loading
Loading