# How Skills and Plugins Operate in the OpenWork Marketplace Ecosystem

> Discover how OpenWork marketplace skills and plugins operate. Learn how agents discover and execute these encrypted config objects securely within the database without external network calls.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: internals
- Published: 2026-07-31

---

**In the OpenWork marketplace ecosystem, skills and plugins are stored as encrypted, versioned config objects that agents discover via the unified capability rail and execute entirely within the database—no external network calls required.**

OpenWork is an open-source AI-workspace platform that treats **skills**, **plugins**, and related resources as **extensions** published to an **organization marketplace**. This marketplace functions as the fourth capability source on the OpenWork rail—the set of tools `search_capabilities` and `execute_capability` available to agents—supplementing the REST catalog, external MCP connections, and native provider capabilities. Understanding how skills and plugins operate in the OpenWork marketplace ecosystem is essential for admins who want to distribute internal tools and for developers building on the `different-ai/openwork` source code.

## The OpenWork Marketplace as a Capability Source for Skills and Plugins

The OpenWork capability rail exposes exactly two tools—`search_capabilities` and `execute_capability`—that consume four underlying sources. The marketplace sits alongside the REST catalog, external MCP connections, and native provider routes, as detailed in [`docs/marketplace-capabilities-architecture.md`](https://github.com/different-ai/openwork/blob/main/docs/marketplace-capabilities-architecture.md) and grounded in the generic extension abstraction from [`docs/extensions-manifest-foundation.md`](https://github.com/different-ai/openwork/blob/main/docs/extensions-manifest-foundation.md).

When a user queries `search_capabilities`, the search engine interleaves marketplace matches with the other sources and scores them on title, description, and full-text fields. Each result is identified by a canonical name that follows the pattern `plugin:<pluginId>:<configObjectId>`.

For example, `plugin:12345:skill-abc` maps to a specific config object inside a plugin record. Under the hood, these objects are indexed from the database tables defined in [`den-db/src/schema/sharables/plugin-arch.ts`](https://github.com/different-ai/openwork/blob/main/den-db/src/schema/sharables/plugin-arch.ts). The marketplace surfaces DB-only config object types such as **skill**, **command**, **agent**, **mcp**, **tool**, **hook**, **context**, and **custom**.

## Execution Flow for Marketplace Skills and Plugins

When an agent calls `execute_capability` with a marketplace name, the server runs a deterministic, database-local pipeline. Because the path never makes outbound network requests, it remains fast and isolated. The flow is implemented across the plugin-system store and agent execution layers in [`ee/apps/den-api/src/routes/org/plugin-system/store.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/routes/org/plugin-system/store.ts) and related handlers.

### Parse the Capability Identifier

The handler first extracts `pluginId` and `configObjectId` from the `plugin:<pluginId>:<configObjectId>` string using a strict regex. If the name does not match, the request is rejected before any access checks occur.

```ts
function parseMarketplaceCapabilityName(name: string) {
  const m = /^plugin:([^:]+):([^:]+)$/.exec(name);
  if (!m) throw new Error("Invalid marketplace capability");
  return { pluginId: m[1], configObjectId: m[2] };
}

```

### Verify Grants and Visibility

Access is enforced through three grant tables: `ConfigObjectAccessGrantTable`, `PluginAccessGrantTable`, and `MarketplaceAccessGrantTable`. A member with **viewer** rights on the matching grant can both search and execute the object, while organization admins see every marketplace item without restriction.

### Load and Decrypt the Latest Version

After access is confirmed, the server pulls the `latestVersion` record from the `ConfigObjectVersion` table. It then decrypts the stored `rawSourceText` or `normalizedPayloadJson` using the existing `encryptedTextColumn` logic, keeping skill definitions secure at rest.

### Return an Instructional Payload

The final response is an **instructional payload** that agents consume directly. It carries the `kind`, `plugin` and `marketplace` provenance, `name`, `description`, and the **full content**—such as the complete Markdown body of a skill. Optional `status` flags like `needs_install` or `content_not_synced` and a corresponding `hint` surface degraded states.

```json
{
  "kind": "skill",
  "plugin": "Support Operations",
  "marketplace": "Acme Marketplace",
  "name": "Create shift handoff",
  "description": "Creates a handoff report for unresolved tickets.",
  "content": "...full skill markdown body...",
  "provenance": "Content from marketplace plugin Support Operations in your organization."
}

```

Because this payload is returned through the standard `execute_capability` handler, no new tools are added to the agent rail. This preserves the existing API contract while still surfacing rich marketplace content.

## Local Installation of Marketplace Skills and Plugins

The **desktop client** can materialize a marketplace plugin locally by copying its files into the workspace `.opencode/` folder. The orchestration logic lives in [`apps/server/src/cloud-plugins.ts`](https://github.com/different-ai/openwork/blob/main/apps/server/src/cloud-plugins.ts) and handles namespace allocation, path mapping, content rendering, and **MCP** registration.

### Namespace and Path Mapping

During installation, the routine derives a `pluginNamespace` from the plugin’s name or id. It then maps each config object type to a concrete disk path. Skills are written to `.opencode/skills/<namespace>/<skill>/SKILL.md`, while MCP objects become `.opencode/mcps/<namespace>/<name>.json`.

```ts
function getPluginObjectInstallPath(obj: CloudPluginConfigObject, namespace: string) {
  // Returns paths like `.opencode/skills/<namespace>/<skill>/SKILL.md`
  // or `.opencode/mcps/<namespace>/<name>.json` for MCP objects.
  // (Full implementation in installCloudPlugin)
}

```

### Content Rendering and MCP Registration

For skill objects, the installer calls `buildCloudSkillContent` to assemble the final Markdown body before writing it to disk. If the plugin defines MCP servers, the client invokes `addMcp` to register them in the local workspace. Uninstalling a plugin triggers `removeMcp` and `removePluginWorkspaceFile` to keep the workspace clean.

## Access Control and Kill Switches for Marketplace Skills and Plugins

Marketplace visibility uses the same **Connect gating** that governs external MCP connections. Organization metadata can disable the entire marketplace capability source by setting a top-level **kill-switch** flag.

```json
{
  "capabilities": {
    "mcpConnections": false
  }
}

```

When this flag is active, `search_capabilities` omits all `plugin:` matches and `execute_capability` returns `unknown_capability`. This guarantees byte-identical behavior for organizations that have opted out and is documented in [`docs/marketplace-capabilities-architecture.md`](https://github.com/different-ai/openwork/blob/main/docs/marketplace-capabilities-architecture.md).

## Extending the OpenWork Ecosystem with OpenCode Plugins

OpenWork also supports **OpenCode plugins**, which are custom tool bundles that live in a workspace’s `.opencode/plugins/` directory. These plugins export an async factory that returns a hooks object containing tools, experiment transforms, and other extensions, as shown in [`.opencode/skills/create-plugin/SKILL.md`](https://github.com/different-ai/openwork/blob/main/.opencode/skills/create-plugin/SKILL.md).

Although OpenCode plugins are distinct from Anthropic plugins, they can be adapted into standard marketplace plugin resources. Once published, they flow through the same discovery and execution pipeline as any other skill or config object in the OpenWork marketplace ecosystem.

## Summary

- **Config Object Storage**: Skills and plugins are stored as versioned config objects inside a plugin record, with schemas defined in [`den-db/src/schema/sharables/plugin-arch.ts`](https://github.com/different-ai/openwork/blob/main/den-db/src/schema/sharables/plugin-arch.ts).
- **Unified Rail**: The marketplace is a fourth capability source on the OpenWork rail, interleaving results from `search_capabilities` and executing via `execute_capability` without adding new tools.
- **Access Control**: Visibility is enforced through `ConfigObjectAccessGrantTable`, `PluginAccessGrantTable`, and `MarketplaceAccessGrantTable`, plus an organization-wide kill switch.
- **Local Installation**: The desktop client installs marketplace plugins into `.opencode/` using [`apps/server/src/cloud-plugins.ts`](https://github.com/different-ai/openwork/blob/main/apps/server/src/cloud-plugins.ts), rendering skills and registering MCP connections locally.
- **Zero Network Execution**: Marketplace capability execution is database-only, decrypting content on the fly and returning instructional payloads without outbound calls.

## Frequently Asked Questions

### How are skills and plugins stored in the OpenWork marketplace?

They are stored as **config objects** within a plugin record inside the organization database. The schema is defined in [`den-db/src/schema/sharables/plugin-arch.ts`](https://github.com/different-ai/openwork/blob/main/den-db/src/schema/sharables/plugin-arch.ts), and each object is versioned through the `ConfigObjectVersion` table. At rest, sensitive fields such as `rawSourceText` are encrypted using the `encryptedTextColumn` abstraction.

### What happens when an agent executes a marketplace skill?

The agent calls `execute_capability` with a name like `plugin:12345:skill-abc`. The server parses the identifier, validates grants against three access tables, loads the latest version, decrypts the source, and returns an instructional payload containing the full skill content and provenance. No external network calls are required because the path is entirely database-local.

### Can an organization disable marketplace access entirely?

Yes. An admin can set the organization metadata flag `"capabilities": { "mcpConnections": false }`, which acts as a kill switch. When disabled, `search_capabilities` filters out all `plugin:` results and `execute_capability` responds with `unknown_capability`, ensuring opted-out orgs experience identical behavior.

### How does local installation work for marketplace plugins?

The desktop client runs the `installCloudPlugin` routine in [`apps/server/src/cloud-plugins.ts`](https://github.com/different-ai/openwork/blob/main/apps/server/src/cloud-plugins.ts), which copies config objects into the workspace `.opencode/` folder under a derived namespace. Skills become Markdown files, MCP objects trigger `addMcp`, and removal cleans up via `removeMcp` and `removePluginWorkspaceFile`.