How to Create and Publish Custom OpenWork Skills to the Marketplace
OpenWork skills are first-class resources defined in SKILL.md files and published through built-in remote capabilities that create plugins on OpenWork Cloud, attach them to marketplaces, and optionally share access with specific users or teams.
OpenWork provides a structured workflow for turning ideas into reusable agent capabilities. This guide walks through the complete lifecycle—from drafting a SKILL.md to publishing on the marketplace—using the built-in remote skills defined in ee/apps/den-api/src/mcp/builtin-skills.ts.
The Four-Step OpenWork Skill Lifecycle
Creating and publishing a custom OpenWork skill follows a predictable path. Each step maps to a specific built-in capability.
| Step | Built-in skill | What it does |
|---|---|---|
| 1. Draft | skill:create-skill |
Validates and creates a plugin containing your SKILL.md |
| 2. Create | skill:create-skill |
Instantiates the plugin on OpenWork Cloud (instantly usable by creator) |
| 3. Publish | skill:add-to-marketplace |
Attaches the plugin to a marketplace catalog |
| 4. Share | skill:share-plugin |
Grants scoped access to people, teams, or organizations |
Step 1: Draft Your Skill in SKILL.md
Every OpenWork skill starts with a front-matter block followed by execution instructions. The create-skill capability validates this structure before accepting the payload.
Required SKILL.md Structure
---
name: weather-alert # kebab-case, unique within org
description: |
Generate a concise weather alert for a given city.
---
# Weather Alert
Given a city name, fetch the current weather from a public API and return a short
summary in plain English. Use the following steps:
1. Call `fetch("https://api.weatherapi.com/v1/current.json?key=...&q={city}")`.
2. Parse the JSON and extract `temp_c`, `condition.text`.
3. Respond with: "`{city}` is currently `{temp_c}°C` with `{condition}`."
The name field becomes the skill's identifier. The description determines when the agent suggests this skill. The body contains the full execution logic the agent follows when invoked.
As implemented in different-ai/openwork, the CREATE_SKILL_SOURCE constant in builtin-skills.ts enforces that both front-matter and body are non-empty.
Step 2: Create the Skill on OpenWork Cloud
The create-skill capability transforms your SKILL.md into a plugin with a skill component. This is a remote-only operation—no local files are created unless explicitly requested.
API Flow (from builtin-skills.ts)
POST /v1/plugins
{
"name": "My Awesome Plugin",
"components": [
{ "type": "skill", "input": { "rawSourceText": "<SKILL.md content>" } }
]
}
On success, the call returns a pluginId. The capability then verifies creation:
GET /v1/pluginsResolved/{pluginId}
If the plugin already exists (409 duplicate_plugin), the skill offers to update via postConfigObjectsVersions rather than failing.
Step 3: Publish to the OpenWork Marketplace
Once created, your skill exists as a private plugin. To make it discoverable, use skill:add-to-marketplace.
Marketplace Attachment Process
The add-to-marketplace capability performs these operations:
// 1. Discover available marketplaces
const markets = await openworkCloudExecuteCapability({
capability: "getMarketplaces"
});
// 2. Select target and attach plugin
await openworkCloudExecuteCapability({
capability: "skill:add-to-marketplace",
pathParams: [targetMarketplaceId],
body: { pluginId: "<pluginId>" }
});
// 3. Verify attachment
GET /v1/marketplacesResolved/{marketplaceId}
This step does not create a new skill—it adds the existing plugin to a marketplace catalog you own or administer.
Step 4: (Optional) Scope Access with share-plugin
By default, only the creator can use a skill. To grant access without publishing broadly, use skill:share-plugin.
Sharing Configuration
await openworkCloudExecuteCapability({
capability: "skill:share-plugin",
body: {
pluginId: "<pluginId>",
orgMembershipId: "om_9876", // resolved via getOrg
role: "viewer" // or "admin"
}
});
The capability validates recipients through getOrg before granting access. Valid targets include:
- Individual users
- Teams
- Entire organizations
Complete Publishing Example
Here's the full workflow from SKILL.md draft to marketplace publication:
// Step 1-2: Create skill from markdown source
const skillMd = `---
name: changelog-generator
description: |
Generate a formatted changelog from Git commits since last tag.
---
# Changelog Generator
1. Run \`git describe --tags --abbrev=0\` to find last tag.
2. Run \`git log {lastTag}..HEAD --oneline\`.
3. Group commits by type (feat, fix, docs).
4. Output Markdown changelog.`;
const createResult = await openworkCloudExecuteCapability({
capability: "skill:create-skill",
body: { rawSourceText: skillMd }
});
// Step 3: Publish to marketplace
await openworkCloudExecuteCapability({
capability: "skill:add-to-marketplace",
pathParams: ["mp_acme_public"],
body: { pluginId: createResult.pluginId }
});
// Step 4: Share with engineering team
await openworkCloudExecuteCapability({
capability: "skill:share-plugin",
body: {
pluginId: createResult.pluginId,
orgMembershipId: "om_eng_team",
role: "viewer"
}
});
Key Implementation Files
Understanding these source locations helps debug and extend the OpenWork skill system:
| File Path | Purpose |
|---|---|
ee/apps/den-api/src/mcp/builtin-skills.ts |
Defines create-skill, add-to-marketplace, add-user-to-marketplace, and share-plugin with their capability schemas |
ee/apps/den-api/src/mcp/agent.ts |
Shows how the agent discovers and executes built-in remote skills |
AGENTS.md (.opencode/skills/prd-conventions/SKILL.md section) |
Documents the SKILL.md file format expected by create-skill |
Summary
- Skills are resources, not standalone code—define them in
SKILL.mdwith front-matter and execution body - Creation is remote via
skill:create-skill, which wraps your markdown in a plugin component - Publishing is attachment via
skill:add-to-marketplace, adding an existing plugin to a catalog - Sharing is granular via
skill:share-plugin, controlling access without marketplace exposure - All capabilities are discoverable through the OpenWork skill index and executed by the agent against OpenWork Cloud APIs
Frequently Asked Questions
What format must my skill definition follow?
Your skill must be a valid SKILL.md file with YAML front-matter containing at minimum name (kebab-case, unique within your organization) and description fields, followed by a Markdown body with execution instructions. The create-skill capability rejects files missing either component.
Can I update a skill after publishing it?
Yes. If create-skill detects a duplicate plugin (HTTP 409), it offers to update via postConfigObjectsVersions. For marketplace-published skills, the updated version becomes available immediately to all users with access.
Do I need to publish to a marketplace to use my skill?
No. Skills are instantly usable by their creator immediately after create-skill succeeds. Marketplace publication is only required to make the skill discoverable by other users or teams in your organization.
How do I control who can see my marketplace skill?
Use skill:share-plugin to grant specific orgMembershipId values access with roles (viewer, admin). Alternatively, create a private marketplace and add your plugin only there—marketplace visibility acts as a first gate, with plugin-level sharing as a second layer.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →