Skip to Content

Node Metadata Gap Analysis

Node Metadata Gap Analysis

CTO Assessment: node_metadata.json as Source of Truth

Date: 2025-10-31
File: C:\Working With AI\ai_sam\ai_sam\ai_sam\static\src\vendor_library\_registry\node_metadata.json
Total Nodes: 249


What node_metadata.json Provides

Available Fields (7 total):

{
  "icon": "file:actionNetwork.svg",
  "folder": "ActionNetwork",
  "displayName": "actionNetwork",
  "group": "transform",
  "credential_group": "ActionNetwork",
  "credential_pattern": "single",
  "credential_type": "api_key"
}

What Odoo Models Need (Field Comparison)

Model: node_types (n8n_node_types.py)

Odoo Field node_metadata.json Field Status Notes
display_name ✅ displayName MATCH Direct mapping
n8n_type ❌ MISSING GAP Need to construct: n8n-nodes-base.{displayName}
category ⚠️ group PARTIAL Maps to "transform" but needs N8N categories ("AI", "Action in an app", etc.)
description ❌ MISSING GAP No description field in metadata
icon_class ⚠️ icon PARTIAL Has SVG path, need to convert to Font Awesome class
color ❌ MISSING GAP No color field in metadata
requires_credentials ⚠️ credential_type PARTIAL Can infer: if credential_type != null, then true
default_credential_id ❌ MISSING GAP No default credential in metadata
connection_inputs ❌ MISSING GAP No input count in metadata
connection_outputs ❌ MISSING GAP No output count in metadata
parameters_json ❌ MISSING GAP No parameter schema in metadata
documentation_url ❌ MISSING GAP No documentation URL in metadata
example_workflow ❌ MISSING GAP No example in metadata
usage_count N/A N/A Runtime tracking (not in metadata)
last_used N/A N/A Runtime tracking (not in metadata)

Model: n8n.simple.node (n8n_simple_nodes.py)

Odoo Field node_metadata.json Field Status Notes
node_id ❌ MISSING GAP Need to construct: n8n-nodes-base.{displayName}
display_name ✅ displayName MATCH Direct mapping
description ❌ MISSING GAP No description field
supplier ⚠️ folder PARTIAL Folder name = supplier name (e.g., "ActionNetwork")
service ❌ MISSING GAP No service hierarchy in metadata
is_trigger ❌ MISSING GAP No trigger flag in metadata
node_type ⚠️ group PARTIAL "transform" doesn't map to "Action" or "Trigger"
categories ⚠️ group PARTIAL Only has "transform", need N8N categories
subcategories ❌ MISSING GAP No subcategories in metadata
alias ❌ MISSING GAP No search aliases in metadata

Gap Summary

✅ Available (2 fields):

  1. displayName → Direct mapping
  2. icon → SVG path (needs conversion)

⚠️ Partial (3 fields):

  1. group → Only "transform", need full N8N category mapping
  2. folder → Can extract supplier name
  3. credential_type → Can infer requires_credentials

❌ Missing (10+ critical fields):

  1. n8n_type (CRITICAL) - Official N8N node identifier
  2. description - User-facing node description
  3. color - UI color coding
  4. connection_inputs - How many inputs node accepts
  5. connection_outputs - How many outputs node produces
  6. parameters_json - Node configuration schema
  7. documentation_url - Link to N8N docs
  8. is_trigger - Action vs Trigger classification
  9. categories - Full N8N category list
  10. subcategories - Detailed categorization

CTO Assessment: Can node_metadata.json Replace Models?

Answer: NO - Insufficient Metadata

Coverage: ~20% of required fields
Usability: Cannot populate Odoo models without significant data gaps

What's Missing:

1. Node Identity (CRITICAL)

# NEED:
n8n_type = "n8n-nodes-base.gmail"  # Official identifier

# HAVE:
displayName = "gmail"  # Just the name

# PROBLEM:
# Can't construct full n8n_type reliably (some nodes use different prefixes)
# Can't validate against N8N server without official identifier

2. Node Behavior (CRITICAL)

# NEED:
connection_inputs = 1   # How to connect nodes
connection_outputs = 2  # Support for branching logic
is_trigger = False      # Action vs Trigger

# HAVE:
group = "transform"     # Vague category

# PROBLEM:
# Can't render node connections in canvas without input/output counts
# Can't filter by Action vs Trigger without is_trigger flag

3. Node Configuration (IMPORTANT)

# NEED:
parameters_json = {...}  # What fields does node accept?
description = "..."      # What does this node do?
documentation_url = "..." # Where to learn more?

# HAVE:
(nothing)

# PROBLEM:
# Can't build node configuration UI without parameter schema
# Users don't know what nodes do without descriptions

Recommendations

Option 1: Enhance node_metadata.json (Best)

Extract additional fields from N8N .node.json files:

# Enhanced metadata structure:
{
  "gmail": {
    "displayName": "Gmail",
    "n8n_type": "n8n-nodes-base.gmail",  # ADD
    "description": "Send and receive emails via Gmail",  # ADD
    "icon": "file:gmail.svg",
    "folder": "Gmail",
    "group": "transform",
    "category": "Communication",  # ADD (from N8N)
    "subcategories": ["Email"],  # ADD
    "is_trigger": false,  # ADD
    "inputs": 1,  # ADD
    "outputs": 1,  # ADD
    "color": "#dd4b39",  # ADD
    "documentation_url": "https://docs.n8n.io/...",  # ADD
    "credential_group": "Gmail",
    "credential_pattern": "oauth2",
    "credential_type": "oauth2"
  }
}

Script to generate enhanced metadata:

# C:\Working With AI\ai_sam\ai_sam\ai_sam\scripts\enhance_node_metadata.py

import json
import os

N8N_NODES_PATH = r"C:\path\to\n8n\nodes-base\nodes"
METADATA_PATH = r"C:\Working With AI\ai_sam\ai_sam\ai_sam\static\src\vendor_library\_registry\node_metadata.json"

def extract_full_metadata(node_folder):
    """Extract ALL fields from .node.json"""
    node_json_path = os.path.join(N8N_NODES_PATH, node_folder, f"{node_folder}.node.json")
    with open(node_json_path, 'r') as f:
        node_data = json.load(f)

    return {
        'displayName': node_data.get('displayName'),
        'n8n_type': node_data.get('name'),  # CRITICAL FIELD
        'description': node_data.get('description'),
        'icon': node_data.get('icon'),
        'category': node_data.get('codex', {}).get('categories', ['Uncategorized'])[0],
        'subcategories': node_data.get('codex', {}).get('subcategories', {}),
        'is_trigger': 'Trigger' in node_data.get('name', ''),
        'inputs': len(node_data.get('inputs', [])),
        'outputs': len(node_data.get('outputs', [])),
        'color': node_data.get('defaults', {}).get('color'),
        'documentation_url': node_data.get('documentationUrl'),
        # ... existing fields ...
    }

Option 2: Query N8N API Directly (Simplest)

Don't store node metadata in Odoo at all:

# ai_sam_workflows/controllers/node_registry.py

@http.route('/api/nodes/list', type='json', auth='user')
def list_nodes(self):
    """Fetch node list FROM N8N SERVER (real-time)"""
    response = requests.get(f"{N8N_SERVER}/nodes/list")
    return response.json()  # Always fresh, always complete!

Pros:
- Zero sync burden
- Always up-to-date
- No metadata gaps

Cons:
- Requires N8N server to be running
- Network latency on node list fetch


Use enhanced node_metadata.json as offline fallback, query N8N API when available:

@http.route('/api/nodes/list', type='json', auth='user')
def list_nodes(self):
    """Get node list (N8N API first, fallback to local metadata)"""
    try:
        # Try N8N server first (real-time data)
        response = requests.get(f"{N8N_SERVER}/nodes/list", timeout=2)
        return response.json()
    except:
        # Fallback to local metadata (offline mode)
        metadata_path = get_module_resource('ai_sam', 'static/src/vendor_library/_registry/node_metadata.json')
        with open(metadata_path, 'r') as f:
            return json.load(f)

Conclusion

node_metadata.json Coverage: 20%

Missing Critical Fields:

  • ❌ n8n_type (official identifier)
  • ❌ description (user-facing text)
  • ❌ connection_inputs/outputs (canvas rendering)
  • ❌ is_trigger (Action vs Trigger)
  • ❌ parameters_json (node configuration)
  • ❌ color (UI theming)

CTO Decision Required:

A. Enhance node_metadata.json (extract missing fields from N8N)?
B. Query N8N API directly (no local storage)?
C. Hybrid approach (API + fallback)?

Current state: Cannot replace Odoo models with existing metadata.


Next Steps:
1. Decide on approach (A/B/C)
2. If A: Write enhance_node_metadata.py script
3. If B: Delete all node models, implement API controller
4. If C: Implement hybrid query logic

Was this helpful?