Skip to content

feat(vsc): Update basic node templates to latest Agents SDK #14359

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ resource webApp 'Microsoft.Web/sites@2021-02-01' = {
}
{
name: 'WEBSITE_NODE_DEFAULT_VERSION'
value: '~18' // Set NodeJS version to 18.x for your site
value: '~22' // Set NodeJS version to 22.x for your site
}
{
name: 'RUNNING_ON_AZURE'
Expand Down
8 changes: 2 additions & 6 deletions templates/vsc/js/basic-custom-engine-agent/package.json.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
"teamsAppId": null
},
"description": "Basic Custome Engine Agent with Microsoft 365 Agents SDK",
"engines": {
"node": "18 || 20 || 22"
},
"author": "Microsoft",
"license": "MIT",
"main": "./src/index.js",
Expand All @@ -27,13 +24,12 @@
"dependencies": {
"@azure/identity": "^4.8.0",
"@azure/openai": "^2.0.0",
"@microsoft/agents-hosting": "^0.2.14",
"express": "^5.0.1",
"@microsoft/agents-hosting-express": "^1.0.0",
"openai": "^4.94.0"
},
"devDependencies": {
"env-cmd": "^10.1.0",
"nodemon": "^3.1.7",
"nodemon": "^3.1.10",
"shx": "^0.3.3"
}
}
35 changes: 0 additions & 35 deletions templates/vsc/js/basic-custom-engine-agent/src/adapter.js

This file was deleted.

4 changes: 2 additions & 2 deletions templates/vsc/js/basic-custom-engine-agent/src/agent.js.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ const agentApp = new AgentApplication({
storage,
});

agentApp.conversationUpdate("membersAdded", async (context) => {
agentApp.onConversationUpdate("membersAdded", async (context) => {
await context.sendActivity(`Hi there! I'm an agent to chat with you.`);
});

// Listen for ANY message to be received. MUST BE AFTER ANY OTHER MESSAGE HANDLERS
agentApp.activity(ActivityTypes.Message, async (context) => {
agentApp.onActivity(ActivityTypes.Message, async (context) => {
// Echo back users request
const result = await client.chat.completions.create({
messages: [
Expand Down
29 changes: 2 additions & 27 deletions templates/vsc/js/basic-custom-engine-agent/src/index.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,3 @@
// Import required packages
const { authorizeJWT, loadAuthConfigFromEnv } = require("@microsoft/agents-hosting");
const express = require("express");

// This bot's adapter
const adapter = require("./adapter");

// This bot's main dialog.
const { startServer } = require("@microsoft/agents-hosting-express");
const { agentApp } = require("./agent");

// Create authentication configuration
const authConfig = loadAuthConfigFromEnv();

// Create express application.
const expressApp = express();
expressApp.use(express.json());
expressApp.use(authorizeJWT(authConfig));

const server = expressApp.listen(process.env.port || process.env.PORT || 3978, () => {
console.log(`\nAgent started, ${expressApp.name} listening to`, server.address());
});

// Listen for incoming requests.
expressApp.post("/api/messages", async (req, res) => {
await adapter.process(req, res, async (context) => {
await agentApp.run(context);
});
});
startServer(agentApp);
Original file line number Diff line number Diff line change
Expand Up @@ -10,48 +10,48 @@ const downloader = new AttachmentDownloader();

// Define storage and application
const storage = new MemoryStorage();
const teamsBot = new AgentApplication({
const agentApp = new AgentApplication({
storage,
fileDownloaders: [downloader],
});

// Listen for user to say '/reset' and then delete conversation state
teamsBot.message("/reset", async (context, state) => {
agentApp.onMessage("/reset", async (context, state) => {
state.deleteConversationState();
await context.sendActivity("Ok I've deleted the current conversation state.");
});

teamsBot.message("/count", async (context, state) => {
agentApp.onMessage("/count", async (context, state) => {
const count = state.conversation.count ?? 0;
await context.sendActivity(`The count is ${count}`);
});

teamsBot.message("/diag", async (context, state) => {
agentApp.onMessage("/diag", async (context, state) => {
await state.load(context, storage);
await context.sendActivity(JSON.stringify(context.activity));
});

teamsBot.message("/state", async (context, state) => {
agentApp.onMessage("/state", async (context, state) => {
await state.load(context, storage);
await context.sendActivity(JSON.stringify(state));
});

teamsBot.message("/runtime", async (context, state) => {
agentApp.onMessage("/runtime", async (context, state) => {
const runtime = {
nodeversion: process.version,
sdkversion: version,
};
await context.sendActivity(JSON.stringify(runtime));
});

teamsBot.conversationUpdate("membersAdded", async (context, state) => {
agentApp.onConversationUpdate("membersAdded", async (context, state) => {
await context.sendActivity(
`Hi there! I'm an echo bot running on Agents SDK version ${version} that will echo what you said to me.`
);
});

// Listen for ANY message to be received. MUST BE AFTER ANY OTHER MESSAGE HANDLERS
teamsBot.activity(ActivityTypes.Message, async (context, state) => {
agentApp.onActivity(ActivityTypes.Message, async (context, state) => {
// Increment count state
let count = state.conversation.count ?? 0;
state.conversation.count = ++count;
Expand All @@ -60,15 +60,15 @@ teamsBot.activity(ActivityTypes.Message, async (context, state) => {
await context.sendActivity(`[${count}] you said: ${context.activity.text}`);
});

teamsBot.activity(/^message/, async (context, state) => {
agentApp.onActivity(/^message/, async (context, state) => {
await context.sendActivity(`Matched with regex: ${context.activity.type}`);
});

teamsBot.activity(
agentApp.onActivity(
async (context) => Promise.resolve(context.activity.type === "message"),
async (context, state) => {
await context.sendActivity(`Matched function: ${context.activity.type}`);
}
);

module.exports.teamsBot = teamsBot;
module.exports.agentApp = agentApp;
59 changes: 3 additions & 56 deletions templates/vsc/js/default-bot/index.js
Original file line number Diff line number Diff line change
@@ -1,56 +1,3 @@
// index.js is used to setup and configure your bot

// Import required packages
const express = require("express");

// Import required bot services.
// See https://aka.ms/bot-services to learn more about the different parts of a bot.
const { authorizeJWT, CloudAdapter, loadAuthConfigFromEnv } = require("@microsoft/agents-hosting");
const { teamsBot } = require("./teamsBot");

// Create authentication configuration
const authConfig = loadAuthConfigFromEnv();

// Create adapter
const adapter = new CloudAdapter(authConfig);

adapter.onTurnError = async (context, error) => {
// This check writes out errors to console log .vs. app insights.
// NOTE: In production environment, you should consider logging this to Azure
// application insights. See https://aka.ms/bottelemetry for telemetry
// configuration instructions.
console.error(`\n [onTurnError] unhandled error: ${error}`);

// Only send error message for user messages, not for other message types so the bot doesn't spam a channel or chat.
if (context.activity.type === "message") {
// Send a message to the user
await context.sendActivity(`The bot encountered an unhandled error:\n ${error.message}`);
await context.sendActivity("To continue to run this bot, please fix the bot source code.");
}
};

// Create express application.
const expressApp = express();
expressApp.use(express.json());
expressApp.use(authorizeJWT(authConfig));

const port = process.env.port || process.env.PORT || 3978;
const server = expressApp.listen(port, () => {
console.log(
`Bot Started, listening to port ${port} for appId ${authConfig.clientId} debug ${process.env.DEBUG}`
);
});

// Listen for incoming requests.
expressApp.post("/api/messages", async (req, res) => {
await adapter.process(req, res, async (context) => {
await teamsBot.run(context);
});
});

// Gracefully shutdown HTTP server
["exit", "uncaughtException", "SIGINT", "SIGTERM", "SIGUSR1", "SIGUSR2"].forEach((event) => {
process.on(event, () => {
server.close();
});
});
const { startServer } = require("@microsoft/agents-hosting-express");
const { agentApp } = require("./agent");
startServer(agentApp);
2 changes: 1 addition & 1 deletion templates/vsc/js/default-bot/infra/azure.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ resource webApp 'Microsoft.Web/sites@2021-02-01' = {
}
{
name: 'WEBSITE_NODE_DEFAULT_VERSION'
value: '~18' // Set NodeJS version to 18.x for your site
value: '~22' // Set NodeJS version to 22.x for your site
}
{
name: 'RUNNING_ON_AZURE'
Expand Down
8 changes: 2 additions & 6 deletions templates/vsc/js/default-bot/package.json.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
"teamsAppId": null
},
"description": "Microsoft 365 Agents Toolkit echo bot sample",
"engines": {
"node": "18 || 20 || 22"
},
"author": "Microsoft",
"license": "MIT",
"main": "index.js",
Expand All @@ -21,11 +18,10 @@
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"@microsoft/agents-hosting": "^0.2.14",
"express": "^5.0.1"
"@microsoft/agents-hosting-express": "^1.0.0"
},
"devDependencies": {
"env-cmd": "^10.1.0",
"nodemon": "^3.1.7"
"nodemon": "^3.1.10"
}
}
2 changes: 1 addition & 1 deletion templates/vsc/js/weather-agent/infra/azure.bicep.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ resource webApp 'Microsoft.Web/sites@2021-02-01' = {
}
{
name: 'WEBSITE_NODE_DEFAULT_VERSION'
value: '~18' // Set NodeJS version to 18.x for your site
value: '~22' // Set NodeJS version to 22.x for your site
}
{
name: 'RUNNING_ON_AZURE'
Expand Down
9 changes: 2 additions & 7 deletions templates/vsc/js/weather-agent/package.json.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
"teamsAppId": null
},
"description": "Weather Agent with Microsoft 365 Agents SDK and LangChain",
"engines": {
"node": "18 || 20 || 22"
},
"author": "Microsoft",
"license": "MIT",
"main": "./src/index.js",
Expand All @@ -28,13 +25,11 @@
"@azure/openai": "^2.0.0",
"@langchain/langgraph": "^0.2.66",
"@langchain/openai": "^0.5.6",
"@microsoft/agents-hosting": "^0.2.14",
"express": "^5.0.1",
"zod": "3.25.67"
"@microsoft/agents-hosting-express": "^1.0.0"
},
"devDependencies": {
"env-cmd": "^10.1.0",
"nodemon": "^3.1.7",
"nodemon": "^3.1.10",
"shx": "^0.3.3"
},
"overrides": {
Expand Down
4 changes: 2 additions & 2 deletions templates/vsc/js/weather-agent/src/agent.js.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const { getWeatherTool } = require("./tools/getWeatherTool");

const weatherAgent = new AgentApplicationBuilder().build();

weatherAgent.conversationUpdate(
weatherAgent.onConversationUpdate(
"membersAdded",
async (context) => {
await context.sendActivity(
Expand Down Expand Up @@ -55,7 +55,7 @@ Respond in JSON format with the following JSON schema, and do not use markdown i
"content": "{The content of the response, may be plain text, or JSON based adaptive card}"
}`);

weatherAgent.activity(ActivityTypes.Message, async (context, state) => {
weatherAgent.onActivity(ActivityTypes.Message, async (context, state) => {
const llmResponse = await agent.invoke(
{
messages: [sysMessage, new HumanMessage(context.activity.text)],
Expand Down
32 changes: 3 additions & 29 deletions templates/vsc/js/weather-agent/src/index.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,3 @@
// Import required packages
const { authorizeJWT, CloudAdapter, loadAuthConfigFromEnv } = require("@microsoft/agents-hosting");
const express = require("express");

// This bot's main dialog.
const { weatherAgent } = require("./agent");

// Create authentication configuration
const authConfig = loadAuthConfigFromEnv();
const adapter = new CloudAdapter(authConfig);

// Create express application.
const server = express();
server.use(express.json());
server.use(authorizeJWT(authConfig));

// Listen for incoming requests.
server.post("/api/messages", async (req, res) => {
await adapter.process(req, res, async (context) => {
await weatherAgent.run(context);
});
});

const port = process.env.port || process.env.PORT || 3978;
server.listen(port, () => {
console.log(
`\nServer listening to port ${port} for appId ${authConfig.clientId} debug ${process.env.DEBUG}`
);
});
const { startServer } = require("@microsoft/agents-hosting-express");
const { agentApp } = require("./agent");
startServer(agentApp);
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ resource webApp 'Microsoft.Web/sites@2021-02-01' = {
}
{
name: 'WEBSITE_NODE_DEFAULT_VERSION'
value: '~18' // Set NodeJS version to 18.x for your site
value: '~22' // Set NodeJS version to 22.x for your site
}
{
name: 'RUNNING_ON_AZURE'
Expand Down
Loading