Skip to content

Commit 6be0d9b

Browse files
authored
Samples/node skill (#69)
* Add node-echo-skill sample with Docker support and configuration files * Add privacy documentation and update Docker configuration for node-echo-skill * Add Microsoft Graph client integration and user info retrieval to Echo Skill * Add user photo display and launch configuration for debugging in node-echo-skill * Rename echo-skill to node-echo-skill and fix privacy URL formatting in manifest * Add TypeScript checking and clean up user info retrieval function * Fix dependency version format for agents-bot-hosting in package.json * Update agents-bot-hosting dependency version in package.json * use public feed * configur debugger to stepinto TS files * Remove node-echo-skill files and add copilotstudio-skill structure
1 parent 8541c2f commit 6be0d9b

File tree

11 files changed

+229
-0
lines changed

11 files changed

+229
-0
lines changed

.vscode/launch.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
8+
{
9+
"type": "node",
10+
"request": "launch",
11+
"name": "Launch Program",
12+
"skipFiles": [
13+
"<node_internals>/**"
14+
],
15+
"program": "${workspaceFolder}/samples/skill/node-echo-skill/src/index.js",
16+
"outFiles": [ "${workspaceFolder}/samples/skill/node-echo-skill/node_modules/@microsoft/**/*.js" ]
17+
18+
}
19+
]
20+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules/
2+
dist/
3+
.env
4+
package-lock.json
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@microsoft:registry=https://pkgs.dev.azure.com/ConversationalAI/BotFramework/_packaging/SDK/npm/registry/
2+
package-lock=false
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": "Debug index",
9+
"program": "${workspaceFolder}/src/index.js",
10+
"request": "launch",
11+
"skipFiles": [
12+
"<node_internals>/**"
13+
],
14+
"type": "node",
15+
"envFile": "${workspaceFolder}/.env"
16+
},
17+
18+
]
19+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# copilotstudio-skill
2+
3+
This sample shows how to create an Agent that can be consumed from CopilotStudio as a skill.
4+
5+
## Prerequisites
6+
7+
- [Node.js](https://nodejs.org) version 20 or higher
8+
9+
```bash
10+
# determine node version
11+
node --version
12+
```
13+
14+
- Access to CopilotStudio to [create an Agent](https://learn.microsoft.com/en-us/microsoft-copilot-studio/fundamentals-get-started?tabs=web)
15+
16+
## Deploy in localhost
17+
18+
The first time you setup the agent to be consumed as a skill, you might want to do it in `localhost`, so you can debug and revisit the desired configuration before deploying to azure.
19+
To do so you can use the tool [Dev Tunnels](https://aka.ms/devtunnels) to expose an endpoint in your machine to the internet.
20+
21+
```bash
22+
devtunnel host -a -p 3978
23+
```
24+
25+
Take note of the tunnelUrl
26+
27+
1. Create an EntraID app registration, and save the authentication information in the `.env` file, following any of the [available options](https://microsoft.github.io/Agents/HowTo/azurebot-auth-for-js.html) for Single Tenant.
28+
1. Update the Home page URL in the app registration with the tunnel url.
29+
1. Update the manifest replacing the `{baseUrl}` with the `{tunnelUrl}` and `{clientId}` with the `{appId}` from EntraID
30+
1. - [Configure a skill](https://learn.microsoft.com/en-us/microsoft-copilot-studio/configuration-add-skills#configure-a-skill)
31+
1. In CopilotStudio navigate to the Agent settings, skills, and register the skill with the URL `{tunnelUrl}/manifest.json`
32+
1. In CopilotStudio navigate to the Agent topics, add a new trigger to invoke an action to call the skill
33+
34+
## Deploy in Azure
35+
36+
1. Deploy the express application to Azure, using AppService, AzureVMs or Azure Container Apps.
37+
1. Update the Home page URL in the app registration with the Azure service URL.
38+
1. Create an EntraID app registration, and configure the Azure instance following any of the [available options](https://microsoft.github.io/Agents/HowTo/azurebot-auth-for-js.html) for SingleTenant.
39+
1. - [Configure a skill](https://learn.microsoft.com/en-us/microsoft-copilot-studio/configuration-add-skills#configure-a-skill)
40+
1. In CopilotStudio navigate to the Agent settings, skills, and register the skill with the URL `{azureServiceUrl}/manifest.json`
41+
1. In CopilotStudio navigate to the Agent topics, add a new trigger to invoke an action to call the skill
42+
43+
44+
## Running this sample
45+
46+
1. Once the express app is running, in localhost or in Azure
47+
1. Use the CopilotStudio _Test your agent_ chat UI, and use the trigger defined to invoke the skill
48+
49+
# Helper Scripts
50+
51+
Replace Manifest Values
52+
53+
```ps
54+
$url='{tunnelUrl}'
55+
$clientId='{clientId}'
56+
(Get-Content public/manifest.template.json).Replace('{baseUrl}', $url).Replace('{clientId}', $clientId) | Set-Content public/manifest.json
57+
```
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "node-echo-skill",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"type": "module",
6+
"scripts": {
7+
"lint": "eslint src",
8+
"start": "node --env-file .env src/index.js"
9+
},
10+
"keywords": [],
11+
"author": "",
12+
"license": "ISC",
13+
"description": "",
14+
"dependencies": {
15+
"@microsoft/agents-bot-hosting": "0.1.20",
16+
"@microsoft/microsoft-graph-client": "^3.0.7",
17+
"express": "^5.0.1"
18+
},
19+
"devDependencies": {
20+
"globals": "^15.14.0"
21+
}
22+
}
27.7 KB
Loading
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"$schema": "https://schemas.botframework.com/schemas/skills/skill-manifest-2.0.0.json",
3+
"$id": "EchoSkill",
4+
"name": "Echo Skill",
5+
"version": "1.0",
6+
"description": "This is a sample echo skill",
7+
"publisherName": "Microsoft",
8+
"privacyUrl": "{baseUrl}/privacy.html",
9+
"copyright": "Copyright (c) Microsoft Corporation. All rights reserved.",
10+
"license": "",
11+
"iconUrl": "{baseUrl}/icon.png",
12+
"tags": [
13+
"sample",
14+
"skill"
15+
],
16+
"endpoints": [
17+
{
18+
"name": "default",
19+
"protocol": "BotFrameworkV3",
20+
"description": "Default endpoint for the bot",
21+
"endpointUrl": "https://{baseUrl}/api/messages",
22+
"msAppId": "{clientId}"
23+
}
24+
],
25+
"activities": {
26+
"message": {
27+
"type": "message",
28+
"description": "Echo messages from user"
29+
}
30+
}
31+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Privacy</title>
7+
</head>
8+
<body>
9+
<h1>Privacy Doc</h1>
10+
11+
<p>Privacy is important to us. We do not collect any personal information from you. We do not use cookies. We do not track you. We do not store any information about you.</p>
12+
</body>
13+
</html>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// @ts-check
2+
3+
import { ActivityHandler, MessageFactory, MsalTokenProvider } from '@microsoft/agents-bot-hosting'
4+
import { default as pjson } from '../node_modules/@microsoft/agents-bot-hosting/package.json' with { type: "json" }
5+
6+
export class EchoBot extends ActivityHandler {
7+
constructor() {
8+
super()
9+
this.onMessage(async (context, next) => {
10+
const text = context.activity.text
11+
const replyText = `Echo: ${ text }`
12+
await context.sendActivity(MessageFactory.text(replyText, replyText))
13+
if (text?.includes('version')) {
14+
await context.sendActivity(MessageFactory.text('Running on version ' + pjson.version, 'Running on version ' + pjson.version))
15+
}
16+
await next()
17+
});
18+
19+
this.onMembersAdded(async (context, next) => {
20+
const welcomeText = `Hello from echo bot, running on version ${ pjson.version }`
21+
const membersAdded = context.activity.membersAdded
22+
if (membersAdded) {
23+
for (let cnt = 0; cnt < membersAdded.length; ++cnt) {
24+
if (membersAdded[cnt].id !== context.activity.recipient?.id) {
25+
await context.sendActivity(MessageFactory.text(welcomeText, welcomeText))
26+
}
27+
}
28+
}
29+
await next()
30+
})
31+
}
32+
}

0 commit comments

Comments
 (0)