Skill and Plugin Publishing Architecture in OpenWork's Den Marketplace System

OpenWork's Den marketplace system uses a four-layer architecture—persistence, API contracts, business logic, and client helpers—to enable role-based publishing of skills through plugins and marketplaces.

The Den control-plane in different-ai/openwork provides a complete skill and plugin publishing architecture that separates storage, contracts, and access control. This article examines how config objects (skills), plugins, and marketplaces interact through granular access grants.


How the Four-Layer Architecture Works

Layer Responsibility Core Source File
Persistence MySQL tables for config objects, plugins, marketplaces, and grants ee/packages/den-db/src/schema/sharables/plugin-arch.ts
API Contracts Zod-typed REST endpoint definitions ee/apps/den-api/src/routes/org/plugin-system/contracts.ts
Business Logic Server handlers for RBAC enforcement and mutation ee/apps/den-api/src/routes/org/plugin-system/store.ts
Client Helpers Convenience wrappers for API invocation evals/packages/behaviors/src/cloud-plugins.ts

Core entities in the publishing model:

  • Skill: A config_object with object_type = "skill" containing markdown body (SKILL.md)
  • Plugin: Container owning one-to-many config objects via plugin_config_object junction table
  • Marketplace: Container owning plugins via marketplace_plugin junction table
  • Access Grant: *_access_grant tables controlling viewer | editor | manager permissions at org, team, or member scope

Step-by-Step Publishing Flow

1. Create a Marketplace (Admin Only)

Admins initialize marketplaces as the top-level sharing boundary:

POST /v1/marketplaces
{
  "name": "Team Marketplace",
  "description": "Plugins shared within the team"
}

Implementation: createMarketplace in store.ts inserts into the marketplace table and returns the generated id.


2. Create a Plugin Containing a Skill

Members bundle skills into plugins that can optionally attach to marketplaces immediately:

POST /v1/plugins
{
  "name": "My Demo Plugin",
  "description": "Demo plugin for a skill",
  "orgWide": true,
  "marketplaceId": "<marketplace-id>",
  "components": [
    {
      "type": "skill",
      "input": {
        "rawSourceText": "---\nname: demo-skill\ndescription: Demo skill\n---\nThe skill body…"
      }
    }
  ]
}

Implementation chain:

  • createPluginWithSkill in cloud-plugins.ts POSTs to /v1/plugins
  • store.ts → createPlugin creates the plugin row and related config_object via the plugin_config_object junction

3. Assign Existing Plugin to Marketplace

For plugins created independently, admins attach them to marketplaces:

POST /v1/marketplaces/{marketplaceId}/plugins
{
  "pluginId": "<plugin-id>"
}

Implementation: assignPluginToMarketplace in cloud-plugins.ts invokes this endpoint; store.ts inserts into marketplace_plugin with a unique (marketplaceId, pluginId) constraint.


4. Grant Marketplace Access

Admins control visibility through explicit grants:

POST /v1/marketplaces/{marketplaceId}/access
{
  "role": "viewer",
  "orgMembershipId": "<member-id>"
}

# Alternative: { "orgWide": true } for organization-wide access

Implementation: grantMarketplaceAccess in cloud-plugins.ts creates a marketplace_access_grant row. store.ts enforces role requirements via requirePluginArchResourceRole.


5. Resolve Visible

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →