# openclaw-action workflow This skill ships an importable workflow at: - `assets/openclaw-action.workflow.json` It implements a real local OpenClaw → n8n router. ## What it does - accepts `POST /webhook/openclaw-action` - normalizes incoming JSON into an action contract - supports these actions in the shipped asset: - `append_log` - `get_logs` - `notify` - `send_notification_draft` - `send_email_draft` - `create_calendar_event` - `approval_queue_add` - `approval_queue_list` - `approval_queue_resolve` - `approval_history_attach_execution` - `fetch_and_normalize_url` - `inbound_event_filter` - returns normalized JSON responses - returns `400` for unknown actions - returns `400` when required args are missing ## Current side effects ### `append_log` - appends records into workflow static data under key: - `actionLog` - keeps the most recent `200` entries - persists in n8n's database when the workflow execution succeeds Example stored record: ```json {"ts":"2026-03-12T07:00:00Z","source":"openclaw-action","request_id":"abc","text":"backup complete"} ``` ### `send_notification_draft` - queues an approval-gated notification proposal into workflow static data under key: - `approvalQueue` - when resolved with `decision=approve`, it executes the existing `notify` path and sends through Telegram + Discord - uses only the already-configured notification credentials in the live n8n instance ### `send_email_draft` and `create_calendar_event` - queue approval-gated proposals into workflow static data under key: - `approvalQueue` - keep the most recent `200` pending entries - do **not** send email or create provider-side calendar events in the shipped starter workflow - are designed to become safe provider-backed executors later once instance-local creds are bound in n8n ### `approval_queue_resolve` - removes one item from `approvalQueue` - appends the resolved entry into: - `approvalHistory` - supports optional notification on approval/rejection - executes notification drafts inline when the approved item kind is `notification` ### `approval_history_attach_execution` - patches an existing resolved history item in `approvalHistory` - designed for host-side executors that run outside n8n itself - used by the included `scripts/resolve-approval-with-gog.py` bridge to attach Gmail/Calendar execution results ### `fetch_and_normalize_url` - fetches a remote `http` or `https` URL from inside n8n - normalizes HTML/text/JSON into a single response shape - returns title/excerpt/body text suitable for downstream summarization or logging - uses n8n's runtime HTTP helper inside the Code node rather than relying on global `fetch` - supports optional arg `skip_ssl_certificate_validation: true` for runtimes with incomplete CA trust ### `inbound_event_filter` - classifies inbound events as `urgent`, `important`, `watch`, or `deduped` - stores recent events in: - `inboundEvents` - stores recent dedupe keys in: - `eventDedup` - can fan out a notification for urgent/important non-duplicate events ### `notify` - sends a Telegram message using credential: - `Telegram Bot (OpenClaw)` - sends a Discord message using credential: - `Discord Bot Auth` - current targets mirror the already-working reminder workflow ## Why workflow static data first Why this first: - built-in, no extra credentials - persists without guessing writable filesystem paths - good fit for queues, recent breadcrumbs, and small operational state - lets us implement safe approval-gated patterns immediately When to add provider-backed steps later: - email draft creation in Gmail/Outlook - calendar writes in Google Calendar - Airtable/Sheets append pipelines - long-retention logs or external archival ## Intentional security choice The exported workflow leaves the Webhook node auth unset in the JSON file. Why: - n8n credentials are instance-local - secrets should not be embedded in a shareable skill asset After import, set this manually in n8n: - Webhook node → **Authentication** → `Header Auth` - bind a credential with: - header name: `x-openclaw-secret` - header value: your generated shared secret ## Import steps 1. In n8n, create or open a workflow. 2. Import `assets/openclaw-action.workflow.json`. 3. Open the **Webhook** node. 4. Set **Authentication** to `Header Auth`. 5. Bind your local credential. 6. Save. 7. Use **Listen for test event** and call the test URL first. 8. Once successful, activate the workflow for production URL use. ## Expected URLs - test: `http://192.168.153.113:18808/webhook-test/openclaw-action` - prod: `http://192.168.153.113:18808/webhook/openclaw-action` ## Test payloads included - `assets/test-append-log.json` - `assets/test-notify.json` - `assets/test-send-notification-draft.json` - `assets/test-send-email-draft.json` - `assets/test-create-calendar-event.json` - `assets/test-fetch-and-normalize-url.json` - `assets/test-approval-queue-list.json` - `assets/test-inbound-event-filter.json` ## Example tests ```bash export N8N_WEBHOOK_SECRET='YOUR_SECRET_HERE' scripts/call-action.sh append_log --args '{"text":"backup complete"}' --pretty scripts/call-action.sh get_logs --args '{"limit":5}' --pretty scripts/call-action.sh notify --args '{"title":"Workflow finished","message":"n8n router test"}' --pretty scripts/call-action.sh send_notification_draft --args-file assets/test-send-notification-draft.json --pretty scripts/call-action.sh send_email_draft --args-file assets/test-send-email-draft.json --pretty scripts/call-action.sh create_calendar_event --args-file assets/test-create-calendar-event.json --pretty scripts/call-action.sh fetch_and_normalize_url --args '{"url":"http://192.168.153.113:18808/healthz"}' --pretty scripts/call-action.sh fetch_and_normalize_url --args '{"url":"https://example.com","skip_ssl_certificate_validation":true}' --pretty scripts/call-action.sh approval_queue_list --args '{"limit":10,"include_history":true}' --pretty scripts/call-action.sh inbound_event_filter --args-file assets/test-inbound-event-filter.json --pretty python3 scripts/resolve-approval-with-gog.py --id --decision approve --dry-run ``` ## Expected success examples ### send_notification_draft ```json { "ok": true, "request_id": "test-notify-draft-001", "result": { "action": "send_notification_draft", "status": "queued_for_approval", "pending_id": "approval-abc123", "approval_status": "pending" } } ``` ### send_email_draft ```json { "ok": true, "request_id": "test-email-draft-001", "result": { "action": "send_email_draft", "status": "queued_for_approval", "pending_id": "approval-abc123", "approval_status": "pending" } } ``` ### create_calendar_event ```json { "ok": true, "request_id": "test-calendar-event-001", "result": { "action": "create_calendar_event", "status": "queued_for_approval", "pending_id": "approval-def456", "approval_status": "pending" } } ``` ### fetch_and_normalize_url ```json { "ok": true, "request_id": "test-fetch-001", "result": { "action": "fetch_and_normalize_url", "status": "ok", "url": "http://192.168.153.113:18808/healthz", "title": "", "content_type": "application/json; charset=utf-8" } } ``` ### inbound_event_filter ```json { "ok": true, "request_id": "test-inbound-001", "result": { "action": "inbound_event_filter", "status": "stored", "classification": "urgent", "duplicate": false, "notified": true } } ``` ## Host bridge notes The included host bridge `scripts/resolve-approval-with-gog.py` is for the case where Gmail/Calendar auth exists on the OpenClaw host via `gog`, not inside n8n itself. Behavior: - resolves an approval item through `openclaw-action` - executes supported kinds on the host: - `email_draft` → `gog gmail drafts create` - `calendar_event` → `gog calendar create` - writes execution metadata back via `approval_history_attach_execution` Important automation note: - real unattended execution needs `GOG_KEYRING_PASSWORD` in the environment - without it, non-TTY `gog` calls will fail when the file keyring tries to prompt - `--dry-run` works without touching Google state and is useful for plumbing verification ## Validation Run the local validator before import/package changes: ```bash python3 scripts/validate-workflow.py assets/openclaw-action.workflow.json ```