docs(n8n-webhook): add operator approval runbook
This commit is contained in:
+6
-7
@@ -4,7 +4,7 @@
|
||||
Immediate baton-pass for the next fresh implementation session.
|
||||
|
||||
## Current objective
|
||||
Run operator/polish pass (3/3): tighten operator docs, approval policy clarity, recurring verification flow, and low-noise execution reporting now that Gmail + Calendar passes are complete.
|
||||
Operator/polish pass is complete. Next fresh session should decide whether Drive / Docs / Sheets need action-bus verbs at all, while preserving the approval/history contract that now exists for Gmail + Calendar.
|
||||
|
||||
## Use these state files first
|
||||
1. `WIP.md` — full standing plan and checkpoints
|
||||
@@ -59,14 +59,13 @@ Run operator/polish pass (3/3): tighten operator docs, approval policy clarity,
|
||||
- Added docs/test payloads/validator coverage for the expanded calendar contract.
|
||||
|
||||
## Highest-priority next actions
|
||||
1. Add a compact operator command/reference section for common approval flows.
|
||||
2. Add one or two canned recurring verification flows (queue → approve → verify → cleanup).
|
||||
3. Decide/document approval defaults clearly per action family.
|
||||
4. Improve low-noise execution/result reporting in approval history.
|
||||
1. Decide whether Drive / Docs / Sheets need action-bus verbs or should stay direct-tool only.
|
||||
2. If new Google actions are added, keep approval defaults explicit by family (`notification`, `gmail`, `calendar`, `manual`).
|
||||
3. Preserve compact operator reporting (`pending_compact`, `history_compact`, `summary_line`, `result_refs`) for any new approval-backed actions.
|
||||
|
||||
## Success criteria for the next session
|
||||
- Operator/polish pass completed with docs/playbook/history-reporting improvements.
|
||||
- Approval defaults are explicit and easy to skim.
|
||||
- Clear go/no-go decision on expanding beyond Gmail + Calendar.
|
||||
- Any new verbs inherit the same safe approval defaults and low-noise history contract.
|
||||
- `WIP.md` and memory updated with concrete evidence.
|
||||
- Meaningful commit(s) captured.
|
||||
|
||||
|
||||
@@ -105,10 +105,10 @@ Started: `2026-03-12`
|
||||
- [ ] Decide whether Drive/Docs/Sheets need action-bus verbs next or can stay direct-tool only for now
|
||||
|
||||
### Then polish the operator experience
|
||||
- [ ] Add a compact operator command/reference section for common approval flows
|
||||
- [ ] Add one or two canned test payloads for real bridge verification flows
|
||||
- [ ] Decide whether some Google actions should stay approval-gated by default
|
||||
- [ ] Add low-noise reporting so history clearly shows:
|
||||
- [x] Add a compact operator command/reference section for common approval flows
|
||||
- [x] Add one or two canned test payloads for real bridge verification flows
|
||||
- [x] Decide/document approval defaults clearly per action family
|
||||
- [x] Add low-noise reporting so history clearly shows:
|
||||
- queued
|
||||
- approved/rejected
|
||||
- executed
|
||||
@@ -139,12 +139,12 @@ Planned passes:
|
||||
- added `delete_calendar_event`
|
||||
- added `list_upcoming_events`
|
||||
- updated workflow contract/docs/test payloads/bridge + WIP evidence
|
||||
3. Operator/polish pass:
|
||||
- decide approval defaults for each action
|
||||
- add low-noise execution/result reporting
|
||||
- add compact operator command/reference docs
|
||||
- add one or two canned recurring test payloads
|
||||
- update `WIP.md` with evidence before ending the pass
|
||||
3. Operator/polish pass: ✅ complete
|
||||
- documented approval defaults by action family (`notification`, `gmail`, `calendar`, `manual`)
|
||||
- added low-noise queue/history reporting (`pending_compact`, `history_compact`, `summary_line`, `result_refs`)
|
||||
- added compact operator command/reference docs
|
||||
- added two canned recurring verification payloads
|
||||
- refreshed `WIP.md` with evidence before ending the pass
|
||||
|
||||
## Fresh-session proof refresh (2026-03-12 19:44Z)
|
||||
- Re-ran both target proofs through the real approval-routed path in a clean implementation session.
|
||||
@@ -220,15 +220,60 @@ Targeted verification evidence:
|
||||
- `calendar_event_delete` → `gog calendar delete primary example-calendar-event-id --account will@example.com --json --no-input --force --send-updates none --dry-run`
|
||||
- `python3 -m py_compile skills/n8n-webhook/scripts/resolve-approval-with-gog.py` passed.
|
||||
|
||||
## Operator/polish pass 3 completion (2026-03-12)
|
||||
Implemented in this pass:
|
||||
- added explicit approval-family defaults in the shipped workflow + docs:
|
||||
- `notification` → required `high`
|
||||
- `gmail` read-only (`list_email_drafts`) → required `low`
|
||||
- `gmail` mutating (`send_email_draft`, `delete_email_draft`, `send_gmail_draft`) → required `high`
|
||||
- `calendar` read-only (`list_upcoming_events`) → required `low`
|
||||
- `calendar` mutating (`create_calendar_event`, `update_calendar_event`, `delete_calendar_event`) → required `high`
|
||||
- added compact operator-facing queue/history fields in the workflow:
|
||||
- `payload_preview`
|
||||
- `operator.summary_line`
|
||||
- `operator.execution_state`
|
||||
- `operator.result_refs`
|
||||
- `approval_queue_list.result.pending_compact`
|
||||
- `approval_queue_list.result.history_compact`
|
||||
- `approval_queue_resolve.result.item_compact`
|
||||
- `approval_history_attach_execution.result.item_compact`
|
||||
- taught the host bridge to attach `execution.summary` + `execution.result_refs`
|
||||
- added recurring verification payloads:
|
||||
- `skills/n8n-webhook/assets/test-verify-email-draft-cycle.json`
|
||||
- `skills/n8n-webhook/assets/test-verify-calendar-event-cycle.json`
|
||||
- added operator runbook / recurring verification docs in:
|
||||
- `skills/n8n-webhook/references/openclaw-action.md`
|
||||
- `skills/n8n-webhook/references/payloads.md`
|
||||
- `skills/n8n-webhook/SKILL.md`
|
||||
|
||||
Targeted verification evidence:
|
||||
- `python3 skills/n8n-webhook/scripts/validate-workflow.py skills/n8n-webhook/assets/openclaw-action.workflow.json`
|
||||
- result: `OK: workflow asset structure looks consistent`
|
||||
- validator now also checks the two new recurring verification payload files
|
||||
- `python3 -m py_compile skills/n8n-webhook/scripts/resolve-approval-with-gog.py`
|
||||
- result: passed
|
||||
- bridge helper proof via direct import/execution:
|
||||
- `execution_result_refs('gmail.drafts.create', {'draft': {'id': 'r-proof-draft-123'}})` → `{'draft_id': 'r-proof-draft-123'}`
|
||||
- `execution_summary(...)` → `gmail.drafts.create draft created (draft_id=r-proof-draft-123)`
|
||||
- `execution_result_refs('calendar.create', {'event': {'id': 'evt-proof-456'}, 'calendar': 'primary'})` → `{'event_id': 'evt-proof-456', 'calendar': 'primary'}`
|
||||
- `execution_summary(...)` → `calendar.create event created (event_id=evt-proof-456, calendar=primary)`
|
||||
- workflow asset inspection confirmed low-noise operator fields are present:
|
||||
- `pending_compact`
|
||||
- `history_compact`
|
||||
- `summary_line`
|
||||
- `result_refs`
|
||||
- `default_mode`
|
||||
- `approval.family`
|
||||
- recurring verification payload identity proofs:
|
||||
- `test-verify-email-draft-cycle.json` → request id `verify-email-draft-cycle-001`
|
||||
- `test-verify-calendar-event-cycle.json` → request id `verify-calendar-event-cycle-001`
|
||||
|
||||
## Next-session handoff
|
||||
For the next fresh implementation session, start from `HANDOFF.md` + `WIP.md` rather than from old chat context.
|
||||
|
||||
Immediate target:
|
||||
- operator/polish pass only:
|
||||
- add a compact operator command/reference section for common approval flows
|
||||
- add one or two canned recurring verification flows
|
||||
- decide/document approval defaults clearly per action family
|
||||
- improve low-noise execution/result reporting in history
|
||||
- decide whether Drive / Docs / Sheets actually need action-bus verbs or can remain direct-tool workflows for now
|
||||
- if Google action coverage expands again, preserve the same approval-family defaults and compact history contract
|
||||
- refresh WIP/memory/tasks before ending
|
||||
|
||||
## Relevant files
|
||||
|
||||
@@ -198,3 +198,28 @@
|
||||
- `gog calendar update primary example-calendar-event-id --account will@example.com --json --no-input --send-updates none --summary Updated call with vendor --from 2026-03-13T18:15:00Z --to 2026-03-13T18:45:00Z --description Updated by OpenClaw action bus. --location Updated room --dry-run`
|
||||
- `gog calendar delete primary example-calendar-event-id --account will@example.com --json --no-input --force --send-updates none --dry-run`
|
||||
- `python3 -m py_compile skills/n8n-webhook/scripts/resolve-approval-with-gog.py` passed.
|
||||
|
||||
## Operator/polish pass 3 (fresh subagent implementation, locally verified)
|
||||
- Added explicit approval families + defaults across the n8n action bus:
|
||||
- notification → required/high
|
||||
- gmail read-only → required/low
|
||||
- gmail mutating → required/high
|
||||
- calendar read-only → required/low
|
||||
- calendar mutating → required/high
|
||||
- Added low-noise operator/history reporting in the workflow:
|
||||
- `payload_preview`
|
||||
- `operator.summary_line`
|
||||
- `operator.execution_state`
|
||||
- `operator.result_refs`
|
||||
- compact list surfaces: `pending_compact`, `history_compact`, `item_compact`
|
||||
- Extended the host bridge so attached execution metadata now includes:
|
||||
- `execution.summary`
|
||||
- `execution.result_refs`
|
||||
- Added recurring verification payloads with stable proof IDs:
|
||||
- `skills/n8n-webhook/assets/test-verify-email-draft-cycle.json` → `verify-email-draft-cycle-001`
|
||||
- `skills/n8n-webhook/assets/test-verify-calendar-event-cycle.json` → `verify-calendar-event-cycle-001`
|
||||
- Local verification proofs:
|
||||
- workflow validator passed after the operator/history changes
|
||||
- bridge helper proof: `gmail.drafts.create` sample result produced `draft_id = r-proof-draft-123`
|
||||
- bridge helper proof: `calendar.create` sample result produced `event_id = evt-proof-456`, `calendar = primary`
|
||||
- workflow asset string checks confirmed presence of `pending_compact`, `history_compact`, `summary_line`, `result_refs`, `default_mode`, and `approval.family`
|
||||
|
||||
@@ -43,6 +43,8 @@ Keep the integration narrow: let OpenClaw decide what to do, and let n8n execute
|
||||
- `assets/test-list-upcoming-events.json`
|
||||
- `assets/test-update-calendar-event.json`
|
||||
- `assets/test-delete-calendar-event.json`
|
||||
- `assets/test-verify-email-draft-cycle.json`
|
||||
- `assets/test-verify-calendar-event-cycle.json`
|
||||
|
||||
## Quick usage
|
||||
|
||||
@@ -65,6 +67,7 @@ scripts/call-action.sh append_log --args '{"text":"backup complete"}' --request-
|
||||
scripts/call-action.sh get_logs --args '{"limit":5}' --pretty
|
||||
scripts/call-action.sh list_email_drafts --args '{"max":10}' --pretty
|
||||
scripts/call-action.sh list_upcoming_events --args '{"days":7,"max":10}' --pretty
|
||||
scripts/call-action.sh approval_queue_list --args '{"limit":5,"include_history":true}' --pretty
|
||||
```
|
||||
|
||||
Call a test webhook while editing a flow:
|
||||
@@ -159,6 +162,7 @@ Practical note:
|
||||
- unattended execution needs `GOG_KEYRING_PASSWORD` available to the executor because `gog`'s file keyring cannot prompt in non-TTY automation
|
||||
- the included bridge auto-loads `/home/openclaw/.openclaw/credentials/gog.env` when present, so you can keep `GOG_ACCOUNT` and `GOG_KEYRING_PASSWORD` there with mode `600`
|
||||
- for safe plumbing tests without touching Google state, add `--dry-run`
|
||||
- approval queue/history reads now expose compact `pending_compact` / `history_compact` entries plus `summary_line` + `result_refs` for low-noise operator review
|
||||
|
||||
### Add a new webhook-backed capability
|
||||
|
||||
|
||||
@@ -75,13 +75,41 @@ Behavior:
|
||||
- do **not** execute Gmail/Calendar side effects directly in the shipped starter workflow
|
||||
- are intended for host-side execution via the included `gog` bridge after explicit approval resolution
|
||||
|
||||
Approval policy defaults:
|
||||
- `send_email_draft`, `delete_email_draft`, `send_gmail_draft` / `send_approved_email`, `create_calendar_event`, `update_calendar_event`, `delete_calendar_event`
|
||||
Approval policy defaults by action family:
|
||||
- notification family
|
||||
- `send_notification_draft`
|
||||
- `approval.family = "notification"`
|
||||
- `approval.required = true`
|
||||
- `approval.mutation_level = "high"`
|
||||
- `list_email_drafts`, `list_upcoming_events`
|
||||
- `approval.required = true`
|
||||
- `approval.mutation_level = "low"` (read-only action, still routed through approval queue for explicit operator acknowledgement + audit trail)
|
||||
- approved items execute inline in n8n via the existing `notify` path
|
||||
- Gmail family
|
||||
- read-only: `list_email_drafts`
|
||||
- `approval.family = "gmail"`
|
||||
- `approval.required = true`
|
||||
- `approval.mutation_level = "low"`
|
||||
- still queued so operators must explicitly acknowledge host-side Gmail reads
|
||||
- mutating: `send_email_draft`, `delete_email_draft`, `send_gmail_draft` / `send_approved_email`
|
||||
- `approval.family = "gmail"`
|
||||
- `approval.required = true`
|
||||
- `approval.mutation_level = "high"`
|
||||
- Calendar family
|
||||
- read-only: `list_upcoming_events`
|
||||
- `approval.family = "calendar"`
|
||||
- `approval.required = true`
|
||||
- `approval.mutation_level = "low"`
|
||||
- mutating: `create_calendar_event`, `update_calendar_event`, `delete_calendar_event`
|
||||
- `approval.family = "calendar"`
|
||||
- `approval.required = true`
|
||||
- `approval.mutation_level = "high"`
|
||||
- manual/generic approvals
|
||||
- `approval_queue_add`
|
||||
- no automatic side effect is implied; the operator decides what the queued item means
|
||||
|
||||
Queue/history entries now also carry compact operator-facing fields for low-noise review:
|
||||
- `approvalQueue[].payload_preview`
|
||||
- `approvalQueue[].operator.summary_line`
|
||||
- `approvalHistory[].operator.execution_state`
|
||||
- `approvalHistory[].operator.result_refs`
|
||||
|
||||
### `approval_queue_resolve`
|
||||
|
||||
@@ -90,12 +118,20 @@ Approval policy defaults:
|
||||
- `approvalHistory`
|
||||
- supports optional notification on approval/rejection
|
||||
- executes notification drafts inline when the approved item kind is `notification`
|
||||
- returns both the full resolved item and a compact operator view at:
|
||||
- `result.item_compact`
|
||||
|
||||
### `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
|
||||
- the updated history entry now includes low-noise operator metadata such as:
|
||||
- `operator.summary_line`
|
||||
- `operator.execution_state`
|
||||
- `operator.result_refs`
|
||||
- `execution.summary`
|
||||
- returns both the full item and `result.item_compact`
|
||||
|
||||
### `fetch_and_normalize_url`
|
||||
|
||||
@@ -181,6 +217,8 @@ After import, set this manually in n8n:
|
||||
- `assets/test-list-upcoming-events.json`
|
||||
- `assets/test-update-calendar-event.json`
|
||||
- `assets/test-delete-calendar-event.json`
|
||||
- `assets/test-verify-email-draft-cycle.json`
|
||||
- `assets/test-verify-calendar-event-cycle.json`
|
||||
- `assets/test-fetch-and-normalize-url.json`
|
||||
- `assets/test-approval-queue-list.json`
|
||||
- `assets/test-inbound-event-filter.json`
|
||||
@@ -202,6 +240,8 @@ scripts/call-action.sh create_calendar_event --args-file assets/test-create-cale
|
||||
scripts/call-action.sh list_upcoming_events --args-file assets/test-list-upcoming-events.json --pretty
|
||||
scripts/call-action.sh update_calendar_event --args-file assets/test-update-calendar-event.json --pretty
|
||||
scripts/call-action.sh delete_calendar_event --args-file assets/test-delete-calendar-event.json --pretty
|
||||
scripts/call-action.sh --args-file assets/test-verify-email-draft-cycle.json --pretty
|
||||
scripts/call-action.sh --args-file assets/test-verify-calendar-event-cycle.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
|
||||
@@ -209,6 +249,76 @@ scripts/call-action.sh inbound_event_filter --args-file assets/test-inbound-even
|
||||
python3 scripts/resolve-approval-with-gog.py --id <approval-id> --decision approve --dry-run
|
||||
```
|
||||
|
||||
## Operator command reference
|
||||
|
||||
Common approval flows:
|
||||
|
||||
```bash
|
||||
# 1) inspect the queue with both full and compact views
|
||||
scripts/call-action.sh approval_queue_list --args '{"limit":10,"include_history":true}' --pretty
|
||||
|
||||
# 2) reject an item without host-side execution
|
||||
scripts/call-action.sh approval_queue_resolve \
|
||||
--args '{"id":"approval-abc123","decision":"reject","note":"not safe to run"}' \
|
||||
--pretty
|
||||
|
||||
# 3) approve through the host bridge, but keep it side-effect free
|
||||
python3 scripts/resolve-approval-with-gog.py --id approval-abc123 --decision approve --dry-run
|
||||
|
||||
# 4) approve for real through the host bridge
|
||||
python3 scripts/resolve-approval-with-gog.py --id approval-abc123 --decision approve
|
||||
|
||||
# 5) re-check recent history in compact form
|
||||
scripts/call-action.sh approval_queue_list --args '{"limit":5,"include_history":true}' --pretty
|
||||
```
|
||||
|
||||
What to look for in low-noise history output:
|
||||
- `result.pending_compact[]` and `result.history_compact[]`
|
||||
- `summary_line` for a one-line operator digest
|
||||
- `execution_state` for `pending`, `awaiting_host_execution`, `dry_run`, `executed`, or `failed`
|
||||
- `result_refs` for durable IDs such as `draft_id`, `message_id`, or `event_id`
|
||||
|
||||
## Canned recurring verification flows
|
||||
|
||||
### Gmail draft queue → approve → verify → cleanup
|
||||
|
||||
1. Queue the canned payload:
|
||||
|
||||
```bash
|
||||
scripts/call-action.sh --args-file assets/test-verify-email-draft-cycle.json --pretty
|
||||
```
|
||||
|
||||
2. Find the new approval id from `pending_compact`.
|
||||
3. Approve with the host bridge:
|
||||
|
||||
```bash
|
||||
python3 scripts/resolve-approval-with-gog.py --id <approval-id> --decision approve
|
||||
```
|
||||
|
||||
4. Re-run `approval_queue_list` and confirm the matching history item shows:
|
||||
- `execution_state = "executed"`
|
||||
- `result_refs.draft_id` populated
|
||||
5. Cleanup by queueing `assets/test-delete-email-draft.json` with the returned draft id and approving that item.
|
||||
|
||||
### Calendar event queue → approve → verify → cleanup
|
||||
|
||||
1. Queue the canned payload:
|
||||
|
||||
```bash
|
||||
scripts/call-action.sh --args-file assets/test-verify-calendar-event-cycle.json --pretty
|
||||
```
|
||||
|
||||
2. Approve with the host bridge:
|
||||
|
||||
```bash
|
||||
python3 scripts/resolve-approval-with-gog.py --id <approval-id> --decision approve
|
||||
```
|
||||
|
||||
3. Re-run `approval_queue_list` and confirm the matching history item shows:
|
||||
- `execution_state = "executed"`
|
||||
- `result_refs.event_id` populated
|
||||
4. Cleanup by queueing `assets/test-delete-calendar-event.json` with the returned `event_id` and approving that item.
|
||||
|
||||
## Expected success examples
|
||||
|
||||
### send_notification_draft
|
||||
|
||||
@@ -48,6 +48,22 @@ Recommended request shape:
|
||||
}
|
||||
```
|
||||
|
||||
## Approval defaults by family
|
||||
|
||||
- notification family
|
||||
- `send_notification_draft`
|
||||
- `approval.family = "notification"`
|
||||
- `approval.required = true`
|
||||
- `approval.mutation_level = "high"`
|
||||
- Gmail family
|
||||
- read-only: `list_email_drafts` → `approval.family = "gmail"`, `approval.mutation_level = "low"`
|
||||
- mutating: `send_email_draft`, `delete_email_draft`, `send_gmail_draft` / `send_approved_email` → `approval.family = "gmail"`, `approval.mutation_level = "high"`
|
||||
- Calendar family
|
||||
- read-only: `list_upcoming_events` → `approval.family = "calendar"`, `approval.mutation_level = "low"`
|
||||
- mutating: `create_calendar_event`, `update_calendar_event`, `delete_calendar_event` → `approval.family = "calendar"`, `approval.mutation_level = "high"`
|
||||
- manual/generic approvals
|
||||
- `approval_queue_add` leaves side effects to the operator; there is no automatic host executor for arbitrary manual kinds
|
||||
|
||||
## Live actions in the shipped workflow asset
|
||||
|
||||
### `append_log`
|
||||
@@ -362,6 +378,9 @@ Request:
|
||||
Purpose:
|
||||
- inspect pending approval items
|
||||
- optionally include recent resolved history
|
||||
- returns both raw entries and compact operator-friendly summaries at:
|
||||
- `result.pending_compact`
|
||||
- `result.history_compact`
|
||||
|
||||
### `approval_queue_resolve`
|
||||
|
||||
@@ -405,6 +424,11 @@ Request:
|
||||
Purpose:
|
||||
- patch a resolved history item with host-side execution metadata after a real executor runs outside n8n
|
||||
- intended for bridges such as `gog`-backed Gmail/Calendar execution
|
||||
- compact execution reporting should populate or expose:
|
||||
- `execution.summary`
|
||||
- `execution.result_refs`
|
||||
- `item.operator.summary_line`
|
||||
- `item.operator.execution_state`
|
||||
|
||||
### `fetch_and_normalize_url`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user