Typespec API Operations
GitHubOfficialOriginally contributed by @troystaylor as prompts/typespec-api-operations.prompt.md; moved into a skill by pull request #761Distributed by GitHub
- Skill
- Tool integration
- Software development
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a comprehensive reference for defining CRUD operations (GET, POST, PATCH, DELETE) in TypeSpec. It covers essential configurations for routing, parameter handling, error responses, and the integration of Adaptive Cards for rich UI interactions within Microsoft 365 Copilot. The guide also includes best practices for model definitions, documentation, and user confirmation flows for destructive actions.
What it does
- Defines RESTful API operations using TypeSpec decorators.
- Configures query, path, and body parameters for API endpoints.
- Integrates Adaptive Cards for visual data representation and user interaction.
- Implements confirmation dialogs for POST, PATCH, and DELETE operations.
- Structures service namespaces and data models for API consistency.
- Provides patterns for handling error responses and custom response models.
When to use it
- When building or extending a Microsoft 365 Copilot plugin using TypeSpec.
- When you need to map API endpoints to specific user-facing actions.
- When you want to display API data using custom Adaptive Cards.
- When implementing safety confirmations for destructive API operations.
- When standardizing API request and response models.
Advantages
- Ensures consistent RESTful routing conventions.
- Enhances user experience through integrated Adaptive Card visualizations.
- Reduces errors by implementing mandatory confirmation flows for destructive actions.
- Promotes clean code through reusable model definitions and decorators.
Usage examples
- “How do I define a GET operation with a query parameter in TypeSpec?”
- The agent provides the syntax using the @get decorator and @query parameter, showing how to filter results by an optional ID.
- “Show me how to add a confirmation dialog to a DELETE operation.”
- The agent provides a code snippet using the @capabilities decorator with a confirmation object containing a warning message.
- “How can I link an Adaptive Card to my API list operation?”
- The agent demonstrates the use of the @card decorator, specifying the data path and the path to the JSON file defining the card layout.
- “What is the best way to define a PATCH operation for updating an item?”
- The agent provides a template for a PATCH operation including path parameters for the ID and a model for the update request.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/github/typespec-api-operations/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip typespec-api-operations.zip -d .agents/skills
Documentation by troystaylor
Add TypeSpec API Operations
Add RESTful operations to an existing TypeSpec API plugin for Microsoft 365 Copilot.
Adding GET Operations
Simple GET - List All Items
/**
* List all items.
*/
@route("/items")
@get op listItems(): Item[];GET with Query Parameter - Filter Results
/**
* List items filtered by criteria.
* @param userId Optional user ID to filter items
*/
@route("/items")
@get op listItems(@query userId?: integer): Item[];GET with Path Parameter - Get Single Item
/**
* 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;GET with Adaptive Card
/**
* List items with adaptive card visualization.
*/
@route("/items")
@card(#{
dataPath: "$",
title: "$.title",
file: "item-card.json"
})
@get op listItems(): Item[];Create the 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}"
}
]
}Adding POST Operations
Simple POST - Create Item
/**
* 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 with Confirmation
/**
* 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;Adding PATCH Operations
Simple PATCH - Update Item
/**
* 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 with Confirmation
/**
* 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;Adding DELETE Operations
Simple DELETE
/**
* Delete an item.
* @param id The ID of the item to delete
*/
@route("/items/{id}")
@delete op deleteItem(@path id: integer): void;DELETE with Confirmation
/**
* 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;Complete CRUD Example
Define the Service and Models
@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;
}Advanced Features
Multiple Query Parameters
@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;
}Header Parameters
@route("/items")
@get op listItems(
@header("X-API-Version") apiVersion?: string,
@query userId?: integer
): Item[];Custom Response Models
@route("/items/{id}")
@delete op deleteItem(@path id: integer): DeleteResponse;
model DeleteResponse {
success: boolean;
message: string;
deletedId: integer;
}Error Responses
model ErrorResponse {
error: {
code: string;
message: string;
details?: string[];
};
}
@route("/items/{id}")
@get op getItem(@path id: integer): Item | ErrorResponse;Testing Prompts
After adding operations, test with these prompts:
GET Operations:
"List all items and show them in a table"
"Show me items for user ID 1"
"Get the details of item 42"
POST Operations:
"Create a new item with title 'My Task' for user 1"
"Add an item: title 'New Feature', description 'Add login'"
PATCH Operations:
"Update item 10 with title 'Updated Title'"
"Change the status of item 5 to completed"
DELETE Operations:
"Delete item 99"
"Remove the item with ID 15"
Best Practices
Parameter Naming
Use descriptive parameter names:
userIdnotuidBe consistent across operations
Use optional parameters (
?) for filters
Documentation
Add JSDoc comments to all operations
Describe what each parameter does
Document expected responses
Models
Use
@visibility(Lifecycle.Read)for read-only fields likeidUse
@format("date-time")for date fieldsUse union types for enums:
"active" | "completed"Make optional fields explicit with
?
Confirmations
Always add confirmations to destructive operations (DELETE, PATCH)
Show key details in confirmation body
Use warning emoji (⚠️) for irreversible actions
Adaptive Cards
Keep cards simple and focused
Use conditional rendering with
${if(..., ..., 'N/A')}Include action buttons for common next steps
Test data binding with actual API responses
Routing
Use RESTful conventions:
GET /items- ListGET /items/{id}- Get onePOST /items- CreatePATCH /items/{id}- UpdateDELETE /items/{id}- Delete
Group related operations in the same namespace
Use nested routes for hierarchical resources
Common Issues
Issue: Parameter not showing in Copilot
Solution: Check parameter is properly decorated with @query, @path, or @body
Issue: Adaptive card not rendering
Solution: Verify file path in @card decorator and check JSON syntax
Issue: Confirmation not appearing
Solution: Ensure @capabilities decorator is properly formatted with confirmation object
Issue: Model property not appearing in response
Solution: Check if property needs @visibility(Lifecycle.Read) or remove it if it should be writable
Files
- ATTRIBUTION.mdAdded by AutoGineer1.1 KiB
- LICENSELicence file added by AutoGineer1.0 KiB
- SKILL.md8.9 KiB
ATTRIBUTION.md
Attribution
This folder is an unmodified copy of the Agent Skill "typespec-api-operations", distributed by AutoGineer (https://autogineer.com/agent-skills).
Commit: 797337f33f73e35d08d82f840e21c4b8c4932d88
Originally contributed by: @troystaylor (https://github.com/troystaylor) as prompts/typespec-api-operations.prompt.md (history: https://github.com/github/awesome-copilot/commits/9efb8cd3885ad3a445e11de2b6cc7ab3abcbdef6/prompts/typespec-api-operations.prompt.md); moved into a skill by pull request #761 (https://github.com/github/awesome-copilot/pull/761)
Publisher: GitHub (https://github.com/github)
Licence: MIT License (https://github.com/github/awesome-copilot/blob/797337f33f73e35d08d82f840e21c4b8c4932d88/LICENSE)
Licence evidence: repository licence LICENSE
Retrieved: 2026-11-07
The skill's own files are unmodified copies. AutoGineer is not affiliated with or endorsed by the author or the publisher.
Files added by AutoGineer
ATTRIBUTION.md: this file, written by AutoGineer
LICENSE: copied from LICENSE
Requirements and compatibility
Written for: GitHub Copilot
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Originally contributed by
@troystayloras prompts/typespec-api-operations.prompt.mdmoved into a skill by pull request #761
- Publisher
- GitHub (Official)
- Distributed by
- GitHub
- Source
- github/awesome-copilot · skills/typespec-api-operations · commit 797337f
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Contributors
- troystaylor
AutoGineer is not affiliated with or endorsed by troystaylor or GitHub.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download typespec-api-operations.zip