Build plugins for Cowork (Frontier)

[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, COM1COM9, LPT1LPT9)
  • The file SKILL.md itself 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_price not getData
  • 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:

  1. Open M365 Admin Center > Manage Apps > Upload custom app.
  2. Upload your .zip package.
  3. 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_law tool 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.md files. Use agentConnectors with 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, COM1COM9, LPT1LPT9) 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.