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