feat(skill): add n8n action-bus helper

This commit is contained in:
zap
2026-03-12 06:51:15 +00:00
parent 7a44225481
commit 295809b161
4 changed files with 225 additions and 42 deletions

View File

@@ -9,4 +9,4 @@
- `openclaw-ping` webhook path tested end-to-end
- Operating note: prefer narrow webhook-first integration rather than broad n8n admin/API access.
- Will clarified the primary host LAN IP to use/document is `192.168.153.113`.
- Drafted local skill `skills/n8n-webhook` for authenticated webhook-first n8n integration, including `scripts/call-webhook.sh`, payload notes, and a successful package/validation run to `/tmp/n8n-skill-dist/n8n-webhook.skill`.
- Drafted local skill `skills/n8n-webhook` for authenticated webhook-first n8n integration, including `scripts/call-webhook.sh`, `scripts/call-action.sh`, payload notes, and a successful package/validation run to `/tmp/n8n-skill-dist/n8n-webhook.skill`.

View File

@@ -1,6 +1,6 @@
---
name: n8n-webhook
description: Trigger authenticated local n8n webhooks on the LAN for OpenClaw-to-n8n integration. Use when calling safe, narrow workflows on the dedicated local n8n-agent instance, such as ping/test endpoints, action-bus style workflows, notifications, logging, or other preapproved webhook entrypoints. Do not use for broad n8n admin/API management, workflow mutation, credential management, or unrestricted orchestration.
description: Trigger authenticated local n8n webhooks on the LAN for OpenClaw-to-n8n integration. Use when calling safe, narrow workflows on the dedicated local n8n-agent instance, such as ping/test endpoints, an action-bus style router workflow, notifications, logging, or other preapproved webhook entrypoints. Do not use for broad n8n admin/API management, workflow mutation, credential management, or unrestricted orchestration.
---
# N8n Webhook
@@ -15,11 +15,12 @@ Keep the integration narrow: let OpenClaw decide what to do, and let n8n execute
## Policy
1. Prefer named webhook entrypoints over generic admin APIs.
2. Send JSON and expect JSON back.
3. Use header auth by default (`x-openclaw-secret`).
4. Use `/webhook-test/` only while building/editing a workflow.
5. Surface non-2xx responses clearly instead of pretending success.
6. If a new workflow is needed, define its request/response contract before wiring callers.
2. Prefer one small router webhook (`openclaw-action`) when several agent-safe actions are needed.
3. Send JSON and expect JSON back.
4. Use header auth by default (`x-openclaw-secret`).
5. Use `/webhook-test/` only while building/editing a workflow.
6. Surface non-2xx responses clearly instead of pretending success.
7. If a new workflow is needed, define its request/response contract before wiring callers.
## Quick usage
@@ -29,40 +30,56 @@ Set the shared secret once for the shell session:
export N8N_WEBHOOK_SECRET='replace-me'
```
Call a production webhook:
Call a production webhook directly:
```bash
scripts/call-webhook.sh openclaw-ping --data '{"message":"hello from OpenClaw"}'
```
Call the preferred action-bus route:
```bash
scripts/call-action.sh append_log --args '{"text":"backup complete"}'
```
Call a test webhook while editing a flow:
```bash
scripts/call-webhook.sh openclaw-ping --test --data '{"message":"hello from OpenClaw"}'
```
Pretty-print JSON response:
```bash
scripts/call-webhook.sh openclaw-ping --pretty --data '{"message":"hello"}'
scripts/call-action.sh notify --args '{"message":"hello from OpenClaw"}' --test --pretty
```
## Workflow
### Call an existing safe webhook
### Call an existing safe webhook directly
1. Confirm the target webhook path is already intended for agent use.
2. Use `scripts/call-webhook.sh` with JSON input.
3. Treat any non-2xx response as a failure that needs investigation.
Use `scripts/call-webhook.sh` when the path is already defined and there is no benefit to the action-bus wrapper.
Current known endpoint:
Current known direct endpoint:
- `openclaw-ping` — basic end-to-end connectivity check
### Call the action bus
Use `scripts/call-action.sh` when the n8n side exposes a router webhook such as `openclaw-action`.
Payload shape:
```json
{
"action": "append_log",
"args": {
"text": "backup complete"
},
"request_id": "optional-uuid"
}
```
This keeps the external surface small while letting n8n route internally.
### Add a new webhook-backed capability
1. Write down the webhook path, required auth, request JSON, and response JSON.
2. If the shape is more than trivial, read `references/payloads.md` first.
2. If the path should become part of the shared action bus, document the `action` name and `args` shape in `references/payloads.md`.
3. Keep the first version small and explicit.
4. Only add the new endpoint to regular use after a successful `/webhook-test/` run.
@@ -71,8 +88,10 @@ Current known endpoint:
- `N8N_BASE_URL` — override base URL (default `http://192.168.153.113:18808`)
- `N8N_WEBHOOK_SECRET` — required shared secret for authenticated calls
- `N8N_SECRET_HEADER` — header name (default `x-openclaw-secret`)
- `N8N_ACTION_PATH` — router path for `call-action.sh` (default `openclaw-action`)
## Resources
- `scripts/call-webhook.sh` — authenticated POST helper for local n8n webhooks
- `references/payloads.md` — suggested request/response contracts and naming conventions
- `scripts/call-webhook.sh` — authenticated POST helper for direct local n8n webhooks
- `scripts/call-action.sh` — wrapper for action-bus style calls against `openclaw-action`
- `references/payloads.md` — request/response contracts and naming conventions

View File

@@ -25,52 +25,88 @@ Recommended success response:
}
```
## Recommended contract for new endpoints
## Preferred router endpoint
Prefer a stable JSON shape like:
### `openclaw-action`
Purpose:
- keep the external n8n surface small
- route several agent-safe operations behind one authenticated webhook
Recommended request shape:
```json
{
"action": "append_log",
"args": {
"text": "backup complete"
},
"request_id": "optional-uuid"
}
```
Recommended success response:
```json
{
"ok": true,
"request_id": "optional-uuid",
"result": {
"...": "workflow-specific payload"
"status": "accepted"
}
}
```
On failure, return a non-2xx status plus:
Recommended failure response:
```json
{
"ok": false,
"error": {
"code": "short-machine-code",
"message": "human-readable summary"
"code": "unknown_action",
"message": "action is not supported"
}
}
```
## Naming guidance
## Suggested initial actions
- Use lowercase kebab-case webhook paths.
- Keep names explicit: `openclaw-ping`, `openclaw-action`, `append-log`, `send-notify`.
- Avoid generic names like `run`, `task`, or `webhook1`.
### `append_log`
## Suggested action-bus pattern
If multiple agent-safe actions are needed, prefer one router webhook such as `openclaw-action`.
Request shape:
Request:
```json
{
"action": "append_log",
"args": {
"text": "backup finished"
},
"request_id": "optional-uuid"
"text": "backup complete"
}
}
```
That keeps the external surface small while letting n8n route internally.
Purpose:
- append a short line to a known log or tracking sink
### `notify`
Request:
```json
{
"action": "notify",
"args": {
"message": "workflow finished",
"title": "optional title"
}
}
```
Purpose:
- send a small notification through a known downstream channel
## Naming guidance
- Use lowercase kebab-case for webhook paths.
- Use lowercase snake_case or kebab-case consistently for action names; prefer snake_case for JSON actions if using switch/router logic.
- Keep names explicit: `openclaw-ping`, `openclaw-action`, `append_log`, `notify`.
- Avoid generic names like `run`, `task`, or `webhook1`.

View File

@@ -0,0 +1,128 @@
#!/usr/bin/env bash
set -euo pipefail
usage() {
cat <<'EOF'
Usage:
scripts/call-action.sh <action> [--args '{"k":"v"}'] [--args-file args.json] [--request-id <id>] [--path openclaw-action] [--test] [--pretty] [--dry-run]
Environment:
N8N_ACTION_PATH Default router webhook path (default: openclaw-action)
N8N_WEBHOOK_SECRET Shared secret for header auth
N8N_BASE_URL Base n8n URL (default: http://192.168.153.113:18808)
N8N_SECRET_HEADER Header name (default: x-openclaw-secret)
Examples:
scripts/call-action.sh append_log --args '{"text":"backup complete"}'
scripts/call-action.sh notify --args-file notify.json --test --pretty
EOF
}
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
CALL_WEBHOOK="$SCRIPT_DIR/call-webhook.sh"
ACTION_PATH="${N8N_ACTION_PATH:-openclaw-action}"
ACTION=""
ARGS='{}'
ARGS_FILE=""
REQUEST_ID=""
MODE_FLAG=""
PRETTY=0
DRY_RUN=0
EXTRA_ARGS=()
while [[ $# -gt 0 ]]; do
case "$1" in
--help|-h)
usage
exit 0
;;
--args)
ARGS="${2:?missing value for --args}"
shift 2
;;
--args-file)
ARGS_FILE="${2:?missing value for --args-file}"
shift 2
;;
--request-id)
REQUEST_ID="${2:?missing value for --request-id}"
shift 2
;;
--path)
ACTION_PATH="${2:?missing value for --path}"
shift 2
;;
--test)
MODE_FLAG="--test"
shift
;;
--prod)
MODE_FLAG="--prod"
shift
;;
--pretty)
PRETTY=1
shift
;;
--dry-run)
DRY_RUN=1
shift
;;
--*)
echo "Unknown option: $1" >&2
usage >&2
exit 2
;;
*)
if [[ -z "$ACTION" ]]; then
ACTION="$1"
else
EXTRA_ARGS+=("$1")
fi
shift
;;
esac
done
if [[ -z "$ACTION" ]]; then
usage >&2
exit 2
fi
if [[ ${#EXTRA_ARGS[@]} -gt 0 ]]; then
echo "Unexpected extra arguments: ${EXTRA_ARGS[*]}" >&2
exit 2
fi
if [[ -n "$ARGS_FILE" ]]; then
ARGS="$(cat "$ARGS_FILE")"
fi
PAYLOAD="$({
python3 - <<'PY' "$ACTION" "$ARGS" "$REQUEST_ID"
import json, sys
action = sys.argv[1]
args = json.loads(sys.argv[2])
request_id = sys.argv[3]
if not isinstance(args, dict):
raise SystemExit('Action args must decode to a JSON object.')
payload = {
'action': action,
'args': args,
}
if request_id:
payload['request_id'] = request_id
print(json.dumps(payload, separators=(',', ':')))
PY
} )"
CMD=("$CALL_WEBHOOK" "$ACTION_PATH" --data "$PAYLOAD")
[[ -n "$MODE_FLAG" ]] && CMD+=("$MODE_FLAG")
[[ "$PRETTY" -eq 1 ]] && CMD+=(--pretty)
[[ "$DRY_RUN" -eq 1 ]] && CMD+=(--dry-run)
exec "${CMD[@]}"