From a82c5801b753441d74b122ac3e6040bbebc0cbf6 Mon Sep 17 00:00:00 2001 From: dodaa08 Date: Fri, 18 Sep 2026 12:31:51 +0530 Subject: [PATCH] feat(multi-bot): atomic config updates, dynamic agent routing & skill docs --- .github/workflows/publish.yml | 6 -- docs/SKILLS.md | 65 ++++++++++++++++--- docs/SKILLS/Cron.md | 119 ---------------------------------- docs/SKILLS/doc.md | 51 --------------- openclaw.plugin.json | 2 +- package.json | 2 +- src/cli/config-updater.ts | 3 - src/service/inbound.ts | 4 -- 8 files changed, 58 insertions(+), 194 deletions(-) delete mode 100644 docs/SKILLS/Cron.md delete mode 100644 docs/SKILLS/doc.md diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8235530..6770428 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -39,7 +39,6 @@ jobs: ROCKETCHAT_USER_ID: ${{ secrets.ROCKETCHAT_USER_ID }} ROCKETCHAT_TOKEN: ${{ secrets.ROCKETCHAT_TOKEN }} - # Add dist/ to git staging (include in publish) - name: Stage dist for publish run: | git add dist/ --force @@ -47,14 +46,11 @@ jobs: git config user.email "actions@github.com" git commit -m "build: dist for v$(node -p 'require(\"./package.json\").version')" || true - # Authenticate with ClawHub - name: Authenticate with ClawHub env: CLAWHUB_TOKEN: ${{ secrets.CLAWHUB_TOKEN }} run: pnpm dlx clawhub login --token "$CLAWHUB_TOKEN" - # Compare package.json version against the current ClawHub latest; - # only publish when the version actually changed (skips duplicates). - name: Check for new version id: check run: | @@ -74,7 +70,6 @@ jobs: echo "current=$CURRENT latest=$LATEST publish_new=$SHOULD" echo "should_publish=$SHOULD" >> "$GITHUB_OUTPUT" - # Publish to ClawHub (always on a version tag, only on new versions otherwise) - name: Publish to ClawHub id: publish if: ${{ startsWith(github.ref, 'refs/tags/') || steps.check.outputs.should_publish == 'true' }} @@ -86,7 +81,6 @@ jobs: --source-ref ${{ github.ref_name }} \ --wait - # Create GitHub release (optional but nice, only for version tags) - name: Create GitHub Release if: startsWith(github.ref, 'refs/tags/') uses: softprops/action-gh-release@v1 diff --git a/docs/SKILLS.md b/docs/SKILLS.md index f1ac303..2cb01a8 100644 --- a/docs/SKILLS.md +++ b/docs/SKILLS.md @@ -1,10 +1,51 @@ -# Skill Installation & Management Guide +# OpenClaw Skills & Management Guide -OpenClaw supports installing skills both **globally** for all bots and **per-agent** for isolated bots. +Skills let you extend what your OpenClaw agent can do—from scheduling reminders and automation to integrating with third-party services like email, calendars, and external APIs. +OpenClaw supports creating custom skills manually in your workspace as well as installing package-managed skills from ClawHub. + +--- + +## 1. Creating a Custom Skill Manually + +To create your own custom skill: + +### Step 1: Create the Skill Folder + +Skills live inside an agent's workspace folder under `skills`: + +```bash +# For a specific agent (e.g., main or rc-newb2) +mkdir -p ~/.openclaw/workspace/main/skills/my-custom-skill +``` + +### Step 2: Add `SKILL.md` + +Inside the skill folder, create a `SKILL.md` file detailing what the skill does and its rules: + +```markdown +--- +name: my-custom-skill +description: A brief summary of what this custom skill does --- -## 1. Global Skill Installation (For ALL Bots) +# My Custom Skill + +Write instructions, required parameters, environment variables, or CLI usage rules here for the agent. +``` + +A `SKILL.md` must include: + +- A YAML frontmatter block (`---` containing `name` and `description`). +- Usage instructions and rules that the AI model follows when executing the skill. + +--- + +## 2. Installing Skills via ClawHub CLI + +OpenClaw supports installing pre-built community skills directly from ClawHub. + +### Global Installation (Available to ALL Bots) To install a skill **globally** so that every bot on your server (`main`, `rc-newb2`, etc.) can access it: @@ -13,12 +54,11 @@ openclaw skills install --global ``` - **Target Directory**: `~/.openclaw/skills/` -- **Scope**: All present and future agents automatically gain access. -- **Flag Required**: `--global` (or `-g`). Does **not** require `--agent`. +- **Access**: Available to all present and future bots. --- -## 2. Per-Agent Skill Installation (Isolated Bot Workspace) +### Per-Agent Installation (Isolated Bot Workspace) To install a skill **specifically for one agent** (so other bots cannot access it): @@ -26,12 +66,12 @@ To install a skill **specifically for one agent** (so other bots cannot access i openclaw skills install --agent ``` -> ⚠️ **Note on Syntax**: Always use `--agent ` (e.g. `--agent main` or `--agent rc-newb2`). Do not pass `--main` as a boolean flag. +> ⚠️ **Note**: Always use `--agent ` (e.g., `--agent main` or `--agent rc-newb2`). **Examples:** ```bash -# Install for the main agent +# Install for default main agent openclaw skills install @otman-ai/google-calender-maton --agent main # Install for a dedicated Rocket.Chat bot agent @@ -39,7 +79,7 @@ openclaw skills install @porteden/email-gmail-outlook --agent rc-newb2 ``` - **Target Directory**: `~/.openclaw/workspace//skills/` -- **Scope**: Isolated to that specific agent only. +- **Access**: Isolated to that specific agent only. --- @@ -70,3 +110,10 @@ When multiple agents exist (e.g., `main` and `rc-newb2`), OpenClaw operates in * | **List Skills** | `openclaw skills list` | `openclaw skills list --agent ` | | **Check Skills** | `openclaw skills check` | `openclaw skills check --agent ` | | **Uninstall Skill** | `openclaw skills uninstall --global` | `openclaw skills uninstall --agent ` | + +--- + +## 6. Resources & Community Skills + +- 🔗 **Official Documentation**: [https://docs.openclaw.ai/tools/skills](https://docs.openclaw.ai/tools/skills) +- 🔗 **ClawHub Registry**: Search skills using `openclaw skills search ` diff --git a/docs/SKILLS/Cron.md b/docs/SKILLS/Cron.md deleted file mode 100644 index 74c0134..0000000 --- a/docs/SKILLS/Cron.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -name: cron -description: "Schedule one-shot and recurring reminders via openclaw cron CLI. Use exec, NOT the cron tool (restricted to cron job context)." -metadata: - openclaw: - emoji: "⏰" - requires: - bins: ["openclaw"] ---- - -# Cron / Reminders - -Use `exec` with the `openclaw cron` CLI. Do NOT use the built-in `cron` tool — it only works inside cron job executions, not from chat. (The `cron` tool is denied for this agent; only the CLI is available.) - -## MANDATORY — you MUST actually run the command - -You have `exec` access (`tools.profile: full`, `exec.mode: full`). You are NOT allowed to only describe what you would do. - -1. **Execute** the `openclaw cron add ...` command via `exec`. Do not skip this step. -2. **NEVER fabricate output.** Do not invent a job id (e.g. `fast-nexus`), a schedule (e.g. `Every 120,000ms`), or a "next run" time. Only report values that appear in the real command output. -3. **VERIFY** by running `openclaw cron list --json` immediately after. Confirm the new job is present. If it is NOT in the list, the creation failed — report the actual error from the `add` command instead of claiming success. -4. Report back the **real** job id, schedule, and next-run time from the `list`/`add --json` output — nothing else. - -If the `add` command errors, paste the real error and stop. Do not paper over failures with a fake success message. - -## FORBIDDEN — common failures - -- NEVER call the `cron.add` tool. Only `openclaw cron add` (CLI) is allowed. -- NEVER set `trigger.script` (or `payload.kind: "systemEvent"`). `trigger.script` is executed as **JavaScript (code-mode)**, so a shell command like `echo '...'` throws `SyntaxError: expecting ';'`. Put the reminder text in `--message "..."` instead — that is the agent payload and is delivered correctly. -- NEVER use `--session main` for non-default agents; use `--session isolated`. -- NEVER let the reminder payload trigger an action. A reminder is a NOTE to the user, not a task. Use `--command 'echo ""'` so the text is relayed verbatim via `--announce`. Do NOT use `--message` with an instruction the agent will try to execute. For a plain "remind me to X" reminder, always use the `--command echo` form below. -- NEVER use a `sleep`/background-process workaround (`sleep 120 && echo ...`, `nohup ... &`, `at`, shell loops, etc.). A background `sleep` does NOT deliver to chat — it only echoes into a detached shell and is NOT a reminder. Always create the reminder with `openclaw cron add`. -- NEVER claim "cron is disabled" / "cron is globally disabled" / "cron triggers are disabled". Cron is ENABLED. Only the agent's built-in `cron` _tool_ is denied (that is exactly why you must use the `openclaw cron add` CLI). If `openclaw cron add` errors, report the REAL error — do not invent a workaround or a disabled-system excuse. - -## How to handle ANY reminder request (free-form) - -Users will phrase requests unpredictably ("remind me to X in 2 minutes", "ping me tomorrow 3pm to Y", "every weekday at 9 standup"). There is no fixed template — **parse the request and build the command from it**: - -1. **Extract the reminder text** — what the user wants to be reminded of (strip "remind me to/that", "ping me to", etc.). This becomes the echoed string in `--command 'echo ""'`. Derive a short `--name` from it. -2. **Classify the schedule** and pick flags: - - **Relative** ("in/after N minutes/hours/seconds/days", "N minutes from now") → `--at "+Nm"` where N is the number and the unit is `s`/`m`/`h`/`d`. One-shot → add `--delete-after-run`. - - **Absolute** ("tomorrow at 3pm", "2026-08-25 15:00", "at 09:00") → `--at ""` plus `--tz ""`. One-shot → add `--delete-after-run`. - - **Recurring** ("every day at 9", "every weekday 8am", "every Monday 10:00") → `--cron "<5-field expression>"` plus `--tz`. Do NOT add `--delete-after-run` (it repeats forever). -3. **Delivery target** — deliver to the conversation where the request originated (the user's direct message). Use `--channel rocketchat --to ""`. If you cannot determine the room, ASK the user which room to deliver to. **Never default to `general`** — a personal reminder goes to the user, not a public room. -4. **Acting agent** — ALWAYS pass `--agent ` (e.g. `rc-ocrcbot` for this agent). Without it the job runs as the `main` agent, which is NOT permitted to deliver to the user's chat and fails with `error-not-allowed`. Combined with `--session isolated`, this is mandatory. -5. **Always** include `--agent --session isolated --announce --json`. -6. **Execute** the command (see MANDATORY above), then **verify** with `openclaw cron list --json`. - -### Examples (patterns — adapt to the actual words) - -Relative one-shot ("remind me to check server status after 2 minutes"): - -```bash -openclaw cron add \ - --name "Check server" \ - --at "+2m" \ - --agent rc-ocrcbot \ - --session isolated \ - --command 'echo "Time to check the server status!"' \ - --announce --channel rocketchat --to "" \ - --delete-after-run --json -``` - -Absolute one-shot ("remind me tomorrow 3pm"): - -```bash -openclaw cron add \ - --name "Meeting reminder" \ - --at "2026-08-24T15:00:00" --tz "Asia/Kolkata" \ - --agent rc-ocrcbot \ - --session isolated \ - --command 'echo "Meeting starting now"' \ - --announce --channel rocketchat --to "" \ - --delete-after-run --json -``` - -Recurring ("every weekday at 9am standup"): - -```bash -openclaw cron add \ - --name "Daily standup" \ - --cron "0 9 * * 1-5" --tz "Asia/Kolkata" \ - --agent rc-ocrcbot \ - --session isolated \ - --command 'echo "Time for daily standup!"' \ - --announce --channel rocketchat --to "" \ - --json -``` - -## List jobs - -```bash -openclaw cron list --json -``` - -> **VERIFY after every create:** always run `openclaw cron list --json` after `add` and confirm the job id from the output exists. If it is missing, the create failed — report the real error, never a fake success. - -## Remove a job - -```bash -openclaw cron rm --json -``` - -## Important flags - -- `--agent ` — the agent that runs/delivers the job. ALWAYS set this to your own agent id (e.g. `rc-ocrcbot`). Omitting it makes the job run as `main`, which is NOT allowed to deliver to the user's chat and fails with `error-not-allowed`. -- `--session isolated` — ALWAYS use `isolated`, NEVER use `main`. Using `--session main` causes delivery failures. -- `--command 'echo ""'` — the reminder payload. Runs on the Gateway and its output is delivered via `--announce`. Use this for plain reminders so the text is relayed verbatim and the agent does NOT perform the task described. -- `--announce` — delivers the command output (the reminder text) to the channel -- `--channel rocketchat` — the channel plugin name -- `--to ` — the room name (e.g. `general`) or room ID where the reminder is delivered. Use the room you received the request in (the user's DM), NOT `general`, unless the user asks for a public room. -- `--account ` — the bot account ID (e.g. `rocketbot123`), required for multi-account setups -- `--delete-after-run` — auto-remove ONE-SHOT jobs after they fire. Omit for recurring jobs. -- `--json` — get machine-readable output -- `--tz ""` — set timezone for absolute times and cron expressions (e.g. `Asia/Kolkata`) - -> **Delivery is mandatory with `--session isolated`.** An isolated job runs in a fresh session with no inherited recipient, so omitting `--channel`/`--to` (or having the channel plugin fail to resolve them) causes the runner to abort with "Refusing implicit isolated cron delivery" and the job is disabled. Always pass `--agent --announce --channel --to ` together. - -> **NEVER use `--session main`.** Always use `--session isolated` + `--agent `. The `main` session target is not permitted to deliver to the user's chat and fails with `error-not-allowed`. diff --git a/docs/SKILLS/doc.md b/docs/SKILLS/doc.md deleted file mode 100644 index aa71a86..0000000 --- a/docs/SKILLS/doc.md +++ /dev/null @@ -1,51 +0,0 @@ -# OpenClaw Skills - -Skills let you extend what your OpenClaw agent can do from scheduling reminders to integrating with third-party services. - -## 1. Create the skills folder - -Skills live inside your OpenClaw workspace, in the `skills` subfolder: - -```bash -mkdir -p ~/.openclaw/workspace/skills -``` - -Each skill gets its own subfolder inside `~/.openclaw/workspace/skills/`. - -## 2. Add a skill - -Inside each skill's folder, add a `SKILL.md` file describing what the skill does and how to use it. - -``` -~/.openclaw/workspace/skills/ - -├── cron/ -│ └── SKILL.md -└── agentmail/ - ├── SKILL.md - └── references/ -``` - -A `SKILL.md` typically includes: - -- A YAML frontmatter block (`name`, `description`, `metadata`) -- Usage instructions, required binaries, and any hard rules the agent must follow - -## 3. Example skills included - -Two ready-made example skills are included to get you started: - -- **`cron`** : schedule one-shot and recurring reminders via the `openclaw cron` CLI - Reference: [SKILLS/Cron.md](./Cron.md) - -The `cron` skill is exposed natively in the command menu (`!cron`). Other skills are used via OpenClaw core (`!skill `). - -> Copy the contents of the reference file into `~/.openclaw/workspace/skills//SKILL.md` to use it as-is, or edit it to fit your setup. - -## 5. Explore and add more skills - -Want more skills and install them like npm packages ? Check out: - -- 🔗 Awesome OpenClaw Skills (community repo): [https://github.com/VoltAgent/awesome-openclaw-skills](https://github.com/VoltAgent/awesome-openclaw-skills) -- 🔗 Skills website: [https://clawskills.sh/](https://clawskills.sh/) -- 🔗 Official docs: [https://docs.openclaw.ai/tools/skills](https://docs.openclaw.ai/tools/skills) diff --git a/openclaw.plugin.json b/openclaw.plugin.json index 2de49a8..452afa5 100644 --- a/openclaw.plugin.json +++ b/openclaw.plugin.json @@ -2,7 +2,7 @@ "id": "rocketchat", "name": "Rocket.Chat", "description": "Rocket.Chat channel plugin with DDP/websocket outbound/inbound", - "version": "1.2.17", + "version": "1.2.19", "kind": "channel", "channels": [ "rocketchat" diff --git a/package.json b/package.json index 3e28ebc..1d3bdcf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dodaa08/openclaw-plugin-test", - "version": "1.2.17", + "version": "1.2.19", "description": "A fully unified plugin for integrating Rocket.Chat with OpenClaw. This plugin eliminates the need for an external bridging server, providing a direct, single-place architecture for inbounds, outbounds, session management, and CLI configuration.", "main": "dist/index.js", "peerDependencies": { diff --git a/src/cli/config-updater.ts b/src/cli/config-updater.ts index d7fcf54..7941473 100644 --- a/src/cli/config-updater.ts +++ b/src/cli/config-updater.ts @@ -27,9 +27,6 @@ export function getAgentWorkspaceDir(agentId: string): string { return resolve(SHARED_WORKSPACE_DIR, agentId); } -// ensureSystemAgent was removed: agents.defaults.systemAgent is a legacy retired key -// in OpenClaw 2026.9.x and causes "Unrecognized key" config validation errors. - export type ExistingAccount = { accountId: string; serverUrl: string; diff --git a/src/service/inbound.ts b/src/service/inbound.ts index a466d9f..dc8bc79 100644 --- a/src/service/inbound.ts +++ b/src/service/inbound.ts @@ -32,10 +32,6 @@ export async function dispatchInboundEventWithChannelRuntime(params: { }, }); - // Core 2026.9+ SQLite stores are bound to a registered agent id (usually "main"). - // Account `agentId` (e.g. rc-oc) is only a plugin label — it is not in agents.entries. - // Passing it into resolveStorePath opens an rc-* store, then dispatch still requests - // "main" and Core throws: store path belongs to rc-oc; requested agent main. const coreAgentId = route.agentId || "main"; const botAwareSessionKey = `${route.sessionKey}:${params.accountId}:${params.event.senderId}`;