---
read_when:
    - 你需要 `definePluginEntry` 或 `defineChannelPluginEntry` 的精确类型签名
    - 你想了解注册模式（完整、设置、CLI 元数据）
    - 你在查找入口点选项
sidebarTitle: Entry Points
summary: '`definePluginEntry`、`defineChannelPluginEntry` 和 `defineSetupPluginEntry` 的参考说明'
title: 插件入口点
x-i18n:
    generated_at: "2026-04-25T02:36:15Z"
    model: gpt-5.4
    provider: openai
    source_hash: 8253cf0ac43ca11b42c0032027bba6e926c961b54901caaa63da70bd5ff5aab5
    source_path: plugins/sdk-entrypoints.md
    workflow: 15
---

每个插件都会导出一个默认入口对象。SDK 提供了三个辅助函数来创建它们。

对于已安装的插件，`package.json` 应在可用时将运行时加载指向已构建的 JavaScript：

```json
{
  "openclaw": {
    "extensions": ["./src/index.ts"],
    "runtimeExtensions": ["./dist/index.js"],
    "setupEntry": "./src/setup-entry.ts",
    "runtimeSetupEntry": "./dist/setup-entry.js"
  }
}
```

`extensions` 和 `setupEntry` 仍然是工作区和 git 检出开发时有效的源码入口。`runtimeExtensions` 和 `runtimeSetupEntry` 会在 OpenClaw 加载已安装包时优先使用，并让 npm 包避免在运行时编译 TypeScript。如果某个已安装包只声明了 TypeScript 源码入口，OpenClaw 会在存在对应项时使用匹配的已构建 `dist/*.js` 对应文件，然后再回退到 TypeScript 源码。

所有入口路径都必须保留在插件包目录内。运行时入口和推断出的已构建 JavaScript 对应文件，不会让逃逸出 `extensions` 或 `setupEntry` 源码路径的配置变为有效。

<Tip>
  **在找分步演练？** 参见 [渠道插件](/zh-CN/plugins/sdk-channel-plugins) 或 [提供商插件](/zh-CN/plugins/sdk-provider-plugins) 获取分步指南。
</Tip>

## `definePluginEntry`

**导入：** `openclaw/plugin-sdk/plugin-entry`

用于提供商插件、工具插件、钩子插件，以及任何**不是**消息渠道的插件。

```typescript
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";

export default definePluginEntry({
  id: "my-plugin",
  name: "My Plugin",
  description: "Short summary",
  register(api) {
    api.registerProvider({
      /* ... */
    });
    api.registerTool({
      /* ... */
    });
  },
});
```

| 字段 | 类型 | 必填 | 默认值 |
| -------------- | ---------------------------------------------------------------- | -------- | ------------------- |
| `id`           | `string`                                                         | 是       | —                   |
| `name`         | `string`                                                         | 是       | —                   |
| `description`  | `string`                                                         | 是       | —                   |
| `kind`         | `string`                                                         | 否       | —                   |
| `configSchema` | `OpenClawPluginConfigSchema \| () => OpenClawPluginConfigSchema` | 否       | 空对象 schema |
| `register`     | `(api: OpenClawPluginApi) => void`                               | 是       | —                   |

- `id` 必须与你的 `openclaw.plugin.json` 清单一致。
- `kind` 用于互斥槽位：`"memory"` 或 `"context-engine"`。
- `configSchema` 可以是一个用于延迟求值的函数。
- OpenClaw 会在首次访问时解析并记忆该 schema，因此代价较高的 schema 构建器只会运行一次。

## `defineChannelPluginEntry`

**导入：** `openclaw/plugin-sdk/channel-core`

这是带有渠道专用接线逻辑的 `definePluginEntry` 封装。它会自动调用 `api.registerChannel({ plugin })`，提供一个可选的根帮助 CLI 元数据扩展点，并根据注册模式控制 `registerFull` 的执行。

```typescript
import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";

export default defineChannelPluginEntry({
  id: "my-channel",
  name: "My Channel",
  description: "Short summary",
  plugin: myChannelPlugin,
  setRuntime: setMyRuntime,
  registerCliMetadata(api) {
    api.registerCli(/* ... */);
  },
  registerFull(api) {
    api.registerGatewayMethod(/* ... */);
  },
});
```

| 字段 | 类型 | 必填 | 默认值 |
| --------------------- | ---------------------------------------------------------------- | -------- | ------------------- |
| `id`                  | `string`                                                         | 是       | —                   |
| `name`                | `string`                                                         | 是       | —                   |
| `description`         | `string`                                                         | 是       | —                   |
| `plugin`              | `ChannelPlugin`                                                  | 是       | —                   |
| `configSchema`        | `OpenClawPluginConfigSchema \| () => OpenClawPluginConfigSchema` | 否       | 空对象 schema |
| `setRuntime`          | `(runtime: PluginRuntime) => void`                               | 否       | —                   |
| `registerCliMetadata` | `(api: OpenClawPluginApi) => void`                               | 否       | —                   |
| `registerFull`        | `(api: OpenClawPluginApi) => void`                               | 否       | —                   |

- `setRuntime` 会在注册期间调用，这样你就可以保存运行时引用（通常通过 `createPluginRuntimeStore`）。在捕获 CLI 元数据期间会跳过它。
- `registerCliMetadata` 会在 `api.registrationMode === "cli-metadata"`、`api.registrationMode === "discovery"` 和 `api.registrationMode === "full"` 时运行。
  将它作为渠道自有 CLI 描述符的规范位置，这样根帮助就不会激活插件，设备发现快照会包含静态命令元数据，而正常 CLI 命令注册也能与完整插件加载保持兼容。
- 设备发现注册是非激活式的，而不是完全不导入。OpenClaw 可能会对受信任的插件入口和渠道插件模块求值，以构建快照，因此要保持顶层导入无副作用，并把套接字、客户端、worker 和服务放在仅 `"full"` 的路径后面。
- `registerFull` 仅会在 `api.registrationMode === "full"` 时运行。在仅设置加载期间会跳过它。
- 与 `definePluginEntry` 一样，`configSchema` 可以是延迟工厂，且 OpenClaw 会在首次访问时记忆已解析的 schema。
- 对于插件自有的根 CLI 命令，如果你希望命令保持延迟加载，同时又不从根 CLI 解析树中消失，优先使用 `api.registerCli(..., { descriptors: [...] })`。对于渠道插件，优先在 `registerCliMetadata(...)` 中注册这些描述符，并让 `registerFull(...)` 专注于仅运行时工作。
- 如果 `registerFull(...)` 还会注册 Gateway 网关 RPC 方法，请将它们保留在插件专属前缀下。保留的核心管理命名空间（`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`）始终会被强制为 `operator.admin`。

## `defineSetupPluginEntry`

**导入：** `openclaw/plugin-sdk/channel-core`

用于轻量级的 `setup-entry.ts` 文件。它只返回 `{ plugin }`，不包含运行时或 CLI 接线逻辑。

```typescript
import { defineSetupPluginEntry } from "openclaw/plugin-sdk/channel-core";

export default defineSetupPluginEntry(myChannelPlugin);
```

当某个渠道被禁用、未配置，或启用了延迟加载时，OpenClaw 会加载它而不是完整入口。有关何时会出现这种情况，请参见 [设置和配置](/zh-CN/plugins/sdk-setup#setup-entry)。

在实际使用中，建议将 `defineSetupPluginEntry(...)` 与以下窄范围的设置辅助函数族搭配使用：

- `openclaw/plugin-sdk/setup-runtime`：用于运行时安全的设置辅助函数，例如导入安全的设置补丁适配器、查找说明输出、`promptResolvedAllowFrom`、`splitSetupEntries` 和委托式设置代理
- `openclaw/plugin-sdk/channel-setup`：用于可选安装的设置界面
- `openclaw/plugin-sdk/setup-tools`：用于设置/安装 CLI、归档和文档辅助函数

请将重量级 SDK、CLI 注册以及长生命周期运行时服务保留在完整入口中。

拆分了设置面和运行时面的内置工作区渠道，可以改用来自 `openclaw/plugin-sdk/channel-entry-contract` 的 `defineBundledChannelSetupEntry(...)`。这个契约允许设置入口在暴露运行时 setter 的同时，仍然保留设置安全的插件/密钥导出：

```typescript
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";

export default defineBundledChannelSetupEntry({
  importMetaUrl: import.meta.url,
  plugin: {
    specifier: "./channel-plugin-api.js",
    exportName: "myChannelPlugin",
  },
  runtime: {
    specifier: "./runtime-api.js",
    exportName: "setMyChannelRuntime",
  },
});
```

只有当设置流程确实需要在完整渠道入口加载之前，先使用一个轻量级运行时 setter 时，才使用这个内置契约。

## 注册模式

`api.registrationMode` 会告诉你的插件它是如何被加载的：

| 模式 | 何时 | 应注册的内容 |
| ----------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `"full"`          | 正常 Gateway 网关启动 | 全部内容 |
| `"discovery"`     | 只读能力发现 | 渠道注册加静态 CLI 描述符；入口代码可能会加载，但要跳过套接字、worker、客户端和服务 |
| `"setup-only"`    | 渠道被禁用/未配置 | 仅渠道注册 |
| `"setup-runtime"` | 设置流程且运行时可用 | 渠道注册，以及在完整入口加载前所需的轻量级运行时 |
| `"cli-metadata"`  | 根帮助 / CLI 元数据捕获 | 仅 CLI 描述符 |

`defineChannelPluginEntry` 会自动处理这个拆分。如果你对某个渠道直接使用 `definePluginEntry`，请自行检查模式：

```typescript
register(api) {
  if (
    api.registrationMode === "cli-metadata" ||
    api.registrationMode === "discovery" ||
    api.registrationMode === "full"
  ) {
    api.registerCli(/* ... */);
    if (api.registrationMode === "cli-metadata") return;
  }

  api.registerChannel({ plugin: myPlugin });
  if (api.registrationMode !== "full") return;

  // Heavy runtime-only registrations
  api.registerService(/* ... */);
}
```

设备发现模式会构建一个非激活式注册表快照。它仍然可能会对插件入口和渠道插件对象求值，以便 OpenClaw 注册渠道能力和静态 CLI 描述符。应将设备发现中的模块求值视为受信任但轻量：顶层不要包含网络客户端、子进程、监听器、数据库连接、后台 worker、凭证读取或其他实时运行时副作用。

将 `"setup-runtime"` 视为这样一个窗口：仅设置阶段所需的启动面必须存在，但不能重新进入完整的内置渠道运行时。适合放在这里的内容包括渠道注册、设置安全的 HTTP 路由、设置安全的 Gateway 网关方法以及委托式设置辅助函数。重量级后台服务、CLI 注册器以及提供商/客户端 SDK 引导仍然应放在 `"full"` 中。

具体到 CLI 注册器：

- 当注册器拥有一个或多个根命令，并且你希望 OpenClaw 在首次调用时再延迟加载真实 CLI 模块时，请使用 `descriptors`
- 确保这些描述符覆盖注册器暴露的每个顶层命令根
- 将描述符命令名称限制为字母、数字、连字符和下划线，并且必须以字母或数字开头；OpenClaw 会拒绝不符合该形状的描述符名称，并在渲染帮助前移除描述中的终端控制序列
- 仅当需要急切兼容路径时，才单独使用 `commands`

## 插件形态

OpenClaw 会根据已加载插件的注册行为对其进行分类：

| 形态 | 说明 |
| --------------------- | -------------------------------------------------- |
| **plain-capability**  | 单一能力类型（例如仅提供商） |
| **hybrid-capability** | 多种能力类型（例如提供商 + 语音） |
| **hook-only**         | 仅有钩子，没有能力 |
| **non-capability**    | 有工具/命令/服务，但没有能力 |

使用 `openclaw plugins inspect <id>` 查看插件的形态。

## 相关内容

- [SDK 概览](/zh-CN/plugins/sdk-overview) —— 注册 API 和子路径参考
- [运行时辅助函数](/zh-CN/plugins/sdk-runtime) —— `api.runtime` 和 `createPluginRuntimeStore`
- [设置和配置](/zh-CN/plugins/sdk-setup) —— 清单、设置入口、延迟加载
- [渠道插件](/zh-CN/plugins/sdk-channel-plugins) —— 构建 `ChannelPlugin` 对象
- [提供商插件](/zh-CN/plugins/sdk-provider-plugins) —— 提供商注册和钩子
