Skip to Content

Architecture

Architecture

Original file: ARCHITECTURE.mermaid
Type: MERMAID


```mermaid
---
title: SAM AI Workflows Base - System Architecture
---

graph TB
    subgraph "Frontend Layer (ai_sam module)"
        UI[Visual Workflow Canvas<br/>JavaScript + React]
        Builder[Workflow Builder UI]
        Viewer[Execution Viewer UI]
    end

    subgraph "Data Layer (ai_sam_workflows_base)"
        Canvas[canvas<br/>Workflow Definitions]
        Executions[executions<br/>Execution Logs]
        Templates[workflow.template<br/>Reusable Templates]
        Nodes[nodes<br/>DEPRECATED Phase 1]
        Credentials[api_credentials<br/>API Keys]
        BusinessUnit[workflow.business.unit<br/>Org Units]
    end

    subgraph "Execution Engine"
        Executor[Workflow Executor]
        NodeRunner[Node Runner]
        ErrorHandler[Error Handler & Retry]
        Trigger[Trigger Handler<br/>Webhook, Cron, Manual]
    end

    subgraph "N8N Integration"
        JSONParser[N8N JSON Parser]
        NodeRegistry[Node Type Registry<br/>195 N8N Nodes]
        ContentNodes[SAM Content Nodes]
        AgentNodes[AI Agent Nodes]
    end

    subgraph "External Services"
        OpenAI[OpenAI API]
        Slack[Slack API]
        GitHub[GitHub API]
        Webhooks[External Webhooks]
        CustomAPIs[Custom APIs]
    end

    %% Frontend connections
    UI --> Builder
    UI --> Viewer
    Builder -->|save_canvas_state| Canvas
    Viewer -->|load execution logs| Executions

    %% Data Layer connections
    Canvas -->|json_definition| JSONParser
    Canvas -->|creates| Executions
    Templates -->|create_from_template| Canvas
    Canvas --> BusinessUnit
    Canvas --> Credentials

    %% Execution flow
    Canvas -->|action_execute_workflow| Executor
    Executor --> NodeRunner
    Executor --> ErrorHandler
    Executor -->|logs to| Executions
    Trigger -->|triggers| Executor

    %% N8N Integration
    JSONParser --> NodeRegistry
    JSONParser --> ContentNodes
    JSONParser --> AgentNodes
    NodeRunner --> NodeRegistry

    %% External Services
    NodeRunner -.->|API calls| OpenAI
    NodeRunner -.->|API calls| Slack
    NodeRunner -.->|API calls| GitHub
    Trigger -.->|receives| Webhooks
    NodeRunner -.->|API calls| CustomAPIs
    Credentials -.->|provides credentials| NodeRunner

    %% Styling
    classDef frontend fill:#e1f5ff,stroke:#01579b,stroke-width:2px
    classDef data fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px
    classDef engine fill:#fff9c4,stroke:#f57f17,stroke-width:2px
    classDef n8n fill:#f3e5f5,stroke:#4a148c,stroke-width:2px
    classDef external fill:#ffebee,stroke:#b71c1c,stroke-width:2px,stroke-dasharray: 5 5
    classDef deprecated fill:#fce4ec,stroke:#880e4f,stroke-width:1px,stroke-dasharray: 3 3

    class UI,Builder,Viewer frontend
    class Canvas,Executions,Templates,Credentials,BusinessUnit data
    class Nodes deprecated
    class Executor,NodeRunner,ErrorHandler,Trigger engine
    class JSONParser,NodeRegistry,ContentNodes,AgentNodes n8n
    class OpenAI,Slack,GitHub,Webhooks,CustomAPIs external

Data Model Relationships

---
title: SAM AI Workflows Base - Data Model ERD
---

erDiagram
    %% Core Workflow Models
    CANVAS ||--o{ EXECUTIONS : creates
    CANVAS }o--o| WORKFLOW_TEMPLATE : created_from
    CANVAS }o--o| WORKFLOW_BUSINESS_UNIT : belongs_to
    CANVAS ||--o{ NODES : contains

    %% Template System
    WORKFLOW_TEMPLATE ||--o{ WORKFLOW_TEMPLATE_TAG : tagged_with
    WORKFLOW_TEMPLATE }o--|| RES_USERS : authored_by

    %% Execution System
    EXECUTIONS }o--|| CANVAS : executes
    EXECUTIONS }o--|| RES_USERS : executed_by

    %% API Credentials
    CANVAS }o--o{ API_CREDENTIALS : uses

    %% N8N Integration
    CANVAS }o--o{ NODE_TYPES : uses_node_types
    NODE_TYPES }o--|| N8N_NODE_CATEGORY : categorized_by

    %% Business Organization
    WORKFLOW_BUSINESS_UNIT ||--o{ CANVAS : organizes

    %% Model Definitions
    CANVAS {
        int id PK
        string name
        text json_definition
        string execution_mode
        string workflow_type
        int business_unit_id FK
        int template_id FK
        boolean nodes_cache_valid
        text generated_python_code
        text generated_javascript_code
    }

    EXECUTIONS {
        int id PK
        int canvas_id FK
        string state
        datetime started_at
        datetime finished_at
        float duration
        text error_message
        text execution_log
        json node_executions
    }

    WORKFLOW_TEMPLATE {
        int id PK
        string name
        text json_definition
        string category
        string visibility
        int author_id FK
        int usage_count
        boolean is_validated
    }

    WORKFLOW_TEMPLATE_TAG {
        int id PK
        string name
    }

    API_CREDENTIALS {
        int id PK
        string name
        string credential_type
        string api_key
        string oauth_access_token
    }

    WORKFLOW_BUSINESS_UNIT {
        int id PK
        string name
        string code
        text description
    }

    NODES {
        int id PK
        int canvas_id FK
        string node_id
        string node_type
        json parameters
        int position_x
        int position_y
    }

    NODE_TYPES {
        int id PK
        string name
        string node_type
        int category_id FK
        json metadata
    }

    N8N_NODE_CATEGORY {
        int id PK
        string name
        string code
    }

    RES_USERS {
        int id PK
        string name
        string login
    }

Workflow Execution Flow

---
title: Workflow Execution Sequence
---

sequenceDiagram
    actor User
    participant UI as Visual Canvas
    participant Canvas as Canvas Model
    participant Execution as Execution Model
    participant NodeRunner as Node Runner
    participant ExtAPI as External API

    User->>UI: Click "Execute Workflow"
    UI->>Canvas: action_execute_workflow()

    Canvas->>Execution: create(state='pending')
    Execution-->>Canvas: execution_id

    Canvas->>Execution: _execute_workflow()
    Note over Execution: Parse json_definition

    Execution->>Execution: Find start node
    Execution->>Execution: _execute_node_chain(start_node)

    loop For each node in chain
        Execution->>NodeRunner: _execute_single_node(node, input)
        NodeRunner->>NodeRunner: Get node type & parameters

        alt Node type: HTTP Request
            NodeRunner->>ExtAPI: HTTP call with params
            ExtAPI-->>NodeRunner: Response data
        else Node type: Email Send
            NodeRunner->>ExtAPI: Send email via SMTP
            ExtAPI-->>NodeRunner: Success
        else Node type: Logic
            NodeRunner->>NodeRunner: Process logic (if/switch)
        end

        NodeRunner-->>Execution: node_result {success, data}
        Execution->>Execution: Log to node_executions JSON
        Execution->>Execution: Pass output to next node
    end

    alt Execution successful
        Execution->>Execution: Update state='success'
    else Execution failed
        Execution->>Execution: Update state='failed'
        Execution->>Execution: Log error_message
    end

    Execution-->>Canvas: Execution complete
    Canvas-->>UI: {success, execution_id, results}
    UI-->>User: Show execution results

Template Creation and Usage Flow

---
title: Workflow Template Lifecycle
---

stateDiagram-v2
    [*] --> CreateWorkflow: User creates workflow

    state CreateWorkflow {
        [*] --> BuildCanvas: Add nodes
        BuildCanvas --> ConnectNodes: Connect nodes
        ConnectNodes --> TestWorkflow: Test execution
        TestWorkflow --> RefineWorkflow: Fix errors
        RefineWorkflow --> BuildCanvas: Iterate
    }

    CreateWorkflow --> SaveAsTemplate: User saves as template

    state SaveAsTemplate {
        [*] --> FillMetadata: Name, description, category
        FillMetadata --> AddDocumentation: Add usage docs
        AddDocumentation --> SetVisibility: Private/Team/Public/Marketplace
    }

    SaveAsTemplate --> TemplateCreated: Template saved

    state TemplateCreated {
        [*] --> Validation
        Validation --> Validated: action_validate_template()
    }

    TemplateCreated --> BrowseMarketplace: Others browse templates

    state BrowseMarketplace {
        [*] --> SearchTemplates: Filter by category/tags
        SearchTemplates --> PreviewTemplate: action_preview_template()
        PreviewTemplate --> SelectTemplate: User selects
    }

    BrowseMarketplace --> CreateFromTemplate: action_create_workflow()

    CreateFromTemplate --> CustomizeWorkflow: User customizes
    CustomizeWorkflow --> SaveWorkflow: Workflow saved
    SaveWorkflow --> IncrementUsageCount: template.usage_count++

    IncrementUsageCount --> [*]

    style CreateWorkflow fill:#e1f5ff
    style SaveAsTemplate fill:#fff9c4
    style TemplateCreated fill:#c8e6c9
    style BrowseMarketplace fill:#f3e5f5

N8N JSON Structure

---
title: N8N JSON Format (Single Source of Truth)
---

graph TD
    JSON[canvas.json_definition]

    JSON --> Nodes[nodes Array]
    JSON --> Connections[connections Object]
    JSON --> Settings[settings Object]

    Nodes --> Node1[Node Object]
    Nodes --> Node2[Node Object]
    Nodes --> NodeN[...]

    Node1 --> NodeID[id: string]
    Node1 --> NodeName[name: string]
    Node1 --> NodeType[type: string]
    Node1 --> NodePos[position: x,y]
    Node1 --> NodeParams[parameters: object]

    Connections --> ConnKey[Node Name]
    ConnKey --> ConnType[Connection Type]
    ConnType --> ConnArray[Array of connections]
    ConnArray --> TargetNode[node, type, index]

    Settings --> ExecOrder[executionOrder: v1]
    Settings --> Timeout[timeout: ms]

    style JSON fill:#714B67,color:#fff
    style Nodes fill:#e1f5ff
    style Connections fill:#fff9c4
    style Settings fill:#c8e6c9

Flatline Migration - Phase 1 vs Phase 2

---
title: Data Storage Evolution
---

graph LR
    subgraph "Pre-Phase 1 (Deprecated)"
        OldJSON[json_definition<br/>Backup]
        OldNodes[nodes table<br/>SOURCE OF TRUTH]
        OldConn[connections table<br/>Relationships]

        OldJSON -.->|rebuild_nodes_cache| OldNodes
        OldNodes --> OldConn
    end

    subgraph "Phase 1 (Current - 2025-10-31)"
        JSON[json_definition<br/>SOURCE OF TRUTH]
        NodesCache[nodes table<br/>Cache DEPRECATED]

        JSON -->|Optional cache| NodesCache
        NodesCache -.->|Legacy support| JSON
    end

    subgraph "Phase 2 (Planned)"
        FinalJSON[json_definition<br/>ONLY SOURCE]

        FinalJSON -.->|Direct parse| Executor
    end

    OldJSON ==>|Migration| JSON
    JSON ==>|Future| FinalJSON

    style OldJSON fill:#ffcdd2,stroke:#c62828
    style OldNodes fill:#ffcdd2,stroke:#c62828
    style OldConn fill:#ffcdd2,stroke:#c62828
    style JSON fill:#c8e6c9,stroke:#2e7d32
    style NodesCache fill:#fff9c4,stroke:#f57f17
    style FinalJSON fill:#81c784,stroke:#1b5e20

Node Execution Types

---
title: Node Type Execution Strategy
---

flowchart TD
    Start([Node Execution Starts]) --> GetType{Get Node Type}

    GetType -->|Trigger| TriggerNode[Execute Trigger Node]
    GetType -->|Action| ActionNode[Execute Action Node]
    GetType -->|Logic| LogicNode[Execute Logic Node]
    GetType -->|Data Transform| DataNode[Execute Data Node]

    TriggerNode --> TriggerTypes{Trigger Type}
    TriggerTypes -->|Webhook| Webhook[Wait for webhook call]
    TriggerTypes -->|Cron| Cron[Schedule with Odoo cron]
    TriggerTypes -->|Manual| Manual[User triggered]

    ActionNode --> ActionTypes{Action Type}
    ActionTypes -->|HTTP| HTTP[Make HTTP request]
    ActionTypes -->|Email| Email[Send email]
    ActionTypes -->|Database| Database[Query database]
    ActionTypes -->|API Call| APICall[Call external API]

    LogicNode --> LogicTypes{Logic Type}
    LogicTypes -->|IF| IF[Evaluate condition]
    LogicTypes -->|Switch| Switch[Multiple branches]
    LogicTypes -->|Merge| Merge[Merge inputs]

    DataNode --> DataTypes{Data Type}
    DataTypes -->|Set| Set[Set variables]
    DataTypes -->|Function| Function[Execute JS code]
    DataTypes -->|Transform| Transform[Transform data]

    HTTP --> Success{Success?}
    Email --> Success
    Database --> Success
    APICall --> Success
    IF --> Success
    Switch --> Success
    Merge --> Success
    Set --> Success
    Function --> Success
    Transform --> Success

    Success -->|Yes| LogResult[Log to node_executions]
    Success -->|No| LogError[Log error message]

    LogResult --> NextNode[Pass output to next node]
    LogError --> RetryLogic{Retry?}

    RetryLogic -->|Yes, retry < 3| GetType
    RetryLogic -->|No| FailExecution[Mark execution as failed]

    NextNode --> End([End])
    FailExecution --> End

    Webhook --> End
    Cron --> End
    Manual --> NextNode

    style Start fill:#e1f5ff
    style End fill:#e1f5ff
    style Success fill:#fff9c4
    style LogResult fill:#c8e6c9
    style LogError fill:#ffcdd2
    style FailExecution fill:#ef9a9a

Deployment Architecture

---
title: SAM AI Workflows - Production Deployment
---

graph TB
    subgraph "Client Layer"
        Browser[Web Browser]
    end

    subgraph "Load Balancer"
        LB[Nginx / HAProxy]
    end

    subgraph "Odoo Application Servers"
        Odoo1[Odoo Instance 1<br/>ai_sam_workflows_base + ai_sam]
        Odoo2[Odoo Instance 2<br/>ai_sam_workflows_base + ai_sam]
    end

    subgraph "Database Layer"
        PG_Primary[(PostgreSQL<br/>Primary)]
        PG_Replica[(PostgreSQL<br/>Replica)]
    end

    subgraph "Background Workers"
        Worker1[Workflow Executor<br/>Worker 1]
        Worker2[Workflow Executor<br/>Worker 2]
        Cron[Odoo Cron<br/>Scheduled Workflows]
    end

    subgraph "External Integration Layer"
        OpenAI[OpenAI API]
        Slack[Slack API]
        GitHub[GitHub API]
        Webhooks[Webhook Receiver]
    end

    Browser --> LB
    LB --> Odoo1
    LB --> Odoo2

    Odoo1 --> PG_Primary
    Odoo2 --> PG_Primary

    PG_Primary --> PG_Replica

    Odoo1 --> Worker1
    Odoo2 --> Worker2
    Odoo1 --> Cron

    Worker1 -.->|API calls| OpenAI
    Worker1 -.->|API calls| Slack
    Worker2 -.->|API calls| GitHub
    Webhooks -.->|triggers| Worker1

    style Browser fill:#e1f5ff
    style LB fill:#fff9c4
    style PG_Primary fill:#c8e6c9
    style Worker1 fill:#f3e5f5
    style Worker2 fill:#f3e5f5
    style Cron fill:#ffe0b2

Note: These diagrams are written in Mermaid syntax and can be rendered in:
- GitHub (automatic rendering in .md files)
- GitLab (automatic rendering)
- VS Code (with Mermaid Preview extension)
- Online: https://mermaid.live

Last Updated: December 10, 2025

```

Was this helpful?