{
  "settings": {
    "executionOrder": "v1",
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false
  },
  "name": "Memory Save",
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Save Memory",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "nodes": [
    {
      "parameters": {
        "inputSource": "passthrough"
      },
      "name": "Start",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "typeVersion": 1.1,
      "position": [
        0,
        0
      ],
      "id": "mem-save-trigger"
    },
    {
      "parameters": {
        "jsCode": "const raw = $input.first().json;\n\n// sessionId comes from parent workflow via workflowInputs mapping\nconst sessionId = raw.sessionId || '';\n\n// Parse query from LLM\nlet input;\ntry { input = JSON.parse(raw.query || raw.input || '{}'); } catch(e) { input = { content: raw.query }; }\nconst content = input.content || raw.query || raw.input || '';\nconst scope = input.scope || 'user';\n\n// Determine user_id: org-scope = null, user-scope = sessionId from parent\nlet userId = null;\nif (scope !== 'org') {\n  userId = sessionId || null;\n}\n\n// Enriched memory fields (optional)\nconst tags = Array.isArray(input.tags) ? input.tags : null;\nconst entityName = input.entity_name || input.entity || null;\nconst sourceRef = input.source || 'agent';\n\n// Generate embedding\nasync function getEmbedding(text) {\n  const cfgResp = await helpers.httpRequest({ method: 'GET', url: '{{SUPABASE_URL}}/rest/v1/tools_config?tool_name=eq.embedding&select=config,enabled', headers: { 'apikey': '{{SUPABASE_SERVICE_KEY}}', 'Content-Type': 'application/json' } });\n  const cfg = (Array.isArray(cfgResp) && cfgResp.length > 0 && cfgResp[0].enabled) ? cfgResp[0].config : null;\n  if (!cfg || !cfg.api_key) return null;\n  const provider = cfg.provider || 'openai';\n  const apiKey = cfg.api_key;\n  const model = cfg.model || 'text-embedding-3-small';\n  try {\n    if (provider === 'openai') {\n      const res = await helpers.httpRequest({ method: 'POST', url: 'https://api.openai.com/v1/embeddings', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model, input: text }) });\n      return res.data[0].embedding;\n    }\n    if (provider === 'voyage') {\n      const res = await helpers.httpRequest({ method: 'POST', url: 'https://api.voyageai.com/v1/embeddings', headers: { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: model || 'voyage-3-lite', input: [text] }) });\n      return res.data[0].embedding;\n    }\n    if (provider === 'ollama') {\n      const ollamaUrl = cfg.ollama_url || 'http://localhost:11434';\n      const res = await helpers.httpRequest({ method: 'POST', url: `${ollamaUrl}/api/embed`, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ model: model || 'nomic-embed-text', input: text }) });\n      return res.embeddings[0];\n    }\n  } catch(e) { return null; }\n  return null;\n}\n\nconst embedding = await getEmbedding(content);\nconst body = {\n  content,\n  category: input.category || 'general',\n  importance: input.importance || 5,\n  user_id: userId,\n  metadata: { source: 'agent', scope }\n};\nif (tags && tags.length > 0) body.tags = tags;\nif (entityName) body.entity_name = entityName;\nif (sourceRef) body.source = sourceRef;\nif (embedding) body.embedding = JSON.stringify(embedding);\n\nconst result = await helpers.httpRequest({\n  method: 'POST',\n  url: '{{SUPABASE_URL}}/rest/v1/memory_long',\n  headers: {\n    'apikey': '{{SUPABASE_SERVICE_KEY}}',\n    'Content-Type': 'application/json',\n    'Prefer': 'return=representation'\n  },\n  body: JSON.stringify(body)\n});\n\nreturn [{ json: { success: true, saved: content, scope, user_id: userId, vectorized: !!embedding, tags: tags || [], entity_name: entityName || null } }];"
      },
      "name": "Save Memory",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        224,
        0
      ],
      "id": "mem-save-code"
    }
  ]
}