Hold Rein 文档
安装
本地安装
本地安装依赖 Node.js 22 及以上版本。确认 Node 环境满足要求后,可以通过 npm 全局安装 Hold Rein CLI。
npm install @hold-rein/cli -gDocker 安装
Docker 方式适合把运行时固定在容器环境中,并通过数据卷保存本地配置与运行数据。
FROM node:22-bookworm-slim
ARG HOLD_REIN_VERSION=latest
ARG NPM_REGISTRY=https://registry.npmmirror.com
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
git \
ca-certificates \
openssh-client \
python3 \
make \
g++ \
&& rm -rf /var/lib/apt/lists/*
ENV PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
ENV GIT_BINARY="/usr/bin/git"
ENV PYTHON="/usr/bin/python3"
ENV npm_config_python="/usr/bin/python3"
ENV npm_config_registry="https://registry.npmmirror.com"
ENV NPM_CONFIG_REGISTRY="https://registry.npmmirror.com"
RUN npm config set registry "${NPM_REGISTRY}" \
&& npm install --global "@hold-rein/cli@${HOLD_REIN_VERSION}" \
&& npm cache clean --force
EXPOSE 3001
VOLUME ["/root/.hold-rein"]
CMD ["hold-rein", "start", "--host", "0.0.0.0", "--port", "3001"]services:
hold-rein:
build:
context: .
args:
HOLD_REIN_VERSION: latest
NPM_REGISTRY: https://registry.npmmirror.com
ports:
- "3001:3001"
volumes:
- hold-rein-data:/root/.hold-rein
environment:
npm_config_registry: https://registry.npmmirror.com
NPM_CONFIG_REGISTRY: https://registry.npmmirror.com
restart: unless-stopped
volumes:
hold-rein-data:docker compose build
docker compose up -d启动
启动本地服务
安装完成后,在需要工作的项目目录中执行启动命令。Hold Rein 会启动内置 API 运行时与 Web 控制台,默认监听127.0.0.1:3001。
hold-rein start- API 运行时负责加载 Agent、工具、插件与本地配置。
- Web 控制台启动后直接在浏览器中访问,用来查看和操作当前工作台。
- 工作目录建议在项目根目录启动,让文件夹自然成为当前工作台边界。
自定义监听地址与端口
默认只监听本机地址。如果需要在容器、局域网或远程开发环境中访问,可以通过--host 与 --port 指定监听方式。
hold-rein start --host 0.0.0.0 --port 4000--host指定监听地址。使用 0.0.0.0 时,服务会接受外部网络访问。--port指定 Web 控制台与 API 服务端口,适合避开本机已有服务。插件开发模式
开发本地插件时,使用 --plugin-dev 加载插件源码。源码变化后运行时会自动重载,适合调试工具、 前端扩展和设置页。
hold-rein start --plugin-dev ./plugins/my-pluginDocker 启动后访问
如果使用上面的 Docker Compose 配置,容器会把内部 3001 端口映射到宿主机 3001 端口。启动完成后访问http://127.0.0.1:3001 即可进入控制台。
docker compose ps插件开发
初始化
hold-rein plugin init 是插件脚手架命令。直接执行时会在当前目录生成插件包; 通过 --path 指定插件根目录,通过 --name 指定新插件文件夹名,两者可以组合使用。
hold-rein plugin init --path ./plugins --name my-pluginInitialized plugin package hold-rein-plugin-my-plugin生成时包名会使用目标文件夹名拼出 hold-rein-plugin-<folder-name>,插件 id 会写入src/plugin-id.ts,格式是 __<folder-name>__plugin。如果目标文件已存在, 初始化会拒绝覆盖,避免误删已有插件代码。
my-plugin/
├─ package.json
├─ tsconfig.json
├─ vite.config.ts
├─ vite.web.config.ts
└─ src/
├─ plugin-id.ts
├─ server.ts
└─ web.ts- package.json声明 server/web 两个导出入口、构建脚本,以及 @hold-rein/plugin-server、@hold-rein/plugin-web、React、Ant Design 等 peerDependencies。
- vite.config.ts构建服务端入口 src/server.ts,输出 ESM 与 CJS,Node 内置模块、Express 与 Hold Rein 运行时依赖会作为 external。
- vite.web.config.ts构建浏览器端入口 src/web.ts,开发时接入共享依赖插件,产物默认是 web.umd.cjs 与 style.css。
- tsconfig.json启用 strict、declaration、Bundler moduleResolution 与 react-jsx,声明文件会输出到 dist。
- src/plugin-id.ts集中导出 PLUGIN_ID,服务端与 Web 端共用同一个插件身份。
- src/server.ts默认导出 ServerPlugin.Plugin,可继续补 registerRoutes 与 contributionResolver。
- src/web.ts默认导出 WebPlugin.Plugin,可继续补面板、设置页、发送区动作和工具渲染。
服务端 API
服务端插件实现 ServerPlugin.Plugin。最小字段是 id;需要扩展 API 时实现registerRoutes,需要影响 Agent 运行时则实现 contributionResolver;需要在加载后初始化时实现onLoaded。
registerRoutes(context)返回 Express Router,宿主会挂载到 /plugin/<plugin-id>。context 提供 sendSuccess、sendError 与响应码定义。contributionResolver(context)可返回静态 Contribution,也可以按 RuntimeContext 动态构建插件能力。onLoaded({ hostApi })每次服务端插件加载或开发热重载后依次执行,可通过插件作用域的宿主 API 完成初始化;钩子失败会中止本次加载。tools、skills、skillDirs、systemPrompts把工具、内联技能、技能目录和系统提示注入 Agent 运行时。subscribe、onAgentEnd订阅 AgentHarnessEvent,或在一轮 Agent 结束后返回 AgentContinuation 继续任务。RuntimeContext 会带上当前 agentName、env、session、model、thinkingLevel、prompt、taskId 等信息;RunAgentInput 与 AgentEndInput 则用于收尾和续跑场景。
import type { ServerPlugin } from "@hold-rein/plugin-server";
import { Router } from "express";
import { PLUGIN_ID } from "./plugin-id";
const serverPlugin: ServerPlugin.Plugin = {
id: PLUGIN_ID,
async onLoaded({ hostApi }) {
const result = await hostApi.plugins.list();
console.log(result.data);
},
registerRoutes({ sendSuccess }) {
const router = Router();
router.get("/status", (_request, response) => {
sendSuccess(response, { ready: true });
});
return router;
},
contributionResolver: (context) => ({
tools: [],
skills: [],
systemPrompts: [
`Current workspace: ${context.env.cwd}`
]
})
};
export default serverPlugin;Web 端 API
Web 插件实现 WebPlugin.Plugin,通过 contributionResolver 返回界面扩展。 resolver 的 RuntimeContext 提供 request<TData> 调用插件服务端 API, 也提供 subscribeAppUi 订阅当前 UI 状态。
rightPanels、settings注册右侧面板和设置项,组件可以读取消息、任务状态、工作区路径等 props。senderActions、senderSuggestions扩展输入区动作与触发式建议,适合插入模板、命令或上下文片段。toolRenders、turnFooterRenders自定义工具调用展示和单轮消息尾部渲染,让插件数据进入会话流。tools、skills、systemPrompts声明浏览器运行时工具、浏览器技能与提示词,工具参数使用 TypeBox schema 描述。构建请求时传入 path、method、query、headers 与body。例如 request<TData>({ path: "/plugin/__my__plugin/status", method: "GET" })会返回统一的 { code, data, msg } 结果。
import type { WebPlugin } from "@hold-rein/plugin-web";
import { PLUGIN_ID } from "./plugin-id";
const webPlugin: WebPlugin.Plugin = {
id: PLUGIN_ID,
contributionResolver: ({ request }) => ({
rightPanels: [],
senderActions: [],
tools: [],
settings: []
})
};
export default webPlugin;