🐙

Visual Studio Code + Agent Toolkitを用いてM365 Copilotの宣言エージェントを作成する方法

に公開

Microsoft 365 Copilotにおける宣言型エージェントとは

一言でいうと、Copilotをユースケースに合わせてカスタマイズしたものになります。
例えば、社内の独自の用語について解説してほしい場合や、Copilot経由で外部のAPIを呼び出して出力してほしい場合などに、Copilotの操作性を活かしつつカスタマイズしたものを宣言型エージェントと呼びます。

従来のプログラミングとの違い

従来のプログラミング(命令型):if-then文やSwitch文などコーディングして設計・開発を行う
宣言型:自然言語で要件やルールを定義してシステムを開発

宣言型エージェントを開発する方法

  1. Copilot Studio
  2. Visual Studio Code + Agent Toolkit(拡張機能)

開発手法の選択

1. Copilot Studio

  • コーディング経験のないユーザーやローコード開発経験があるユーザー
  • 初めて宣言型エージェントを開発する場合、素早くカスタマイズしたい場合
  • Power Platformとの連携を重視する場合
    • Ex)PowerAutomateのフローを呼び出したい、SharePointにファイルを作成したい、Power Apps内に開発したエージェントを導入したい場合

2. Visual Studio Code + Agent Toolkit

  • コーディング経験があるユーザー
  • 複雑な業務ロジックの実装をしたい場合
  • 外部API連携が多い

開発手法の違い

項目 Copilot Studio Visual Studio Code + Agent Toolkit
対象ユーザー 非技術者 技術者
開発手法 チャット形式・GUIベースのローコード開発 コードベース(JSON,YAML,OpenAPI)
適用例 簡単な質疑応答 複雑な業務システム連携
学習コスト

Visual Studio Code + Agent Toolkitを使った開発について

宣言型エージェントを構成する3つの要素


※Microsoft様の資料より参照

開発手順:例)天気予報エージェント

概要:特定の地域の天気予報と営業活動に必要なアドバイスを出力するエージェント
使用したAPI:https://openweathermap.org/api

具体的な開発手順
  1. Visual Studio Codeのインストール
  2. Agent Toolkitのインストール
  3. プロジェクトの作成
  4. エージェントの仕様を記述する(Instructions,Knowledge Source)
  5. 利用可能なアクションを定義する(Actions)
  6. APIを記述する(Actions)

1.Visual Studio Codeのインストール

2.Agent ToolKitのインストール

  • Visual Studio Code内で「Agent Toookit」と検索

3.プロジェクトの作成

  • 「Agent Toolkit」内の「Create a New Agent/App」を選択
  • 「宣言型エージェント」を選択
  • プロジェクトの「ルートフォルダ」を選択
  • 「プロジェクト名」を入力

4.エージェントの仕様を記述する

appPackage/manifest.json:アプリケーションの基本設定を行うファイル
Microsoft Dveloper portalやアプリを公開するときに表示される項目を定義します。

{
  "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.19/MicrosoftTeams.schema.json",
  "manifestVersion": "1.19",
  "id": "${{TEAMS_APP_ID}}",
  "version": "1.0.0",
  "developer": {
    "name": "Teams App, Inc.",
    "websiteUrl": "https://www.example.com",
    "privacyUrl": "https://www.example.com/privacy",
    "termsOfUseUrl": "https://www.example.com/termsofuse"
  },
  "icons": {
    "color": "color.png",
    "outline": "outline.png"
  },
  "name": {
    "short": "Weather Agent",
    "full": "Weather Agent - 天気予報エージェント"
  },
  "description": {
    "short": "天気予報を提供するエージェントです。",
    "full": "天気予報と営業活動に関するアドバイスを提供するエージェントです。都市名や座標を指定して現在の天気情報を取得できます。"
  },
  "accentColor": "#FFFFFF",
  "copilotAgents": {
    "declarativeAgents": [
      {
        "id": "declarativeAgent",
        "file": "declarativeAgent.json"
      }
    ]
  },
  "permissions": [
    "identity",
    "messageTeamMembers"
  ]
}

  • 開発者情報
  • アイコン設定
  • アプリの説明文

appPackage/declarativeAgent.json:エージェントの基本設定を行うファイル

{
    "$schema": "https://developer.microsoft.com/json-schemas/copilot/declarative-agent/v1.3/schema.json",
    "version": "v1.3",
    "name": "Weather Agent",
    "description": "天気予報と営業活動におけるアドバイスを提供するエージェント - 都市名や座標を指定して現在の天気情報を取得できます。その情報を基に営業活動のアドバイスを出力します",
    "instructions": "$[file('instruction.txt')]",
    "conversation_starters": [
        {
          "text": "あなたはなにができるエージェントですか"
        },
        {
          "text": "東京にいくので天気予報と営業アドバイスをしてください"
        }
    ],
     "actions": [
    {
      "id": "weatherPlugin",
      "file": "ai-plugin.json"
    }
  ]
}
  • description: ​このdeclarative copilotが何をするcopilotなのかを定義する​
  • instructions: ​具体的に何をするのかを記述する​(システムプロンプト)
  • conversation_starters: ​この宣言型エージェントの利用方法(プロンプト例)を記述しておく(最大6件)​
  • actions: ​外部のデータにアクセスするためのアクションを定義したJSONファイルを指定する
  • capabilities: ​この宣言型エージェントが参照するナレッジや、アクション以外に利用可能な機能を定義する。
    • WebSearch - ナレッジとして参照するWebサイト​
    • OneDriveAndSharePoint - ナレッジとして参照するSharePointやOneDriveのURL​
    • GraphConnectors - ナレッジとして参照するGraphコネクタによりインデックスされたデータ(コネクタ名を指定)​
    • Dataverse - ナレッジとして参照するDataverse上のデータベース(テーブル名を指定)​
    • TeamsMessages - ナレッジとして参照するTeamsのチャネルの会話​
    • People - ナレッジとして参照するAAD上のユーザ​

appPackage/instruction.txt:システムプロンプトを定義するファイル

# 天気エージェント システムプロンプト
## 概要・役割
あなたは天気予報を提供する天気エージェントです。
ユーザーが都市名や座標を指定すると、その地域の現在の天気情報を取得して表示します。
温度、湿度、気圧、風速、風向き、視界、天気の状況などの詳細な情報を日本語で分かりやすく説明し、営業活動に役立つ実用的なアドバイスを提供してください。

## 利用可能な機能
- 都市名での現在天気取得(例:東京、大阪、Tokyo)
- 緯度・経度での現在天気取得
- 降水確率を含む詳細予報情報
- 摂氏・華氏・ケルビンでの温度表示
- 日本語・英語などでの天気説明

## 取得可能な天気情報
- 各時点の気温(現在・最低・最高・体感温度)
- 湿度・気圧・視界・風速・風向
- 降水確率(パーセンテージ)
- 天気状況と詳細説明

## 営業活動アドバイス機能
### 悪天候時のアドバイス
**雨・雪の場合**
- 傘の必要性(「傘を忘れずに持参してください」)
- 交通遅延の可能性(「電車の遅延に備えて早めの移動をお勧めします」)
- 服装注意(「靴や服が濡れる可能性があります」)

**強風の場合**
- 屋外での営業活動への影響(「風が強いため、屋外での商談は避けることをお勧めします」)
- 交通機関への影響(「強風により交通機関に影響が出る可能性があります」)

### 気温別アドバイス
- **暑い日(30℃以上)**:「熱中症対策として水分補給を心がけてください」「冷房の効いた場所での商談をお勧めします」
- **寒い日(5℃以下)**:「防寒対策をしっかりとしてください」「屋内での商談をお勧めします」
- **体感温度差大**:「実際の気温と体感温度に差があります。服装にご注意ください」

### その他の条件別アドバイス
- **視界不良時**:「視界が悪いため、移動時は十分注意してください」
- **高湿度(80%以上)**:「湿度が高いため、涼しい場所での商談をお勧めします」
- **低湿度(30%以下)**:「乾燥しているため、のどの保湿に気をつけてください」
- **快晴時**:「絶好の営業日和です!屋外での商談や移動に最適です」

## 出力形式
天気情報と営業活動のアドバイスは分かりやすく、営業活動に特化した実用性の高い内容で提供してください。

5.利用可能なアクションを定義する

appPackage/ai-plugin.json:エージェントで利用可能なアクションや機能を定義するファイル

{
  "$schema": "https://developer.microsoft.com/json-schemas/copilot/plugin/v2.1/schema.json",
  "schema_version": "v2.1",
  "namespace": "weather",
  "name_for_human": "Weather Agent",
  "description_for_human": "あらゆる場所の天気情報を入手",
  "description_for_model": "都市名または座標で現在の天気情報を取得するためのプラグイン。さまざまな単位と言語をサポートしています。",
  "functions": [ 
    {
  "name": "getCurrentWeather",
  "description": "指定された都市名や座標の現在の天気情報を取得します。温度、湿度、気圧、風速、天気の状況などの詳細情報を提供します。",
  "capabilities": {
    "response_semantics": {
      "data_path": "$",
      "properties": {
        "title": "$.location.name",
        "subtitle": "$.current.weather.description"
      }
    }
  }
}
  ],
  "runtimes": [
    {
      "type": "OpenApi",
      "auth": {
        "type": "None"
      },
      "spec": {
        "url": "apiSpecificationFile/weather.yml"
      },
      "run_for_functions": [
        "getCurrentWeather"
      ]
    }
  ],
  "capabilities": {
    "localization": {},
    "conversation_starters": []
  }
}

6.APIを記述する(Open API形式)

appPackage/apiSpecificationFile/weather.yml:宣言型エージェントがどのようにAPIと連携するかを定義するファイル。先ほど定義したアクションを具体的にどのように使うのかが書かれています。

openapi: 3.0.0
info:
  title: Weather API
  version: 1.0.0
  description: OpenWeatherMap を使用して現在の天気情報を取得するためのAPI.
servers:
  - url: ${{OPENAPI_SERVER_URL}}/api
    description: Weather API server
paths:
  /weather:
    get:
      operationId: getCurrentWeather
      summary: 現在の天気予報を取得する
      description: 都市名または座標で特定の場所の現在の天気データを取得します
      parameters:
        - in: query
          name: city
          schema:
            type: string
          description: 天気情報を取得するための都市名(例:"Tokyo"、"Tokyo,JP")
        - in: query
          name: q
          schema:
            type: string
          description: 都市名クエリの代替パラメータ名。 
        - in: query
          name: lat
          schema:
            type: number
            format: float
          description: Latitude coordinate (use with lon parameter).
        - in: query
          name: lon
          schema:
            type: number
            format: float
          description: Longitude coordinate (use with lat parameter).
        - in: query
          name: units
          schema:
            type: string
            enum: [metric, imperial, kelvin]
            default: metric
          description: Temperature unit. metric=Celsius, imperial=Fahrenheit, kelvin=Kelvin.
        - in: query
          name: lang
          schema:
            type: string
            default: ja
          description: Language for weather description (ja, en, etc.).
      responses:
        '200':
          description: Current weather information.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WeatherData'
        '400':
          description: Invalid request parameters.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: Error message describing the issue.
        '404':
          description: Location not found.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: Error message indicating location not found.
        '500':
          description: Internal server error.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: Error message describing server issue.

components:
  schemas:
    WeatherData:
      type: object
      properties:
        location:
          type: object
          properties:
            name:
              type: string
              description: City name
            country:
              type: string
              description: Country code
            lat:
              type: number
              format: float
              description: Latitude
            lon:
              type: number
              format: float
              description: Longitude
        current:
          type: object
          properties:
            temp:
              type: number
              description: Current temperature
            feels_like:
              type: number
              description: Temperature it feels like
            humidity:
              type: integer
              description: Humidity percentage
            pressure:
              type: integer
              description: Atmospheric pressure in hPa
            visibility:
              type: number
              description: Visibility in kilometers
            uv_index:
              type: number
              description: UV index
            wind_speed:
              type: number
              description: Wind speed in m/s
            wind_direction:
              type: number
              description: Wind direction in degrees
            weather:
              type: object
              properties:
                main:
                  type: string
                  description: Main weather condition (e.g., Rain, Snow, Clear)
                description:
                  type: string
                  description: Weather condition description
                icon:
                  type: string
                  description: Weather icon code
        business_advice:
          type: object
          description: Business activity advice based on weather conditions
          properties:
            umbrella_needed:
              type: boolean
              description: Whether an umbrella is needed
            recommendations:
              type: array
              items:
                type: string
              description: List of recommendations for business activities
            outfit_advice:
              type: string
              description: Clothing and outfit recommendations
            travel_warnings:
              type: array
              items:
                type: string
              description: Travel-related warnings and precautions
  • API情報: タイトル、バージョン、説明など基本情報
  • サーバー情報: APIサーバーのURL情報
  • パス定義: 各APIエンドポイントのパスとHTTPメソッド(GET、POST等)
  • 操作定義: 各エンドポイントでできる操作(operationId)
  • パラメータ定義: リクエストで受け付けるパラメータ
  • レスポンス定義: 戻り値の形式や内容(成功時とエラー時)
  • スキーマ定義: データモデルの構造定義

天気予報エージェントの実際の画面

まとめ

宣言型エージェントの利点としては、Microsoft 365 CopilotのUIを活かしつつ、自分たち専用のカスマイズができる点と、自然言語で開発をするため直感的に開発を進めることができる点だと思います。ただ、柔軟性が高すぎるためどのようなエージェントを開発しようか迷うことは多いかと個人的に思いました。
今後もCopilotに関する知見を広げていけたらと思います。
最後まで読んでいただきありがとうございました。

参考文献

https://learn.microsoft.com/en-us/microsoft-365-copilot/extensibility/overview-declarative-agent
https://learn.microsoft.com/en-us/training/modules/copilot-declarative-agent-action-api-plugin-vsc/
https://learn.microsoft.com/ja-jp/microsoft-365-copilot/extensibility/build-declarative-agents
https://blog.jbs.co.jp/entry/2024/12/11/085541
https://zenn.dev/mizu4ma/articles/3c29f05ab82739

ヘッドウォータース

Discussion