Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This quickstart guides you through creating a custom engine agent that replies back with whatever message you send to it.
Prerequisites
Python 3.9 or newer.
- To install Python, go to https://www.python.org/downloads/, and follow the instructions for your operating system.
- To verify the version, in a terminal window type
python --version.
A code editor of your choice. These instructions use Visual Studio Code.
If you use Visual Studio Code, install the Python extension
Initialize the project and install the SDK
Create a Python project and install the required dependencies.
Open a terminal and create a new folder
mkdir echo cd echoOpen the folder using Visual Studio Code using this command:
code .Create a virtual environment with the method of your choice and activate it either through Visual Studio Code or in a terminal.
When using Visual Studio Code, you can use these steps with the Python extension installed.
Press F1, type
Python: Create environment, and press Enter.Select Venv to create a
.venvvirtual environment in the current workspace.Select a Python installation to create the virtual environment.
The value might look like this:
Python 1.13.6 ~\AppData\Local\Programs\Python\Python313\python.exe
Install the Agents SDK
Use pip to install the microsoft-agents-hosting-aiohttp package with this command:
pip install microsoft-agents-hosting-aiohttp
Create the server application and import the required libraries
Create a file named
start_server.py, copy the following code, and paste it in:# start_server.py from os import environ from microsoft_agents.hosting.core import AgentApplication, AgentAuthConfiguration from microsoft_agents.hosting.aiohttp import ( start_agent_process, jwt_authorization_middleware, CloudAdapter, ) from aiohttp.web import Request, Response, Application, run_app def start_server( agent_application: AgentApplication, auth_configuration: AgentAuthConfiguration ): async def entry_point(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", 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 try: run_app(APP, host="localhost", port=environ.get("PORT", 3978)) except Exception as error: raise errorThis code defines a
start_serverfunction we'll use in the next file.In the same directory, create a file named
app.pywith the following code.# app.py from microsoft_agents.hosting.core import ( AgentApplication, TurnState, TurnContext, MemoryStorage, ) from microsoft_agents.hosting.aiohttp import CloudAdapter from start_server import start_server
Create an instance of the Agent as an AgentApplication
In app.py, add the following code to create the AGENT_APP as an instance of the AgentApplication, and implement three routes to respond to three events:
- Conversation Update
- the message
/help - any other activity
AGENT_APP = AgentApplication[TurnState](
storage=MemoryStorage(), adapter=CloudAdapter()
)
async def _help(context: TurnContext, _: TurnState):
await context.send_activity(
"Welcome to the Echo Agent sample 🚀. "
"Type /help for help or send a message to see the echo feature in action."
)
AGENT_APP.conversation_update("membersAdded")(_help)
AGENT_APP.message("/help")(_help)
@AGENT_APP.activity("message")
async def on_message(context: TurnContext, _):
await context.send_activity(f"you said: {context.activity.text}")
Start the web server to listen in localhost:3978
At the end of app.py, start the web server using start_server.
if __name__ == "__main__":
try:
start_server(AGENT_APP, None)
except Exception as error:
raise error
Run the Agent locally in anonymous mode
From your terminal, run this command:
python app.py
The terminal should return the following:
======== Running on http://localhost:3978 ========
(Press CTRL+C to quit)
Test the agent locally
From another terminal (to keep the agent running) install the Microsoft 365 Agents Playground with this command:
npm install -g @microsoft/teams-app-test-toolNote
This command uses npm because the Microsoft 365 Agents Playground isn't available using pip.
The terminal should return something like:
added 1 package, and audited 130 packages in 1s 19 packages are looking for funding run `npm fund` for details found 0 vulnerabilitiesRun the test tool to interact with your agent using this command:
teamsapptesterThe terminal should return something like:
Telemetry: agents-playground-cli/serverStart {"cleanProperties":{"options":"{\"configFileOptions\":{\"path\":\"<REDACTED: user-file-path>\"},\"appConfig\":{},\"port\":56150,\"disableTelemetry\":false}"}} Telemetry: agents-playground-cli/cliStart {"cleanProperties":{"isExec":"false","argv":"<REDACTED: user-file-path>,<REDACTED: user-file-path>"}} Listening on 56150 Microsoft 365 Agents Playground is being launched for you to debug the app: http://localhost:56150 started web socket client started web socket client Waiting for connection of endpoint: http://127.0.0.1:3978/api/messages waiting for 1 resources: http://127.0.0.1:3978/api/messages wait-on(37568) complete Telemetry: agents-playground-server/getConfig {"cleanProperties":{"internalConfig":"{\"locale\":\"en-US\",\"localTimezone\":\"America/Los_Angeles\",\"channelId\":\"msteams\"}"}} Telemetry: agents-playground-server/sendActivity {"cleanProperties":{"activityType":"installationUpdate","conversationId":"5305bb42-59c9-4a4c-a2b6-e7a8f4162ede","headers":"{\"x-ms-agents-playground\":\"true\"}"}} Telemetry: agents-playground-server/sendActivity {"cleanProperties":{"activityType":"conversationUpdate","conversationId":"5305bb42-59c9-4a4c-a2b6-e7a8f4162ede","headers":"{\"x-ms-agents-playground\":\"true\"}"}}
The teamsapptester command opens your default browser and connects to your agent.
Now you can send any message to see the echo reply, or send the message /help to see how that message is routed to the _help handler.
Next steps
This quickstart guides you through creating a custom engine agent that just replies with whatever you send to it.
Prerequisites
Node.js v22 or newer
- To install Node.js go to nodejs.org, and follow the instructions for your operating system.
- To verify the version, in a terminal window type
node --version.
A code editor of your choice. These instructions use Visual Studio Code.
Initialize the project and install the SDK
Use npm to initialize a node.js project by creating a package.json and installing the required dependencies
Open a terminal and create a new folder
mkdir echo cd echoInitialize the node.js project
npm init -yInstall the Agents SDK
npm install @microsoft/agents-hosting-expressOpen the folder using Visual Studio Code using the this command:
code .
Import the required libraries
Create the file index.mjs and import the following NPM packages into your application code:
// index.mjs
import { startServer } from '@microsoft/agents-hosting-express'
import { AgentApplication, MemoryStorage } from '@microsoft/agents-hosting'
Implement the EchoAgent as an AgentApplication
In index.mjs, add the following code to create the EchoAgent extending the AgentApplication, and implement three routes to respond to three events:
- Conversation Update
- the message
/help - any other activity
class EchoAgent extends AgentApplication {
constructor (storage) {
super({ storage })
this.onConversationUpdate('membersAdded', this._help)
this.onMessage('/help', this._help)
this.onActivity('message', this._echo)
}
_help = async context =>
await context.sendActivity(`Welcome to the Echo Agent sample 🚀.
Type /help for help or send a message to see the echo feature in action.`)
_echo = async (context, state) => {
let counter= state.getValue('conversation.counter') || 0
await context.sendActivity(`[${counter++}]You said: ${context.activity.text}`)
state.setValue('conversation.counter', counter)
}
}
Start the web server to listen in localhost:3978
At the end of index.mjs start the web server using startServer based on express using MemoryStorage as the turn state storage.
startServer(new EchoAgent(new MemoryStorage()))
Run the Agent locally in anonymous mode
From your terminal, run this command:
node index.mjs
The terminal should return this:
Server listening to port 3978 on sdk 0.6.18 for appId undefined debug undefined
Test the agent locally
From another terminal (to keep the agent running) install the Microsoft 365 Agents Playground with this command:
npm install -D @microsoft/teams-app-test-toolThe terminal should return something like:
added 1 package, and audited 130 packages in 1s 19 packages are looking for funding run `npm fund` for details found 0 vulnerabilitiesRun the test tool to interact with your agent using this command:
node_modules/.bin/teamsapptesterThe terminal should return something like:
Telemetry: agents-playground-cli/serverStart {"cleanProperties":{"options":"{\"configFileOptions\":{\"path\":\"<REDACTED: user-file-path>\"},\"appConfig\":{},\"port\":56150,\"disableTelemetry\":false}"}} Telemetry: agents-playground-cli/cliStart {"cleanProperties":{"isExec":"false","argv":"<REDACTED: user-file-path>,<REDACTED: user-file-path>"}} Listening on 56150 Microsoft 365 Agents Playground is being launched for you to debug the app: http://localhost:56150 started web socket client started web socket client Waiting for connection of endpoint: http://127.0.0.1:3978/api/messages waiting for 1 resources: http://127.0.0.1:3978/api/messages wait-on(37568) complete Telemetry: agents-playground-server/getConfig {"cleanProperties":{"internalConfig":"{\"locale\":\"en-US\",\"localTimezone\":\"America/Los_Angeles\",\"channelId\":\"msteams\"}"}} Telemetry: agents-playground-server/sendActivity {"cleanProperties":{"activityType":"installationUpdate","conversationId":"5305bb42-59c9-4a4c-a2b6-e7a8f4162ede","headers":"{\"x-ms-agents-playground\":\"true\"}"}} Telemetry: agents-playground-server/sendActivity {"cleanProperties":{"activityType":"conversationUpdate","conversationId":"5305bb42-59c9-4a4c-a2b6-e7a8f4162ede","headers":"{\"x-ms-agents-playground\":\"true\"}"}}
The teamsapptester command opens your default browser and connects to your agent.
Now you can send any message to see the echo reply, or send the message /help to see how that message is routed to the _help handler.
Next steps
This quickstart shows you how to download and run the QuickStart/Empty Agent sample from GitHub.
There are two main ways to get started with the Microsoft 365 Agents SDK:
Clone and run the QuickStart/Empty Agent agent sample available on GitHub
Use the Microsoft 365 Agents Toolkit. The Agents Toolkit has two built-in templates for Visual Studio and Visual Studio Code that use the Microsoft 365 Agents SDK for starting with an QuickStart/Empty Agent and a Weather Agent that uses Azure Foundry or OpenAI Services with either Semantic Kernel or LangChain.
Prerequisites
You need a few things before you get started. These steps use the QuickStart/Empty Agent sample at .NET quickstart, but you could also use any Agents SDK sample.
- .NET 8.0 SDK
- Visual Studio or Visual Studio Code
- Knowledge of ASP.NET Core and asynchronous programming in C#
- Download the
quickstartsample from GitHub
Open the solution
Open the solution file
QuickStart.csprojin Visual Studio.Run the project.
At this point, your agent is running locally using port 3978.
Test your agent locally
Install the Agents Playground if you haven't already.
winget install agentsplaygroundStart the agent in Visual Studio or Visual Studio Code
Start the Teams App Tester. At a command prompt:
agentsplayground- The tool opens a web browser showing the Teams App Test Tool, ready to send messages to your agent.
Your running agent on port 3978 should connect automatically to the agent playground in your browser and you should be able to interact with your agent running locally
How does the agent work?
With the Agents SDK, an agent is built using AgentApplication and AgentApplicationOptions classes. This is built in the Program.cs file of the sample.
Build your agent
You can see in the sample, that as the agent is being built AgentApplicationOptions is loaded and your custom agent class MyAgent.cs that inherits from AgentApplication
// Add AgentApplicationOptions from appsettings section "AgentApplication".
builder.AddAgentApplicationOptions();
// Add the AgentApplication, which contains the logic for responding to
// user messages.
builder.AddAgent<MyAgent>();
Then the storage is loaded by default using the MemoryStorage class. This allows for context to be tracked across turns when using TurnState however should be switched out in production for more persistant storage such as BlobsStorage or CosmosDbPartitionedStorage.
builder.Services.AddSingleton<IStorage, MemoryStorage>();
The rest of the agent application uses standard .NET hosting patterns, and adds routes to accept messages at a specific endpoint. These routes use the IAgent interface to accept the agent activity, and provides developers with the AgentApplication object to work with the Activity payload that got passed to it from the channel/client. Learn more about the Activities and working with Activities
// This receives incoming messages from Azure Bot Service or other SDK Agents
var incomingRoute = app.MapPost("/api/messages", async (HttpRequest request, HttpResponse response, IAgentHttpAdapter adapter, IAgent agent, CancellationToken cancellationToken) =>
{
await adapter.ProcessAsync(request, response, agent, cancellationToken);
});
Add new custom logic in a method
Developers add custom logic in the MyAgent.cs class that implements AgentApplication. This class uses the AgentApplicationOptions to configure any specific settings from your config and Program.cs and registers event listeners from the Agents SDK, available in the AgentApplication class that references your respective custom method when those events are triggered from the client.
In the following example, OnConversationUpdate triggers the WelcomeMessageAsync method and OnActivity triggers the method OnMessageAsync.
public MyAgent(AgentApplicationOptions options) : base(options)
{
OnConversationUpdate(ConversationUpdateEvents.MembersAdded, WelcomeMessageAsync);
OnActivity(ActivityTypes.Message, OnMessageAsync, rank: RouteRank.Last);
}
Those events are routed via the endpoint configured in your MyProgram.cs and there are numerous events that you can use. The most common is OnActivity. To learn more about the events that the SDK implement, check out more about working with activities and the Activity protocol specification.
Once your method is triggered, for example OnMessageAsync to end the turn, you can choose in your custom logic to respond to send a message back to the client by using the methods available on and instance of the TurnContext class that should be a parameter in your method as shown in the following example:
private async Task OnMessageAsync(ITurnContext turnContext, ITurnState turnState, CancellationToken cancellationToken)
{
await turnContext.SendActivityAsync($"You said: {turnContext.Activity.Text}", cancellationToken: cancellationToken);
}
Tip
Review the other TurnContext methods available to return to the client.
Now you know the basics, check out the next steps and work to add custom handler logic into your agent and sending back different events.
Next Steps
- Learn more about the Activities and working with Activities
- Review the AgentApplication events you can respond to from the client
- Review the TurnContext events you can sent back to the client
- Provision Azure Bot resources to use with Agents SDK
- Configure your .NET Agent to use OAuth
The Agents Playground is available by default if you're already using the Microsoft 365 Agents Toolkit. You can use one of the following guides if you want to get started with the toolkit: