Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
[This article is prerelease documentation and is subject to change.]
Important
- You need to be part of the Frontier preview program to get early access to Microsoft 365 Copilot Cowork. Frontier connects you directly with Microsoft's latest AI innovations. Frontier previews are subject to the existing preview terms of your customer agreements. As these features are still in development, their availability and capabilities may change over time.
- If Cowork isn't visible in Microsoft Admin Center Agent management, ensure that the admin account is also enrolled in Frontier (Copilot -> Settings -> Frontier).
- This is a preview feature.
- Preview features may have restricted functionality. These features are available before an official release so that customers can get early access and provide feedback.
- For more information, go to our Microsoft Product Terms.
Microsoft 365 Copilot Cowork supports extensibility through M365 App Packages—the same distribution mechanism used by Teams apps, Copilot agents, and Office add-ins. You can extend Cowork with:
- Skills: Prompt-based workflows that teach Cowork new domain expertise, such as financial analysis, legal research, or HR workflows.
- Connectors: Remote servers that give Cowork access to external data sources and APIs.
Both are packaged together in a standard Microsoft 365 app package and distributed through the Microsoft 365 App Store.
What you'll build
A Cowork plugin is a .zip package containing:
my-extension.zip
├── manifest.json # M365 Unified App Manifest (devPreview)
├── color.png # 192×192 full-color app icon
├── outline.png # 32×32 outline icon
└── skills/ # Agent Skills (SKILL.md files)
├── skill-one/
│ ├── SKILL.md
│ └── references/ # Optional deep-dive docs
└── skill-two/
└── SKILL.md
Skills use the Agent Skills open standard-the same format supported by Claude Code, Visual Studio Code Copilot, Gemini CLI, Cursor, JetBrains Junie, and 30+ other AI tools.
Choose your starting point
| Starting point | Path | Time to first package |
|---|---|---|
| I have an existing Claude Code plugin | Convert it | ~5 minutes |
| I'm starting from scratch | Build from scratch | ~30 minutes |
Convert an existing Claude plugin
If you already have a Claude Code plugin with skills and MCP servers, the conversion script handles the translation:
.\Convert-ClaudePluginToMOS3.ps1 -PluginPath ./my-claude-plugin -OutputPath ./output
This script reads your plugin's .claude-plugin/plugin.json, .mcp.json, and skills/ directory, then produces a valid M365 .zip package with a generated manifest.json.
What gets converted
| Claude plugin artifact | M365 equivalent | Notes |
|---|---|---|
.claude-plugin/plugin.json |
manifest.json |
Name, description, and author mapped; GUID autogenerated (deterministic UUID v5) |
skills/*/SKILL.md |
agentSkills[] entries + skills/ folder |
Copied verbatim - identical format |
.mcp.json servers |
agentConnectors[] entries |
URL and auth type autodetected |
color.png / outline.png |
Icons in package | Used if present; placeholders generated if missing |
What's not converted
The following Claude plugin features aren't yet supported in the Microsoft 365 manifest:
| Claude plugin feature | Status |
|---|---|
commands/ (slash commands) |
Not yet supported |
agents/ (sub-agents) |
Not yet supported |
hooks/ (event handlers) |
Not yet supported |
settings.json |
Not applicable |
bin/ (executables) |
Not applicable |
Conversion script options
.\Convert-ClaudePluginToMOS3.ps1
-PluginPath <path> # Required: Claude plugin directory
-OutputPath <path> # Output directory (default: current)
-AppId <guid> # Override auto-generated GUID
-DefaultAuthType <type> # Auto | None | OAuthPluginVault | ApiKeyPluginVault
-DetailedOutput # Show step-by-step progress
Auth type autodetection:
| Source | Default auth type | Reason |
|---|---|---|
| External HTTPS URLs | OAuthPluginVault |
Most remote APIs need auth |
| Localhost or stdio | None |
Local servers don't need platform auth |
If the autodetection doesn't match your setup, use -DefaultAuthType to override it.
Build a plugin from scratch
Follow these steps to create a plugin package from the ground up, starting with your first skill and building up to a complete, publishable package.
Step 1: Create your first skill
A skill is a folder containing a SKILL.md file. Create the following folder structure:
my-extension/
└── skills/
└── contract-analysis/
└── SKILL.md
Write SKILL.md with YAML frontmatter and a Markdown body:
---
name: contract-analysis
description: |
Analyzes contracts for key terms, risks, and obligations.
Use when user asks to "review this contract", "find the liability clause",
"summarize the key terms", or "compare these two agreements".
license: MIT
metadata:
author: Contoso Legal Tech
version: "1.0"
---
# Contract Analysis
## What This Skill Does
Guides Cowork through systematic contract review, identifying:
- Key commercial terms (pricing, payment, renewal)
- Risk clauses (indemnification, limitation of liability, IP)
- Obligations and deadlines
- Non-standard or unusual provisions
## Workflow
1. Read the uploaded contract document
2. Extract and categorize all clauses
3. Flag risk areas with severity ratings
4. Generate a structured summary with recommendations
## Output Format
Present findings in a structured table:
| Clause | Category | Risk Level | Summary |
|--------|----------|------------|---------|
| Section 4.2-Indemnification | Risk | High | Unlimited indemnification for IP claims |
| Section 7.1-Term | Commercial | Low | 12-month auto-renewal with 30-day notice |
SKILL.md frontmatter fields
Required fields:
| Field | Constraints | Description |
|---|---|---|
name |
1-64 characters, kebab-case | Skill identifier-must match the folder name exactly |
description |
1-1024 characters | When to use this skill-include trigger phrases |
Optional fields:
| Field | Constraints | Description |
|---|---|---|
license |
Free-form string | License identifier (for example, MIT, Apache-2.0) |
compatibility |
1-500 characters | Platform compatibility notes |
metadata |
Map of string to string | Custom key-value pairs (author, version, and so on) |
allowed-tools |
Space-delimited list | Restrict which connector tools the skill can invoke (experimental) |
cowork.category |
Free-form string | Category label displayed in the skill list (for example, "Finance", "Legal") |
cowork.icon |
Fluent UI icon name, PascalCase | Icon displayed next to the skill name (for example, Briefcase, Gavel). Use the icon name without the variant suffix—the system adds the appropriate variant automatically. |
Important
The folder name must match the name field in the frontmatter. This mismatch is the most common cause of skill failures.
| Folder path | name field |
Valid? | Why |
|---|---|---|---|
skills/contract-analysis/SKILL.md |
contract-analysis |
Yes | Folder and name match |
skills/contract-analysis/SKILL.md |
ContractAnalysis |
No | Name uses PascalCase instead of matching folder |
skills/my-skill/SKILL.md |
contract-analysis |
No | Folder is my-skill but name is contract-analysis |
Naming rules (kebab-case): Use only lowercase alphanumeric characters and hyphens. Don't use consecutive hyphens, and don't use leading or trailing hyphens.
| Example | Valid? | Issue |
|---|---|---|
bond-relative-value |
Yes | Lowercase with hyphens |
fx-carry-trade |
Yes | Lowercase with hyphens |
email |
Yes | Single word, no hyphens needed |
Bond_Relative_Value |
No | Underscores and uppercase letters |
--my-skill-- |
No | Leading and trailing hyphens |
my--skill |
No | Consecutive hyphens |
Step 2: Add reference materials (optional)
For complex skills, keep the main SKILL.md lean and move detailed content to subdirectories. These additional files are called companion files and are loaded alongside the skill when needed.
skills/
└── contract-analysis/
├── SKILL.md # Core workflow (~1,500-2,000 words ideal)
├── references/ # Deep-dive docs loaded on demand
│ ├── clause-taxonomy.md
│ └── risk-scoring.md
└── scripts/ # Executable utilities
└── extract-clauses.py
Companion file limits
Each skill can include up to 20 companion files (any file other than SKILL.md). The following limits apply per skill:
| Limit | Value |
|---|---|
| Maximum companion files | 20 |
| Maximum size per companion file | 5 MB |
| Maximum total companion size | 10 MB |
| Download timeout (all companions) | 15 seconds |
Companion file rules
Companion file paths must follow these rules:
- Use relative paths only (no absolute paths)
- No path traversal (
..segments) - No backslashes or null bytes in file names
- No hidden files (names starting with
.) - No Windows reserved names (
CON,PRN,AUX,NUL,COM1–COM9,LPT1–LPT9) - The file
SKILL.mditself doesn't count as a companion file - File names must use safe characters: alphanumeric, hyphens, underscores, dots, spaces, and
!
To keep the context window efficient, the system loads skills in three layers:
| Layer | When loaded | Target size |
|---|---|---|
Frontmatter (name + description) |
Always - at startup | ~100 tokens |
SKILL.md body |
When skill triggers | Less than 5,000 tokens (1,500-2,000 words) |
References (references/) |
On demand by the agent | Unlimited |
Scripts (scripts/) |
Executed, not loaded into context | N/A |
Reference the subdirectories explicitly in SKILL.md so the agent knows they exist:
## Additional Resources
- **`references/clause-taxonomy.md`**-Full taxonomy of contract clause types
- **`references/risk-scoring.md`**-Risk scoring methodology and thresholds
- **`scripts/extract-clauses.py`**-Automated clause extraction utility
Step 3: Add a connector (optional)
If your extension needs access to external data, add a remote MCP server. This step is optional. Skills-only packages work well for prompt-based workflows.
Connector requirements
| Requirement | Details |
|---|---|
| Transport | Streamable HTTP (HTTPS required, TLS 1.2+) |
| Protocol | JSON-RPC 2.0 message format |
| Tool discovery | Support tools/list for dynamic discovery (recommended) |
| Tool execution | Support tools/call for invocation |
| Availability | 99.9% uptime SLA recommended for store-published apps |
| Response time | Less than 30 seconds per tool call |
Tool design guidelines
- One tool per action for small APIs (fewer than 15 operations):
search_case_law,get_ruling,cite_precedent - Search + execute for large APIs (50+ operations):
search_actions+execute_action - Descriptive names:
get_bond_pricenotgetData - Rich input schemas: Include a description for every parameter—this is what the agent reads
- Structured output: Return JSON that the agent can format for the user
Supported auth types
| Auth type | When to use | User experience |
|---|---|---|
None |
Public or anonymous APIs, internal services | Transparent - no auth prompt |
OAuthPluginVault |
OAuth 2.0 APIs (recommended for production) | User completes OAuth consent once |
ApiKeyPluginVault |
API key-based services | User provides key once |
DynamicClientRegistration |
RFC 7591 dynamic client registration | OAuth consent flow |
For OAuthPluginVault and ApiKeyPluginVault, the referenceId points to credentials stored in the Microsoft Enterprise Token Store - secrets never appear in the manifest or skill files.
Step 4: Create the manifest
Create manifest.json in your package root:
{
"$schema": "https://developer.microsoft.com/json-schemas/teams/vDevPreview/MicrosoftTeams.schema.json",
"manifestVersion": "devPreview",
"version": "1.0.0",
"id": "YOUR-GUID-HERE",
"packageName": "com.contoso.legal-tools",
"developer": {
"name": "Contoso Legal Tech",
"websiteUrl": "https://contoso.com",
"privacyUrl": "https://contoso.com/privacy",
"termsOfUseUrl": "https://contoso.com/terms"
},
"name": {
"short": "Contoso Legal Tools",
"full": "Contoso Legal Tools for Copilot Cowork"
},
"description": {
"short": "Contract analysis, clause extraction, and legal research",
"full": "Comprehensive legal tools for Copilot Cowork including contract analysis, clause extraction, risk assessment, and legal research capabilities."
},
"icons": {
"color": "color.png",
"outline": "outline.png"
},
"accentColor": "#2B579A",
"agentSkills": [
{ "folder": "./skills/contract-analysis" }
]
}
To add a connector, include agentConnectors:
{
"agentConnectors": [
{
"id": "contoso-legal-api",
"displayName": "Contoso Legal Database",
"description": "Access to case law, statutes, and regulatory databases",
"toolSource": {
"remoteMcpServer": {
"mcpServerUrl": "https://api.contoso.com/legal/mcp",
"authorization": {
"type": "OAuthPluginVault",
"referenceId": "contoso-legal-oauth"
}
}
}
}
]
}
Step 5: Add icons
Create two PNG icons:
| Icon | Size | Purpose |
|---|---|---|
color.png |
192×192 px | Full-color app icon shown in store and app list |
outline.png |
32×32 px | Single-color outline icon for compact views |
If you don't have icons yet, the conversion script generates solid-color placeholders. Replace them before store submission.
Step 6: Package
Create a ZIP file with all contents at the root level:
contoso-legal-tools.zip
├── manifest.json
├── color.png
├── outline.png
└── skills/
└── contract-analysis/
├── SKILL.md
└── references/
└── clause-taxonomy.md
Windows (PowerShell):
Compress-Archive -Path manifest.json, color.png, outline.png, skills -DestinationPath contoso-legal-tools.zip
macOS/Linux:
zip -r contoso-legal-tools.zip manifest.json color.png outline.png skills/
Step 7: Test
Sideload for testing:
- Open M365 Admin Center > Manage Apps > Upload custom app.
- Upload your
.zippackage. - Open Cowork > Sources & Skills-your skills should appear.
You can also sideload via API:
POST /users/titles
Content-Type: application/zip
Body: <your-package.zip>
Step 8: Publish
Submit to the Microsoft 365 App Store via Partner Center.
Packaging patterns
Choose the pattern that fits your extension:
Skills only (no connector)
Best for prompt-based workflows, document analysis, and writing assistance.
my-skills-pack.zip
├── manifest.json # agentSkills only, no agentConnectors
├── color.png
├── outline.png
└── skills/
├── skill-one/SKILL.md
└── skill-two/SKILL.md
Skills + remote connector
Best for data analysis, API integrations, and enterprise systems.
my-data-skills.zip
├── manifest.json # agentSkills + agentConnectors
├── color.png
├── outline.png
└── skills/
├── analysis-workflow/SKILL.md
└── reporting-workflow/SKILL.md
Connector only (no custom skills)
Use this option for data sources that Cowork's built-in skills can already use.
my-connector.zip
├── manifest.json # agentConnectors only, no agentSkills
├── color.png
└── outline.png
Converted Claude plugin
Use this option for existing Claude ecosystem plugins that target Cowork.
.\Convert-ClaudePluginToMOS3.ps1 -PluginPath ./claude-plugin -OutputPath ./output
Skill authoring best practices
Follow these guidelines to create skills that activate reliably and produce consistent results.
Write effective descriptions
The description field determines when the agent activates your skill. Be specific:
# Good-specific trigger phrases, concrete scenarios
description: |
Analyzes bond relative value using Z-spreads, ASW spreads, and butterfly analysis.
Use when user asks to "analyze bond spreads", "compare bonds",
"rich-cheap analysis", "relative value", or "Z-spread calculation".
# Bad-vague, no trigger phrases
description: Provides bond analytics capabilities.
Write effective workflows
- Be specific in the description. Include trigger phrases: "Use when user asks to..." This description is how the agent decides which skill to activate.
- Structure as a workflow. Number the steps. Each step should map to a concrete action (read a file, call a tool, generate output).
- Define output format. Show the exact table, list, or document structure users should expect. This definition improves consistency dramatically.
- Reference tools by name. If your skill depends on connector tools, name them explicitly: "Use the
search_case_lawtool to..." - Keep the main SKILL.md lean. Move detailed reference material to the
references/subdirectory. The skill body should be the workflow, not an encyclopedia.
Avoid common mistakes
- Don't embed secrets in
SKILL.mdfiles. UseagentConnectorswith auth for API credentials. - Don't duplicate built-in skills. Check the built-in skills list before building.
- Don't make skills too broad. "Do everything with legal documents" is worse than specific skills for "contract analysis", "clause extraction", and "legal research".
- Don't hardcode file paths or system commands. Skills should be portable across environments.
- Don't put everything in SKILL.md. If your body exceeds ~3,000 words, move detailed content to
references/.
Validation rules
When you submit your package, the platform validates it at multiple levels. Fix these errors before submission to avoid rejection.
Manifest-level validation
| Code | Rule | Severity |
|---|---|---|
| ASKILL-M001 | folder is required on each agentSkills entry |
Error |
| ASKILL-M002 | Max 20 items in agentSkills array |
Error |
| ASKILL-M003 | folder path max 256 characters |
Error |
Package-level validation
| Code | Rule | Common fix | Severity |
|---|---|---|---|
| ASKILL-P001 | Folder referenced in manifest exists in ZIP | Check your ZIP structure | Error |
| ASKILL-P002 | Folder contains a SKILL.md file |
Add missing SKILL.md |
Error |
| ASKILL-P003 | SKILL.md has valid YAML frontmatter between --- delimiters |
Fix YAML syntax | Error |
| ASKILL-P004 | Frontmatter includes name field |
Add name: to frontmatter |
Error |
| ASKILL-P005 | Frontmatter includes description field |
Add description: to frontmatter |
Error |
| ASKILL-P006 | name matches the folder name (last path segment) |
Rename folder or fix name: |
Error |
| ASKILL-P007 | name is kebab-case |
Use my-skill not MySkill or my_skill |
Error |
| ASKILL-P008 | No duplicate folder values in the array |
Remove duplicates | Error |
Connector validation
| Rule | Severity |
|---|---|
id, displayName, and toolSource required on each connector |
Error |
All connector id values unique within the manifest |
Error |
Exactly one of plugin, remoteMcpServer, or localMcpServer in toolSource |
Error |
mcpServerUrl must be a valid HTTPS URL |
Error |
authorization.referenceId required unless type is None |
Error |
authorization.referenceId must NOT be present when type is None |
Error |
Companion file validation
Companion files (reference materials, scripts, and other files alongside SKILL.md) are validated at upload and sync time:
| Rule | Severity |
|---|---|
Maximum 20 companion files per skill (excluding SKILL.md) |
Error |
| Each companion file must be 5 MB or smaller | Error |
| Total companion files must be 10 MB or smaller per skill | Error |
| File paths must be relative (no absolute paths) | Error |
No path traversal segments (..) |
Error |
| No backslashes or null bytes in file names | Error |
No hidden files (names starting with .) |
Error |
No Windows reserved names (CON, PRN, AUX, NUL, COM1–COM9, LPT1–LPT9) |
Error |
File names must use safe characters only (alphanumeric, hyphens, underscores, dots, spaces, !) |
Error |
Cross-platform compatibility
Skills use the Agent Skills open standard. The same SKILL.md files work across multiple AI tools:
| Platform | Compatibility |
|---|---|
| Claude Code | Full-same SKILL.md format |
| Claude.ai Projects | Full-skills can be uploaded as project files |
| VS Code / GitHub Copilot | Full-Agent Skills supported in agent mode |
| Gemini CLI | Full-Agent Skills supported |
| JetBrains Junie | Full-Agent Skills supported |
| OpenAI Codex | Full-Agent Skills supported |
| Cursor | Full-Agent Skills supported |
If you're developing skills for both Claude Code and Cowork, start with the Claude Code plugin structure - it's the superset:
my-plugin/
├── .claude-plugin/
│ └── plugin.json # Claude plugin manifest
├── skills/
│ ├── skill-one/
│ │ ├── SKILL.md # Works in both Claude Code AND M365
│ │ └── references/
│ └── skill-two/
│ └── SKILL.md
└── .mcp.json # MCP server config (optional)
Then convert to an M365 package when you're ready to publish to the Microsoft 365 App Store:
.\Convert-ClaudePluginToMOS3.ps1 -PluginPath ./my-plugin -OutputPath ./output
Common questions
Can I use skills from the M365 package in Claude Code too?
Yes. The skill folders contain standard Agent Skills. Copy them to .claude/skills/ in any Claude Code project, or structure your project as a Claude plugin first and use the conversion script for M365.
Do I need a remote connector?
No. Skills-only packages work well for prompt-based workflows. Connectors are only needed when your skill requires live data from an external system.
How are plugin skills different from built-in skills?
Plugin skills appear with source "package" in the API. They can't override built-in skills of the same name. Admin-deployed packages show isAdminDeployed: true.
Can IT admins control which plugins are available?
Yes. Standard M365 admin controls apply: tenant-level allow/block lists, admin-managed deployments, and compliance policies.
What happens if a plugin is revoked?
On the next sync cycle, the skills and connectors from that package are removed from the user's session. Active conversations aren't interrupted, but new sessions don't have the package's capabilities.
What's the maximum number of skills per package?
Twenty (20) skills (per ASKILL-M002). For connectors, the limit is 10 per package.
Can skills reference connector tools from the same package?
Yes, and they should. Name the tools explicitly in your SKILL.md workflow (for example, "Use the search_case_law tool to..."). The agent connects them at runtime.
How do I generate a deterministic GUID for my package?
The conversion script uses UUID v5 (SHA-1 based) from your plugin name. Running the conversion twice produces the same GUID. For manual packaging, use any GUID generator. Be sure to keep it stable across versions.