Files
swarm-zap/memory/2026-03-12.md

13 KiB

2026-03-12

n8n local documentation fix

  • Documented the local n8n-agent service in TOOLS.md after noticing it had been set up but not captured in workspace notes.
  • Recorded current known service details from prior host/runtime evidence:
    • port 18808 -> 5678
    • LAN/Tailscale URLs
    • dedicated agent-oriented n8n instance
    • 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.
  • Finished local skill skills/n8n-webhook for authenticated webhook-first n8n integration, including scripts/call-webhook.sh, scripts/call-action.sh, scripts/validate-workflow.py, an importable assets/openclaw-action.workflow.json, sample payloads, payload notes, and a successful package/validation run to /tmp/n8n-skill-dist/n8n-webhook.skill.
  • The shipped openclaw-action workflow intentionally leaves Webhook authentication unset in export JSON; after import, bind local n8n Header Auth credentials manually using x-openclaw-secret so secrets are not embedded in the skill asset.
  • Live n8n API access was confirmed and used on 2026-03-12 against http://192.168.153.113:18808 (public API + existing webhook credential available in the instance).
  • Created and activated live workflow openclaw-action via the n8n API.
  • First live implementation matched the original asset shape (Webhook -> Set -> Switch -> Respond) but failed at runtime: executions errored in the normalize-request Set node with invalid syntax on its expressions.
  • Fix: replaced the live router logic and shipped asset implementation with a simpler, working internal design: Webhook -> Code -> Respond to Webhook, while preserving the external contract (append_log, notify, normalized JSON success/failure responses).
  • Important operational note: the workflow initially activated without a usable production route because the Webhook node lacked a webhookId; adding one and re-publishing was necessary for proper webhook registration.
  • Current state before compaction: the live openclaw-action workflow exists in n8n, is active, and has been updated to the simpler Code-node implementation; post-update live response testing was still in progress at compaction time.
  • After compaction, live verification succeeded against the production webhook:
    • append_log returned 200 with normalized JSON success payload
    • notify returned 200 with normalized JSON success payload
    • unknown action returned 400 with { code: "unknown_action" }
  • The packaged skill artifact was refreshed after the router simplification at /tmp/n8n-skill-dist/n8n-webhook.skill.
  • Follow-up implementation for real side effects:
    • notify was successfully wired to the existing Telegram + Discord credentials and verified live multiple times.
    • append_log hit two dead ends before settling on the clean solution:
      1. Execute Command node was unavailable in this n8n build (Unrecognized node type: n8n-nodes-base.executeCommand).
      2. Read/Write Files from Disk was available, but candidate paths were either missing or not writable in this container/runtime.
    • Final fix: switched append_log to use n8n workflow static data ($getWorkflowStaticData('global')) under key actionLog, capped to the latest 200 entries.
    • Verified persisted state via the n8n API: staticData.global.actionLog contains the live test record for request live-log-003.
    • Conclusion: for small recent operational breadcrumbs, workflow static data is the right sink here; MinIO is better reserved for later archival/rotation/export use cases rather than tiny per-event appends.
  • Added action get_logs to the live openclaw-action workflow and local n8n-webhook skill.
    • get_logs reads from workflow static data key actionLog
    • default limit 20, clamped to 1..50, newest-first
    • verified live with request live-getlogs-001 returning the seed record from live-log-004
  • Re-verified the three live actions together after the update:
    • append_log → success
    • get_logs → success
    • notify → success
  • Refreshed packaged skill artifact again at /tmp/n8n-skill-dist/n8n-webhook.skill.
  • Will clarified a standing operating preference: treat local n8n as an assistant tool to use proactively when appropriate, not as something needing separate approval each time.
  • Extended the shipped skills/n8n-webhook router asset beyond the original live trio (append_log, get_logs, notify) to add:
    • send_email_draft
    • create_calendar_event
    • approval_queue_add
    • approval_queue_list
    • approval_queue_resolve
    • fetch_and_normalize_url
    • inbound_event_filter
  • Design choice for the new actions: keep the starter workflow immediately usable without new provider credentials by using n8n workflow static data for approval queue/history/event state, while leaving room to wire provider-backed email/calendar executors later.
  • Updated local docs, validator, and sample payloads for the expanded action bus and re-ran local structural validation successfully.
  • Live n8n re-import/update was not completed in this pass because the current session did not have a verified safe path into the already-running instance (no confirmed admin/browser path and no confirmed current webhook secret for live test calls).
  • Follow-up in the next direct session: recovered the already-verified live n8n API path from the earlier session log and used it to deploy the expanded openclaw-action workflow in place.
  • Live verification of the expanded action set after deployment:
    • append_log200
    • get_logs200
    • send_email_draft200 (approval-queued)
    • create_calendar_event200 (approval-queued)
    • approval_queue_add200
    • approval_queue_list200
    • approval_queue_resolve200
    • inbound_event_filter200
    • notify200
    • unknown action → 400 with unknown_action
  • fetch_and_normalize_url initially failed in the Code node because global fetch was unavailable; a second attempt using Node built-ins failed because module imports were disallowed in the n8n runtime.
  • Final fix for URL fetching: switched fetch_and_normalize_url to n8n's runtime helper this.helpers.httpRequest, which worked. Added optional arg skip_ssl_certificate_validation: true for environments where the container CA bundle is insufficient.
  • Verified fetch_and_normalize_url live with:
    • local HTTP URL http://192.168.153.113:18808/healthz → success
    • https://example.com with skip_ssl_certificate_validation: true → success
  • Cleanup: resolved the temporary verification approval items so approvalQueue ended empty after testing.
  • State check before attempting deeper executor work: the live n8n instance currently exposes only four credentials via the public API — Discord Bot Auth, Telegram Bot (OpenClaw), OpenClaw Webhook Header, and Header Auth account. No Gmail/Google Calendar credentials were present, so provider-backed email/calendar execution was intentionally not faked.
  • Implemented the first true approval-gated executor that matches currently available creds:
    • new action send_notification_draft
    • queues a pending notification in approvalQueue
    • when approved via approval_queue_resolve, it executes the existing notify path and sends through Telegram + Discord
  • Verified live end-to-end on 2026-03-12:
    • send_notification_draft returned 200 and produced pending id approval-mmnr8pyq-tjxiqkps
    • approving that item via approval_queue_resolve returned executed: true and executed_action: "notify"
    • approval_queue_list showed pending_count: 0 afterward and recorded the execution metadata in history
  • Will explicitly reinforced a durable operating expectation: local n8n, including its live public API, should be treated as assistant-owned tooling. If the correct path is the n8n API, use it directly instead of re-asking for permission or acting blocked.
  • After Google Workspace auth was completed with gog, headless testing showed an important automation constraint: real non-TTY gog calls fail unless GOG_KEYRING_PASSWORD is present, because the current gog file keyring backend cannot prompt in automation. However, gog --dry-run for Gmail draft creation and Calendar event creation works without unlocking the keyring, which made it possible to fully validate executor plumbing safely.
  • Implemented a host-side bridge script at skills/n8n-webhook/scripts/resolve-approval-with-gog.py.
    • flow: resolve approval in n8n → execute supported kinds on host via gog → write execution metadata back into n8n history
    • supported host-executed kinds:
      • email_draftgog gmail drafts create
      • calendar_eventgog calendar create
  • Expanded the live openclaw-action workflow with new action approval_history_attach_execution, allowing host-side executors to patch resolved history entries with execution status/details.
  • Live dry-run verification on 2026-03-12 succeeded end-to-end:
    • queued one email_draft approval item and one calendar_event item
    • resolved both via the new host bridge with --dry-run
    • gog returned dry-run JSON for both operations without touching Google state
    • approvalHistory entries were updated in n8n with execution metadata:
      • email draft item id approval-mmnsx7iz-k26qb60cexecution.op = gmail.drafts.create, status = dry_run
      • calendar item id approval-mmnsx7ji-3rt7yd74execution.op = calendar.create, status = dry_run
  • Current practical next step for real Gmail/Calendar execution: provide GOG_KEYRING_PASSWORD to the runtime environment that will invoke the bridge script, or switch gog to a keyring backend that supports unattended access on this host.
  • Follow-up completion on 2026-03-12:
    • stored local-only Gog automation env in /home/openclaw/.openclaw/credentials/gog.env with restrictive permissions (600)
    • updated resolve-approval-with-gog.py to auto-load that file when present
    • verified non-interactive headless Gmail access works using the stored env (successful gog gmail search ... --json --no-input)
    • verified the bridge itself auto-loads the env file by resolving a fresh email_draft approval item in --dry-run mode and attaching execution metadata successfully without manually exporting GOG_ACCOUNT / GOG_KEYRING_PASSWORD
  • Real direct Google sanity checks succeeded after that:
    • created a Gmail draft to william.valentin.info@gmail.com with subject Test draft from zap
    • deleted the same draft successfully and verified removal via follow-up 404 notFound
  • Created top-level state file WIP.md to track the current Google Workspace + n8n integration plan, status, completed work, and next steps.
  • Updated memory/tasks.json so the overlapping Google Workspace / calendar / email tasks moved from open to in-progress and now point at the current WIP file.
  • Will explicitly noted a durable capability reminder: zap also has access to Will's own Gitea repo on the LAN and can use it when repo-backed tracking/sync is useful.
  • Real end-to-end Google execution via n8n approval + gog bridge was completed (non-dry-run) for both target flows:
    • Gmail draft flow (send_email_draft): queued, approved through resolve-approval-with-gog.py, verified with gog gmail drafts get, and deleted with gog gmail drafts delete --force.
      • approval id: approval-mmnvjcak-qcuhbzqd
      • draft id: r348335896293726096
      • subject: [zap n8n e2e] Gmail draft test 20260312T194153Z
    • Calendar event flow (create_calendar_event): queued, approved through the same bridge, verified with gog calendar get primary <eventId>, and deleted with gog calendar delete primary <eventId> --force.
      • approval id: approval-mmnvjyo5-uezhcw84
      • event id: il3ojkfnsnq3uhlepvrmaklpq4
      • title: [zap n8n e2e] Calendar test 20260312T194222Z
  • Important command-shape notes captured from the live run:
    • gog calendar get and gog calendar delete expect <calendarId> <eventId> argument order.
    • gog gmail drafts delete required --force for non-interactive cleanup.
  • Will also set a new operating preference for context use: for non-trivial implementation work, prepare file-based state/handoff (WIP.md, HANDOFF.md as needed), then start a fresh isolated implementation session/run instead of continuing inside a bloated main-session context window.
  • Implemented that preference locally by:
    • adding a Fresh-session implementation discipline section to AGENTS.md
    • creating HANDOFF.md as the immediate baton-pass file for the next clean implementation session
    • updating WIP.md with a Next-session handoff section