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_objectwithobject_type = "skill"containing markdown body (SKILL.md) - Plugin: Container owning one-to-many config objects via
plugin_config_objectjunction table - Marketplace: Container owning plugins via
marketplace_pluginjunction table - Access Grant:
*_access_granttables controllingviewer | editor | managerpermissions 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:
createPluginWithSkillincloud-plugins.tsPOSTs to/v1/pluginsstore.ts→createPlugincreates thepluginrow and relatedconfig_objectvia theplugin_config_objectjunction
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →