System Architecture Diagrams
Workflow Overview — Architecture Layers
Source: Workflow Overview
flowchart LR
subgraph Brain [OpenClaw — the brain]
OCs[email-normalizer<br/>sender-classifier<br/>email-classifier<br/>reply-drafter]
end
subgraph Hands [n8n — the hands]
orchestrate[Orchestration<br/>+ API integrations<br/>+ approval webhooks<br/>+ retries]
end
subgraph External [External systems]
Gmail[Gmail]
Drive[Google Drive]
Shopify[Shopify]
Gorgias[Gorgias]
Monday[Monday.com]
LogStore[Supabase<br/>audit logs]
end
Hands <--> Brain
Hands <--> External
Brain -.reads.-> External
↑ Back to top
Workflow Overview — The Full Block Flow
Source: Workflow Overview
flowchart TD
Start[New Gmail message arrives] --> A[Block A<br/>Email Ingestion<br/>n8n]
A --> B[Block B<br/>Parse & Normalize<br/>n8n + OpenClaw]
B --> C[Block C<br/>Sender / Context Resolution<br/>n8n + OpenClaw]
C --> D[Block D<br/>SOP Retrieval<br/>n8n + Google Drive]
C --> E[Block E<br/>Classification / Triage<br/>OpenClaw]
D --> E
E --> F[Block F<br/>Routing Decision<br/>n8n]
F --> G[Block G<br/>Draft Generation<br/>OpenClaw]
F --> H[Block H<br/>Monday Task Creation<br/>n8n]
G --> H
H --> I[Block I<br/>Approval Gate<br/>Monday UI + n8n webhook]
I -->|approve / edit_approve| J[Block J<br/>Send / Action Execution<br/>n8n]
I -->|escalate| K[Block K<br/>Escalation Path<br/>n8n]
I -->|reject| End1[Terminate]
J --> Done[Email sent, item closed]
K -.reviewer acts.-> I
L[(Block L<br/>Logging / Audit<br/>Supabase)]
M[Block M<br/>Evaluation / Testing]
N[Block N<br/>Failure Handling]
A & B & C & D & E & F & G & H & I & J & K -.logs.-> L
L -.read.-> M
A & B & C & D & E & F & G & H & I & J & K -.on failure.-> N
N -.escalate on exhaustion.-> K
↑ Back to top
A: Email Ingestion — Diagram
Source: A: Email Ingestion
flowchart TD
Gmail[(Gmail inbox<br/>read-only)]
Gmail -->|new message| N1[gmail_trigger<br/>Gmail Trigger]
N1 --> N2[build_raw_payload<br/>Code]
N2 --> N3[dedup_lookup<br/>HTTP Request]
N3 --> N4{dedup_branch<br/>IF}
N4 -->|duplicate| N7[log_drop_duplicate<br/>HTTP Request]
N4 -->|new| N5{noise_filter<br/>IF}
N5 -->|spam / auto / bounce /<br/>ignored sender / loopback| N8[log_drop_noise<br/>HTTP Request]
N5 -->|clean| N6[log_accept<br/>HTTP Request]
N6 --> N9[emit_to_parsing<br/>Execute Workflow]
N9 --> Next[→ Parsing & Normalization]
N7 --> AuditDB[(Audit DB)]
N8 --> AuditDB
N6 --> AuditDB
↑ Back to top
B: Email Parsing & Normalization — Diagram
Source: B: Email Parsing & Normalization
flowchart TD
classDef n8nNode fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1
classDef openclawNode fill:#ffe0b2,stroke:#e65100,stroke-width:2px,color:#bf360c
classDef externalSystem fill:#c8e6c9,stroke:#1b5e20,stroke-width:2px,color:#0d3f12
classDef failurePath fill:#f8bbd0,stroke:#880e4f,stroke-width:2px,color:#4a0e2c
classDef handoff fill:#d1c4e9,stroke:#311b92,stroke-width:2px,color:#1a0d4d
In[/raw_email_payload<br/>from Block A/]
N1[receive_payload<br/>Workflow Trigger]
N2[thread_fetcher<br/>Gmail API: full thread]
N3[attachment_fetcher<br/>Gmail API: bytes]
N4[build_skill_input<br/>Code: assemble payload]
N5[call_email_normalizer<br/>HTTP → OpenClaw skill]
N6[validate_output<br/>Code: shape check]
N7[log_to_audit<br/>HTTP → audit DB]
N8[emit_to_sender_resolution<br/>Execute Workflow]
Gmail[(Gmail<br/>read-only)]
AuditDB[(Audit DB<br/>Block L)]
BlockN[Block N<br/>retry / escalate]
BlockC([→ Block C<br/>Sender Resolution])
In --> N1 --> N2 --> N3 --> N4 --> N5 --> N6
N6 --> N7
N6 --> N8
N7 --> AuditDB
N8 --> BlockC
Gmail -.thread.-> N2
Gmail -.bytes.-> N3
N5 -. timeout / 5xx .-> BlockN
N6 -. shape invalid .-> BlockN
class N1,N2,N3,N4,N6,N7,N8 n8nNode
class N5 openclawNode
class Gmail,AuditDB externalSystem
class BlockN failurePath
class BlockC,In handoff
↑ Back to top
C: Sender / Context Resolution — Diagram
Source: C: Sender / Context Resolution
flowchart TD
classDef n8nNode fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1
classDef openclawNode fill:#ffe0b2,stroke:#e65100,stroke-width:2px,color:#bf360c
classDef toolNode fill:#fff9c4,stroke:#f57f17,stroke-width:2px,color:#5d4037
classDef externalSystem fill:#c8e6c9,stroke:#1b5e20,stroke-width:2px,color:#0d3f12
classDef failurePath fill:#f8bbd0,stroke:#880e4f,stroke-width:2px,color:#4a0e2c
classDef handoff fill:#d1c4e9,stroke:#311b92,stroke-width:2px,color:#1a0d4d
In[/normalized_email<br/>from Block B/]
N1[receive_payload<br/>Workflow Trigger]
N2[build_skill_input<br/>Code: assemble payload<br/>+ tool endpoint URLs]
N3[call_sender_classifier<br/>HTTP → OpenClaw skill]
N4[validate_output<br/>Code: shape check]
N5[log_to_audit<br/>HTTP → audit DB]
N6[emit_to_sop_and_classification<br/>Execute Workflow x2]
T1[tool: shopify_search_customer_by_email]
T2[tool: shopify_search_orders_by_number]
T3[tool: shopify_get_order_details]
T4[tool: shopify_get_customer_orders]
T5[tool: gorgias_search_tickets_by_email]
Shopify[(Shopify Admin API<br/>read-only)]
Gorgias[(Gorgias REST API<br/>read-only)]
AuditDB[(Audit DB<br/>Block L)]
BlockN[Block N<br/>retry / escalate]
BlockD([→ Block D<br/>SOP Retrieval])
BlockE([→ Block E<br/>Classification])
In --> N1 --> N2 --> N3 --> N4
N4 --> N5
N4 --> N6
N5 --> AuditDB
N6 --> BlockD
N6 --> BlockE
N3 -. tool calls .-> T1
N3 -. tool calls .-> T2
N3 -. tool calls .-> T3
N3 -. tool calls .-> T4
N3 -. tool calls .-> T5
T1 --> Shopify
T2 --> Shopify
T3 --> Shopify
T4 --> Shopify
T5 --> Gorgias
N3 -. timeout / 5xx .-> BlockN
N4 -. shape invalid .-> BlockN
class N1,N2,N4,N5,N6 n8nNode
class N3 openclawNode
class T1,T2,T3,T4,T5 toolNode
class Shopify,Gorgias,AuditDB externalSystem
class BlockN failurePath
class In,BlockD,BlockE handoff
↑ Back to top
D: SOP Retrieval — Diagram
Source: D: SOP Retrieval
flowchart TD
classDef n8nNode fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1
classDef codeNode fill:#fff9c4,stroke:#f57f17,stroke-width:2px,color:#5d4037
classDef externalSystem fill:#c8e6c9,stroke:#1b5e20,stroke-width:2px,color:#0d3f12
classDef handoff fill:#d1c4e9,stroke:#311b92,stroke-width:2px,color:#1a0d4d
In[/normalized_email + context_bundle<br/>from Block C/]
N1[receive_payload<br/>Workflow Trigger]
N2[find_active_folder<br/>Google Drive: find Active/]
N3[find_reference_folder<br/>Google Drive: find Reference/]
N4[list_active_files<br/>Google Drive: list files]
N5[list_reference_files<br/>Google Drive: list files]
N6[download_sop_files<br/>Google Drive: download binary]
N7[extract_file_contents<br/>Code: PDF → pdf-parse<br/>DOCX → mammoth<br/>MD/TXT → UTF-8]
N8[log_to_audit<br/>HTTP → audit DB]
N9[emit_to_classification_and_drafting<br/>Execute Workflow x2]
Drive[(Google Drive<br/>read-only<br/>Active/ + Reference/)]
AuditDB[(Audit DB<br/>Block L)]
BlockE([→ Block E<br/>Classification])
BlockG([→ Block G<br/>Draft Generation])
In --> N1
N1 --> N2
N1 --> N3
N2 --> N4
N3 --> N5
N4 --> N6
N5 --> N6
N6 --> N7
N7 --> N8
N7 --> N9
N8 --> AuditDB
N9 --> BlockE
N9 --> BlockG
N2 -.find by name.-> Drive
N3 -.find by name.-> Drive
N4 -.list files.-> Drive
N5 -.list files.-> Drive
N6 -.download binary.-> Drive
class N1,N2,N3,N4,N5,N6,N8,N9 n8nNode
class N7 codeNode
class Drive,AuditDB externalSystem
class In,BlockE,BlockG handoff
↑ Back to top
E: Classification / Triage — Diagram
Source: E: Classification / Triage
flowchart TD
classDef n8nNode fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1
classDef openclawNode fill:#ffe0b2,stroke:#e65100,stroke-width:2px,color:#bf360c
classDef externalSystem fill:#c8e6c9,stroke:#1b5e20,stroke-width:2px,color:#0d3f12
classDef failurePath fill:#f8bbd0,stroke:#880e4f,stroke-width:2px,color:#4a0e2c
classDef handoff fill:#d1c4e9,stroke:#311b92,stroke-width:2px,color:#1a0d4d
In1[/normalized_email<br/>from Block B/]
In2[/context_bundle<br/>from Block C/]
In3[/sop_files<br/>from Block D/]
N1[receive_payload<br/>Workflow Trigger<br/>wait for all 3 inputs]
N2[build_skill_input<br/>Code: assemble payload]
N3[call_email_classifier<br/>HTTP → OpenClaw skill]
N4[validate_output<br/>Code: shape check]
N5[log_to_audit<br/>HTTP → audit DB]
N6[emit_to_routing<br/>Execute Workflow]
AuditDB[(Audit DB<br/>Block L)]
BlockN[Block N<br/>retry / escalate]
BlockF([→ Block F<br/>Routing Decision])
In1 --> N1
In2 --> N1
In3 --> N1
N1 --> N2 --> N3 --> N4
N4 --> N5
N4 --> N6
N5 --> AuditDB
N6 --> BlockF
N3 -->|out_of_scope / non_english / internal_non_report| Exit[Exit Workflow<br/>log reason + stop]
N3 -. timeout / 5xx .-> BlockN
N4 -. shape invalid .-> BlockN
class N1,N2,N4,N5,N6 n8nNode
class N3 openclawNode
class AuditDB externalSystem
class BlockN failurePath
class In1,In2,In3,BlockF handoff
↑ Back to top
F: Routing Decision — Diagram
Source: F: Routing Decision
flowchart TD
classDef n8nNode fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1
classDef terminalNode fill:#f8bbd0,stroke:#880e4f,stroke-width:2px,color:#4a0e2c
classDef handoff fill:#d1c4e9,stroke:#311b92,stroke-width:2px,color:#1a0d4d
In[/classification_decision<br/>from Block E/]
N1[receive_payload<br/>Workflow Trigger]
N2{exit_check<br/>out_of_scope / non_english<br/>/ internal_non_report?}
N3[log_exit<br/>HTTP → audit DB<br/>TERMINATE]
N4{escalation_check<br/>escalation_flag?}
N5[override_to_lane_8<br/>Code: target = Lane 8<br/>preserve original]
N6[build_routing_payload<br/>Code: lane config lookup<br/>resolve approvers, cross-links<br/>assemble payload]
N7[log_to_audit<br/>HTTP → audit DB]
N8[emit_to_drafting<br/>Execute Workflow<br/>→ Block G if should_draft]
N9[emit_to_monday_creation<br/>Execute Workflow<br/>→ Block H]
AuditDB[(Audit DB<br/>Block L)]
BlockG([→ Block G<br/>Draft Generation])
BlockH([→ Block H<br/>Monday Task Creation])
In --> N1 --> N2
N2 -->|yes| N3
N2 -->|no| N4
N3 --> AuditDB
N4 -->|yes| N5 --> N6
N4 -->|no| N6
N6 --> N7
N7 --> N8
N7 --> N9
N7 --> AuditDB
N8 --> BlockG
N9 --> BlockH
class N1,N5,N6,N7,N8,N9 n8nNode
class N3 terminalNode
class In,BlockG,BlockH handoff
↑ Back to top
G: Draft Generation — Diagram
Source: G: Draft Generation
flowchart TD
classDef n8nNode fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1
classDef openclawNode fill:#ffe0b2,stroke:#e65100,stroke-width:2px,color:#bf360c
classDef externalSystem fill:#c8e6c9,stroke:#1b5e20,stroke-width:2px,color:#0d3f12
classDef failurePath fill:#f8bbd0,stroke:#880e4f,stroke-width:2px,color:#4a0e2c
classDef handoff fill:#d1c4e9,stroke:#311b92,stroke-width:2px,color:#1a0d4d
In1[/routing_payload<br/>from Block F/]
In2[/normalized_email<br/>from Block B/]
In3[/context_bundle<br/>from Block C/]
In4[/sop_files<br/>from Block D/]
N1[receive_payload<br/>Workflow Trigger]
N2{check_draft_mode<br/>should_draft?}
N3[emit_holding_stub<br/>Code: hardcoded template]
N4[build_skill_input<br/>Code: assemble payload]
N5[call_reply_drafter<br/>HTTP → OpenClaw skill]
N6[validate_output<br/>Code: shape check]
N7[log_to_audit<br/>HTTP → audit DB]
N8[emit_to_monday_creation<br/>Execute Workflow]
AuditDB[(Audit DB<br/>Block L)]
BlockN[Block N<br/>retry / escalate]
BlockH([→ Block H<br/>Monday Task Creation])
In1 --> N1
In2 --> N1
In3 --> N1
In4 --> N1
N1 --> N2
N2 -->|false| N3
N2 -->|true| N4
N3 --> N7
N4 --> N5 --> N6
N6 --> N7
N7 --> N8
N7 --> AuditDB
N8 --> BlockH
N5 -. timeout / 5xx .-> BlockN
N6 -. shape invalid .-> BlockN
class N1,N2,N3,N4,N6,N7,N8 n8nNode
class N5 openclawNode
class AuditDB externalSystem
class BlockN failurePath
class In1,In2,In3,In4,BlockH handoff
↑ Back to top
H: Monday Task Creation — Diagram
Source: H: Monday Task Creation
flowchart TD
classDef n8nNode fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1
classDef terminalNode fill:#f8bbd0,stroke:#880e4f,stroke-width:2px,color:#4a0e2c
classDef handoff fill:#d1c4e9,stroke:#311b92,stroke-width:2px,color:#1a0d4d
In[/routing_payload + draft_object<br/>+ normalized_email + context_bundle/]
N1[receive_payload<br/>Workflow Trigger]
N2{dedup_check<br/>item already exists?}
N3[log_dedup<br/>HTTP → audit DB<br/>TERMINATE]
N4[build_item_payload<br/>Code: assemble GraphQL mutation]
N5[create_monday_item<br/>HTTP → Monday API]
N6[post_updates<br/>HTTP → Monday API<br/>3 updates]
N7[log_to_audit<br/>HTTP → audit DB]
N8[emit_complete<br/>Item enters approval queue]
Monday[(Monday.com<br/>GraphQL API)]
AuditDB[(Audit DB<br/>Block L)]
In --> N1 --> N2
N2 -->|yes| N3
N2 -->|no| N4
N3 --> AuditDB
N4 --> N5 --> N6 --> N7 --> N8
N5 -.create item.-> Monday
N6 -.post updates.-> Monday
N7 --> AuditDB
class N1,N4,N5,N6,N7 n8nNode
class N3,N8 terminalNode
class In handoff
↑ Back to top
I: Approval Gate — Diagram
Source: I: Approval Gate
flowchart TD
classDef mondayUI fill:#c8e6c9,stroke:#1b5e20,stroke-width:2px,color:#0d3f12
classDef n8nNode fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1
classDef failurePath fill:#f8bbd0,stroke:#880e4f,stroke-width:2px,color:#4a0e2c
classDef handoff fill:#d1c4e9,stroke:#311b92,stroke-width:2px,color:#1a0d4d
Reviewer[Reviewer opens Monday item<br/>reads Updates: email, draft, reasoning]
Edit[Optional: paste edited draft<br/>as new Update]
StatusChange[Change Status column to:<br/>Approved / Edited & Approved<br/>/ Rejected / Escalated]
Webhook[Monday webhook → n8n]
N4{validate_permission<br/>reviewer authorized?}
N5[revert_status + warning]
N6{route_action}
N7[handle_approve<br/>→ Block J send]
N8[handle_edit_approve<br/>extract edited text<br/>→ Block J send]
N9[handle_reject<br/>close item]
N10[handle_escalate<br/>→ Block K]
Reviewer --> Edit --> StatusChange
Reviewer --> StatusChange
StatusChange --> Webhook --> N4
N4 -->|no| N5
N4 -->|yes| N6
N6 -->|Approved| N7
N6 -->|Edited & Approved| N8
N6 -->|Rejected| N9
N6 -->|Escalated| N10
class Reviewer,Edit,StatusChange mondayUI
class Webhook,N6,N7,N8,N9,N10 n8nNode
class N5 failurePath
class N7,N8,N10 handoff
↑ Back to top
J: Send / Action Execution — Diagram
Source: J: Send / Action Execution
flowchart TD
classDef n8nNode fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1
classDef terminalNode fill:#f8bbd0,stroke:#880e4f,stroke-width:2px,color:#4a0e2c
In[/send_payload<br/>from Block I/]
N1[receive_approval<br/>Workflow Trigger]
N2{idempotency_check<br/>already sent?}
N3[skip<br/>TERMINATE]
N4{check_manual_reply<br/>internal reply already<br/>in thread?}
N5[skip_manual_reply<br/>Status → Manually Replied<br/>post Update<br/>TERMINATE]
N6[send_gmail_reply<br/>Gmail Reply]
N7[update_monday_item<br/>HTTP → Monday API]
N8[gorgias_note<br/>HTTP → Gorgias API<br/>best-effort]
N9[log_to_audit<br/>HTTP → audit DB]
Gmail[(Gmail API)]
Monday[(Monday.com API)]
Gorgias[(Gorgias API)]
AuditDB[(Audit DB)]
In --> N1 --> N2
N2 -->|yes| N3
N2 -->|no| N4
N4 -->|yes, manual reply exists| N5
N4 -->|no| N6
N6 --> N7 --> N8 --> N9
N6 -.send.-> Gmail
N7 -.update.-> Monday
N8 -.note.-> Gorgias
N9 --> AuditDB
class N1,N6,N7,N8,N9 n8nNode
class N3,N5 terminalNode
↑ Back to top
K: Escalation Path — Diagram
Source: K: Escalation Path
flowchart TD
classDef n8nNode fill:#e3f2fd,stroke:#1565c0,stroke-width:2px,color:#0d47a1
In[/escalation trigger<br/>from E, F, G, I, or N/]
N1[receive_escalation<br/>Workflow Trigger]
N2{dedup_check<br/>existing escalation?}
N3[create_or_update_escalation<br/>Monday API: create/update item<br/>post Updates with context]
N4[log_to_audit<br/>HTTP → audit DB]
Monday[(Monday.com API)]
AuditDB[(Audit DB)]
In --> N1 --> N2 --> N3 --> N4
N3 -.create/update.-> Monday
N4 --> AuditDB
class N1,N3,N4 n8nNode
↑ Back to top
L: Logging / Audit — Diagram
Source: L: Logging / Audit
flowchart TD
A[Block A] --> Log
B[Block B] --> Log
C[Block C] --> Log
D[Block D] --> Log
E[Block E] --> Log
F[Block F] --> Log
G[Block G] --> Log
H[Block H] --> Log
I[Block I] --> Log
J[Block J] --> Log
K[Block K] --> Log
N[Block N] --> Log
Log[log_event sub-workflow<br/>fire-and-forget] --> Supa[(Supabase<br/>triage_events)]
Supa --> Trigger[DB trigger →<br/>triage_summary]
Trigger --> Summary[(triage_summary)]
Summary -.read.-> BlockM[Block M<br/>Evaluation]
Supa -.read.-> BlockM
Summary -.read.-> Ops[Ops team<br/>queries]
↑ Back to top
M: Evaluation / Testing — Diagram
Source: M: Evaluation / Testing
flowchart TD
Masked[Masked client emails<br/>50-100 real emails] --> Sandbox[Sandboxed E2E run]
AFTests[Auto-fail tests<br/>AF-1 through AF-4] --> Sandbox
Sandbox --> Gate{Go-live gate<br/>all thresholds met?}
Gate -->|no| Fix[Iterate on skills/SOPs]
Fix --> Sandbox
Gate -->|yes| Live[Live Pilot]
Live --> Trace[LangFuse tracing<br/>all OpenClaw calls]
Live --> Probes[Weekly AF probes]
Trace --> Human[Human annotation<br/>LangFuse or Monday Eval board]
Human --> Scorecard[Weekly scorecard]
Probes --> Scorecard
BlockL[(Block L<br/>Supabase)] -.read.-> Scorecard
↑ Back to top
N: Failure & Edge-Case Handling — Diagram
Source: N: Failure & Edge-Case Handling
flowchart TD
AnyBlock[Any block<br/>external call fails] --> Classify[Classify failure type]
Classify --> Retry{Retries remaining?}
Retry -->|yes| Wait[Wait per backoff]
Wait --> AnyBlock
Retry -->|no| Pending[Write to pending_triage<br/>or escalate now]
Pending --> Decision{Fallback}
Decision -->|escalate| Lane8[Lane 8<br/>with failure reason]
Decision -->|degraded| Continue[Continue with null/flag]
Decision -->|queue| Queue[(pending_triage)]
Queue --> Sched[n8n scheduler<br/>every 10 min]
Sched -->|retry| AnyBlock
Sched -->|maxed out| Lane8
Lane8 --> Log[(Block L)]
↑ Back to top