typespec-api-operations について
typespec-api-operationsは、Microsoft 365 Copilot向けの既存TypeSpec APIプラグインにREST操作を追加するスキルです。CRUDの例、パラメーター、確認、アダプティブカード、テスト用プロンプトを扱います。
主な機能
- 01GET、POST、PATCH、DELETEの例
- 02パス、クエリ、ボディ、ヘッダーのパラメーター
- 03確認とアダプティブカードのパターン
- 04レスポンスモデルとエラーレスポンス
- 05ルーティングとドキュメントの指針
活用シーン
- 01TypeSpec APIへのCRUD操作の追加
- 02フィルターと項目識別子の定義
- 03破壊的な操作への確認の追加
- 04プロンプトによるCopilot API操作の確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ github/ awesome-copilot --skill typespec-api-operationsインストール後、Claude Code で/typespec-api-operationsを入力して読み込まれたか確認します。
詳細
TypeSpec API 操作の追加
Microsoft 365 Copilot 用の既存の TypeSpec API プラグインに RESTful 操作を追加します。
GET 操作の追加
シンプルな GET - すべての項目を一覧表示
/**
* List all items.
*/
@route("/items")
@get op listItems(): Item[];
クエリパラメーター付き GET - 結果を絞り込む
/**
* List items filtered by criteria.
* @param userId Optional user ID to filter items
*/
@route("/items")
@get op listItems(@query userId?: integer): Item[];
パスパラメーター付き GET - 単一の項目を取得
/**
* Get a specific item by ID.
* @param id The ID of the item to retrieve
*/
@route("/items/{id}")
@get op getItem(@path id: integer): Item;
Adaptive Card 付き GET
/**
* List items with adaptive card visualization.
*/
@route("/items")
@card(#{
dataPath: "$",
title: "$.title",
file: "item-card.json"
})
@get op listItems(): Item[];
Adaptive Card を作成します (appPackage/item-card.json):
{
"type": "AdaptiveCard",
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.5",
"body": [
{
"type": "Container",
"$data": "${$root}",
"items": [
{
"type": "TextBlock",
"text": "**${if(title, title, 'N/A')}**",
"wrap": true
},
{
"type": "TextBlock",
"text": "${if(description, description, 'N/A')}",
"wrap": true
}
]
}
],
"actions": [
{
"type": "Action.OpenUrl",
"title": "View Details",
"url": "https://example.com/items/${id}"
}
]
}
POST 操作の追加
シンプルな POST - 項目を作成
/**
* Create a new item.
* @param item The item to create
*/
@route("/items")
@post op createItem(@body item: CreateItemRequest): Item;
model CreateItemRequest {
title: string;
description?: string;
userId: integer;
}
確認付き POST
/**
* Create a new item with confirmation.
*/
@route("/items")
@post
@capabilities(#{
confirmation: #{
type: "AdaptiveCard",
title: "Create Item",
body: """
Are you sure you want to create this item?
* **Title**: {{ function.parameters.item.title }}
* **User ID**: {{ function.parameters.item.userId }}
"""
}
})
op createItem(@body item: CreateItemRequest): Item;
PATCH 操作の追加
シンプルな PATCH - 項目を更新
/**
* Update an existing item.
* @param id The ID of the item to update
* @param item The updated item data
*/
@route("/items/{id}")
@patch op updateItem(
@path id: integer,
@body item: UpdateItemRequest
): Item;
model UpdateItemRequest {
title?: string;
description?: string;
status?: "active" | "completed" | "archived";
}
確認付き PATCH
/**
* Update an item with confirmation.
*/
@route("/items/{id}")
@patch
@capabilities(#{
confirmation: #{
type: "AdaptiveCard",
title: "Update Item",
body: """
Updating item #{{ function.parameters.id }}:
* **Title**: {{ function.parameters.item.title }}
* **Status**: {{ function.parameters.item.status }}
"""
}
})
op updateItem(
@path id: integer,
@body item: UpdateItemRequest
): Item;
DELETE 操作の追加
シンプルな DELETE
/**
* Delete an item.
* @param id The ID of the item to delete
*/
@route("/items/{id}")
@delete op deleteItem(@path id: integer): void;
確認付き DELETE
/**
* Delete an item with confirmation.
*/
@route("/items/{id}")
@delete
@capabilities(#{
confirmation: #{
type: "AdaptiveCard",
title: "Delete Item",
body: """
⚠️ Are you sure you want to delete item #{{ function.parameters.id }}?
This action cannot be undone.
"""
}
})
op deleteItem(@path id: integer): void;
完全な CRUD の例
サービスとモデルを定義する
@service
@server("https://api.example.com")
@actions(#{
nameForHuman: "Items API",
descriptionForHuman: "Manage items",
descriptionForModel: "Read, create, update, and delete items"
})
namespace ItemsAPI {
// Models
model Item {
@visibility(Lifecycle.Read)
id: integer;
userId: integer;
title: string;
description?: string;
status: "active" | "completed" | "archived";
@format("date-time")
createdAt: utcDateTime;
@format("date-time")
updatedAt?: utcDateTime;
}
model CreateItemRequest {
userId: integer;
title: string;
description?: string;
}
model UpdateItemRequest {
title?: string;
description?: string;
status?: "active" | "completed" | "archived";
}
// Operations
@route("/items")
@card(#{ dataPath: "$", title: "$.title", file: "item-card.json" })
@get op listItems(@query userId?: integer): Item[];
@route("/items/{id}")
@card(#{ dataPath: "$", title: "$.title", file: "item-card.json" })
@get op getItem(@path id: integer): Item;
@route("/items")
@post
@capabilities(#{
confirmation: #{
type: "AdaptiveCard",
title: "Create Item",
body: "Creating: **{{ function.parameters.item.title }}**"
}
})
op createItem(@body item: CreateItemRequest): Item;
@route("/items/{id}")
@patch
@capabilities(#{
confirmation: #{
type: "AdaptiveCard",
title: "Update Item",
body: "Updating item #{{ function.parameters.id }}"
}
})
op updateItem(@path id: integer, @body item: UpdateItemRequest): Item;
@route("/items/{id}")
@delete
@capabilities(#{
confirmation: #{
type: "AdaptiveCard",
title: "Delete Item",
body: "⚠️ Delete item #{{ function.parameters.id }}?"
}
})
op deleteItem(@path id: integer): void;
}
高度な機能
複数のクエリパラメーター
@route("/items")
@get op listItems(
@query userId?: integer,
@query status?: "active" | "completed" | "archived",
@query limit?: integer,
@query offset?: integer
): ItemList;
model ItemList {
items: Item[];
total: integer;
hasMore: boolean;
}
ヘッダーパラメーター
@route("/items")
@get op listItems(
@header("X-API-Version") apiVersion?: string,
@query userId?: integer
): Item[];
カスタム応答モデル
@route("/items/{id}")
@delete op deleteItem(@path id: integer): DeleteResponse;
model DeleteResponse {
success: boolean;
message: string;
deletedId: integer;
}
エラー応答
model ErrorResponse {
error: {
code: string;
message: string;
details?: string[];
};
}
@route("/items/{id}")
@get op getItem(@path id: integer): Item | ErrorResponse;
プロンプトのテスト
操作を追加したら、以下のプロンプトでテストします:
GET 操作:
- 「すべての項目を一覧表示して表で示して」
- 「ユーザー ID 1 の項目を見せて」
- 「項目 42 の詳細を取得して」
POST 操作:
- 「ユーザー 1 にタイトル『My Task』の新しい項目を作成して」
- 「項目を追加して: タイトル『New Feature』、説明『Add login』」
PATCH 操作:
- 「項目 10 をタイトル『Updated Title』で更新して」
- 「項目 5 のステータスを完了に変更して」
DELETE 操作:
- 「項目 99 を削除して」
- 「ID 15 の項目を削除して」
ベストプラクティス
パラメーターの命名
- 説明的なパラメーター名を使用する:
uidではなくuserId - 操作間で一貫性を保つ
- フィルターにはオプションのパラメーター (
?) を使用する
ドキュメント
- すべての操作に JSDoc コメントを追加する
- 各パラメーターの役割を説明する
- 想定される応答を記述する
モデル
idのような読み取り専用フィールドには@visibility(Lifecycle.Read)を使用する- 日付フィールドには
@format("date-time")を使用する - 列挙型にはユニオン型を使用する:
"active" | "completed" - オプションのフィールドは
?で明示する
確認
- 破壊的な操作 (DELETE、PATCH) には必ず確認を追加する
- 確認本文に重要な詳細を表示する
- 取り消せない操作には警告絵文字 (⚠️) を使用する
Adaptive Card
- カードはシンプルかつ焦点を絞ったものにする
${if(..., ..., 'N/A')}による条件付きレンダリングを使用する- 一般的な次のステップにはアクションボタンを含める
- 実際の API 応答でデータバインディングをテストする
ルーティング
- RESTful の慣例に従う:
GET /items- 一覧表示GET /items/{id}- 1 件取得POST /items- 作成PATCH /items/{id}- 更新DELETE /items/{id}- 削除
- 関連する操作は同じ名前空間にグループ化する
- 階層的なリソースにはネストされたルートを使用する
よくある問題
問題: パラメーターが Copilot に表示されない
解決策: パラメーターが @query、@path、または @body で適切にデコレートされているか確認します
問題: Adaptive Card がレンダリングされない
解決策: @card デコレーターのファイルパスを確認し、JSON 構文をチェックします
問題: 確認が表示されない
解決策: @capabilities デコレーターが confirmation オブジェクトで適切にフォーマットされているか確認します
問題: モデルのプロパティが応答に表示されない
解決策: そのプロパティに @visibility(Lifecycle.Read) が必要か確認するか、書き込み可能であるべき場合は削除します
コメント
Markdown 対応