Skip to content

feat(MiniMax Node): Add standalone MiniMax vendor node (backport to release-candidate/2.17.x)#28869

Closed
n8n-assistant[bot] wants to merge 1 commit into
release-candidate/2.17.xfrom
backport-28748-to-release-candidate/2.17.x
Closed

feat(MiniMax Node): Add standalone MiniMax vendor node (backport to release-candidate/2.17.x)#28869
n8n-assistant[bot] wants to merge 1 commit into
release-candidate/2.17.xfrom
backport-28748-to-release-candidate/2.17.x

Conversation

@n8n-assistant
Copy link
Copy Markdown
Contributor

@n8n-assistant n8n-assistant Bot commented Apr 22, 2026

Description

Backport of #28748 to release-candidate/2.17.x.

Checklist for the author (@DawidMyslak) to go through.

  • Review the backport changes
  • Fix possible conflicts
  • Merge to target branch

After this PR has been merged, it will be picked up in the next patch release for release track.

Original description

Summary

Add a standalone MiniMax vendor node following the Moonshot/AlibabaCloud pattern with four resources:

  • Text > Message a Model — Chat completions with tool calling, token tracking, reasoning_split, system messages
  • Image > Generate an Image — Text-to-image with aspect ratios, multi-image, download toggle
  • Video > Generate From Text / Image — Async video generation with polling, multiple models, binary download
  • Audio > Text to Speech — 6 speech models, voice selection, emotion/speed/pitch controls

Loom Recording

Reuses the existing minimaxApi credential and icon from PR #28305.

Note: Model lists are currently static. Switching to dynamic loading via loadOptionsMethod is non-breaking and can be done once we have more details from the MiniMax team on their model listing API.

📋 Test Workflow JSON

Import into n8n and configure your MiniMax API credentials.

{"name":"MiniMax - Test All Actions","nodes":[{"parameters":{},"id":"trigger-main","name":"Run All Tests","type":"n8n-nodes-base.manualTrigger","typeVersion":1,"position":[0,780]},{"parameters":{"resource":"text","operation":"message","modelId":"MiniMax-M2.7","messages":{"values":[{"content":"What is the capital of France? Answer in one sentence.","role":"user"}]},"simplify":true,"options":{"temperature":0.7,"maxTokens":256,"hideThinking":true}},"id":"text-message-simple","name":"Text: Simple Message","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[400,0],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}},{"parameters":{"resource":"text","operation":"message","modelId":"MiniMax-M2.7","messages":{"values":[{"content":"You are a friendly pirate.","role":"assistant"},{"content":"Tell me about the weather today.","role":"user"}]},"simplify":true,"options":{"system":"You are a helpful assistant who always responds in a fun way.","temperature":0.9,"maxTokens":512,"hideThinking":true}},"id":"text-message-multiturn","name":"Text: Multi-turn + System","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[400,280],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}},{"parameters":{"resource":"text","operation":"message","modelId":"MiniMax-M2.7","messages":{"values":[{"content":"Explain quantum computing in 3 sentences.","role":"user"}]},"simplify":false,"options":{"hideThinking":false,"maxTokens":1024}},"id":"text-message-full","name":"Text: Full Response + Thinking","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[400,560],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}},{"parameters":{"resource":"text","operation":"message","modelId":"MiniMax-M2.5","messages":{"values":[{"content":"Say hello and tell me a joke.","role":"user"}]},"simplify":true,"options":{"temperature":0.5,"topP":0.9,"maxTokens":256}},"id":"text-message-m25","name":"Text: M2.5 Model","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[400,840],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}},{"parameters":{},"id":"tool-calculator","name":"Calculator","type":"@n8n/n8n-nodes-langchain.toolCalculator","typeVersion":1,"position":[400,1280]},{"parameters":{"resource":"text","operation":"message","modelId":"MiniMax-M2.7","messages":{"values":[{"content":"What is 1547 * 382 + 9281? Use the calculator tool to compute this precisely.","role":"user"}]},"simplify":true,"options":{"temperature":0.1,"maxTokens":512,"maxToolsIterations":5}},"id":"text-message-tools","name":"Text: With Calculator Tool","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[400,1120],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}},{"parameters":{"resource":"image","operation":"generate","prompt":"A cute golden retriever puppy playing in autumn leaves, photorealistic style","aspectRatio":"1:1","numberOfImages":1,"downloadImage":true,"options":{}},"id":"image-generate-download","name":"Image: Generate + Download","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[900,0],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}},{"parameters":{"resource":"image","operation":"generate","prompt":"A futuristic cityscape at sunset with flying cars, cyberpunk style","aspectRatio":"16:9","numberOfImages":2,"downloadImage":false,"options":{"promptOptimizer":true}},"id":"image-generate-url","name":"Image: URL Only + Optimizer","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[900,280],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}},{"parameters":{"resource":"image","operation":"generate","prompt":"A serene Japanese garden with cherry blossoms and a koi pond","aspectRatio":"9:16","numberOfImages":1,"downloadImage":true,"options":{"seed":42}},"id":"image-generate-seed","name":"Image: Portrait + Seed","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[900,560],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}},{"parameters":{"resource":"video","operation":"textToVideo","modelId":"MiniMax-Hailuo-2.3","prompt":"A cat stretching and yawning on a sunny windowsill, camera slowly zooms in","duration":6,"resolution":"768P","downloadVideo":true,"options":{"promptOptimizer":true}},"id":"video-t2v-download","name":"Video T2V: Download","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[1400,0],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}},{"parameters":{"resource":"video","operation":"textToVideo","modelId":"T2V-01-Director","prompt":"A drone shot flying over a mountain lake at sunrise [Pan right] [Push in]","duration":10,"resolution":"1080P","downloadVideo":false,"options":{}},"id":"video-t2v-url","name":"Video T2V: Director Model","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[1400,280],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}},{"parameters":{"resource":"video","operation":"imageToVideo","modelId":"MiniMax-Hailuo-2.3","imageInputType":"url","imageUrl":"https://cdn.hailuoai.com/prod/2024-09-18-16/user/multi_chat_file/9c0b5c14-ee88-4a5b-b503-4f626f018639.jpeg","prompt":"A mouse runs toward the camera, smiling and blinking","duration":6,"resolution":"768P","downloadVideo":true,"options":{}},"id":"video-i2v-url","name":"Video I2V: From URL","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[1400,560],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}},{"parameters":{"resource":"video","operation":"imageToVideo","modelId":"MiniMax-Hailuo-2.3","imageInputType":"binary","binaryPropertyName":"data","prompt":"The image comes to life with gentle animation","duration":6,"resolution":"768P","downloadVideo":false,"options":{}},"id":"video-i2v-binary","name":"Video I2V: From Binary","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[1400,840],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}},{"parameters":{"resource":"audio","operation":"textToSpeech","modelId":"speech-2.8-hd","text":"Hello! Welcome to the MiniMax text to speech demo. This is a test of the audio generation capabilities.","voiceId":"English_Graceful_Lady","downloadAudio":true,"options":{}},"id":"audio-tts-download","name":"Audio TTS: Download MP3","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[1900,0],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}},{"parameters":{"resource":"audio","operation":"textToSpeech","modelId":"speech-2.8-turbo","text":"Today is a wonderful day! The sun is shining and the birds are singing. Let us celebrate this beautiful moment together.","voiceId":"English_Graceful_Lady","downloadAudio":true,"options":{"speed":1.2,"volume":2,"pitch":3,"emotion":"happy","audioFormat":"wav","languageBoost":"English"}},"id":"audio-tts-options","name":"Audio TTS: All Options","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[1900,280],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}},{"parameters":{"resource":"audio","operation":"textToSpeech","modelId":"speech-2.6-hd","text":"This audio will not be downloaded. Only the URL will be returned for later use.","voiceId":"English_Graceful_Lady","downloadAudio":false,"options":{"audioFormat":"mp3"}},"id":"audio-tts-url","name":"Audio TTS: URL Only","type":"@n8n/n8n-nodes-langchain.minimax","typeVersion":1,"position":[1900,560],"credentials":{"minimaxApi":{"id":"","name":"MiniMax API"}}}],"connections":{"Run All Tests":{"main":[[{"node":"Text: Simple Message","type":"main","index":0},{"node":"Text: Multi-turn + System","type":"main","index":0},{"node":"Text: Full Response + Thinking","type":"main","index":0},{"node":"Text: M2.5 Model","type":"main","index":0},{"node":"Image: Generate + Download","type":"main","index":0},{"node":"Image: URL Only + Optimizer","type":"main","index":0},{"node":"Image: Portrait + Seed","type":"main","index":0},{"node":"Video T2V: Download","type":"main","index":0},{"node":"Video T2V: Director Model","type":"main","index":0},{"node":"Video I2V: From URL","type":"main","index":0},{"node":"Audio TTS: Download MP3","type":"main","index":0},{"node":"Audio TTS: All Options","type":"main","index":0},{"node":"Audio TTS: URL Only","type":"main","index":0},{"node":"Text: With Calculator Tool","type":"main","index":0}]]},"Calculator":{"ai_tool":[[{"node":"Text: With Calculator Tool","type":"ai_tool","index":0}]]},"Image: Generate + Download":{"main":[[{"node":"Video I2V: From Binary","type":"main","index":0}]]}},"active":false,"settings":{"executionOrder":"v1"},"meta":{"templateCredsSetupCompleted":true}}

Related Linear tickets

https://linear.app/n8n/issue/NODE-4760

Review / Merge checklist

  • I have seen this code, I have run this code, and I take responsibility for this code.
  • PR title and summary are descriptive. (conventions)
  • Docs updated or follow-up ticket created.
  • Tests included.
  • PR Labeled with Backport to Beta, Backport to Stable, or Backport to v1 (if the PR is an urgent fix that needs to be backported)

Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
(cherry picked from commit 0295369)
@n8n-assistant n8n-assistant Bot added automation:backport core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team labels Apr 22, 2026
@n8n-assistant n8n-assistant Bot requested a review from DawidMyslak April 22, 2026 08:31
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 21 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/@n8n/nodes-langchain/nodes/vendors/MiniMax/actions/video/generate.i2v.operation.ts">

<violation number="1" location="packages/@n8n/nodes-langchain/nodes/vendors/MiniMax/actions/video/generate.i2v.operation.ts:67">
P2: Require `Subject Reference Image URL` in URL mode to avoid building invalid `subject_reference` payloads with empty image values.</violation>

<violation number="2" location="packages/@n8n/nodes-langchain/nodes/vendors/MiniMax/actions/video/generate.i2v.operation.ts:67">
P2: Make `Last Frame Image URL` required when URL input is selected to prevent sending empty `last_frame_image` values.</violation>
</file>
Architecture diagram
sequenceDiagram
    participant n8n as n8n Engine
    participant Creds as Credential Store
    participant Node as NEW: MiniMax Node
    participant Router as NEW: Action Router
    participant Actions as NEW: Resource Operations
    participant Transport as NEW: Transport Layer
    participant MiniMax as MiniMax API
    participant Tools as n8n AI Tools

    n8n->>Node: execute()
    Node->>Router: router.call(this)

    loop For each input item
        Router->>Actions: NEW: execute operation (text|image|video|audio)
        
        Actions->>Transport: apiRequest(method, endpoint, body)
        Transport->>Creds: getCredentials("minimaxApi")
        Creds-->>Transport: API Key & Base URL
        Transport->>MiniMax: HTTP Request (Auth Header + JSON)
        MiniMax-->>Transport: JSON Response
        Transport-->>Actions: Parsed Response

        alt Resource: Text (with tool calling)
            loop Tool Iteration (up to maxToolsIterations)
                Actions->>Actions: Check finish_reason == 'tool_calls'
                opt Tool Calls Present
                    Actions->>Tools: getConnectedTools() / invoke()
                    Tools-->>Actions: Tool Output
                    Actions->>Transport: apiRequest (send tool results)
                    Transport->>MiniMax: POST /chat/completions
                    MiniMax-->>Transport: Updated Completion
                end
            end
        else Resource: Video (Async Polling)
            loop Poll status until Success/Fail (max 60 attempts)
                Actions->>Transport: NEW: pollVideoTask(taskId)
                Transport->>MiniMax: GET /query/video_generation
                MiniMax-->>Transport: status (Processing | Success)
                Note over Transport,MiniMax: Wait 15s between attempts
            end
            Actions->>Transport: NEW: getVideoDownloadUrl(fileId)
            Transport->>MiniMax: GET /files/retrieve
            MiniMax-->>Transport: download_url
        end

        opt downloadBinary is true (Image/Video/Audio)
            Actions->>n8n: helpers.httpRequest (GET download_url)
            n8n->>MiniMax: Download Binary File
            MiniMax-->>n8n: Binary Data (Buffer)
            Actions->>n8n: helpers.prepareBinaryData()
        end

        Actions-->>Router: INodeExecutionData[]
    end

    Router-->>Node: Return Execution Data
    Node-->>n8n: Output Data
Loading

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

displayName: 'Image URL',
name: 'imageUrl',
type: 'string',
default: '',
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Require Subject Reference Image URL in URL mode to avoid building invalid subject_reference payloads with empty image values.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/@n8n/nodes-langchain/nodes/vendors/MiniMax/actions/video/generate.i2v.operation.ts, line 67:

<comment>Require `Subject Reference Image URL` in URL mode to avoid building invalid `subject_reference` payloads with empty image values.</comment>

<file context>
@@ -0,0 +1,380 @@
+		displayName: 'Image URL',
+		name: 'imageUrl',
+		type: 'string',
+		default: '',
+		required: true,
+		placeholder: 'https://example.com/image.jpg',
</file context>
Fix with Cubic

displayName: 'Image URL',
name: 'imageUrl',
type: 'string',
default: '',
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Make Last Frame Image URL required when URL input is selected to prevent sending empty last_frame_image values.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/@n8n/nodes-langchain/nodes/vendors/MiniMax/actions/video/generate.i2v.operation.ts, line 67:

<comment>Make `Last Frame Image URL` required when URL input is selected to prevent sending empty `last_frame_image` values.</comment>

<file context>
@@ -0,0 +1,380 @@
+		displayName: 'Image URL',
+		name: 'imageUrl',
+		type: 'string',
+		default: '',
+		required: true,
+		placeholder: 'https://example.com/image.jpg',
</file context>
Fix with Cubic

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 22, 2026

Merging this PR will degrade performance by 80.99%

❌ 12 regressed benchmarks
✅ 20 untouched benchmarks
⏩ 20 skipped benchmarks1

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
vm micro: Script Compilation - cache hit (repeated expression) 357.5 µs 538.8 µs -33.64%
vm micro: Data Complexity - shallow access (depth 1) 284.1 µs 470.8 µs -39.65%
vm micro: Array Element Access - map 100 elements 278.2 µs 454 µs -38.73%
vm micro: Array Element Access - single element 277.3 µs 893.8 µs -68.98%
vm micro: Data Complexity - deep access (depth 6) 278.6 µs 461.7 µs -39.65%
vm: Extension Call - isEmpty 1.3 ms 7.1 ms -80.99%
vm: Conditional - ternary 1.3 ms 1.6 ms -15.12%
vm: Simple Property - large data 1.4 ms 1.5 ms -10.63%
vm: Simple Property - medium data 1.3 ms 2.4 ms -44.44%
vm: Extension Call - toUpperCase 1.3 ms 1.5 ms -11.19%
vm: Conditional - nullish coalescing 1.3 ms 1.8 ms -24.35%
vm: Nested Property - depth 3 1.4 ms 1.6 ms -10.84%

Comparing backport-28748-to-release-candidate/2.17.x (a5bd9c5) with master (0295369)2

Open in CodSpeed

Footnotes

  1. 20 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on release-candidate/2.17.x (bc9cbea) during the generation of this report, so master (0295369) was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@github-actions
Copy link
Copy Markdown
Contributor

Performance Comparison

Comparing currentlatest master14-day baseline

Memory consumption baseline with starter plan resources

Metric Current Latest Master Baseline (avg) vs Master vs Baseline Status
memory-rss-baseline 225.60 MB 348.40 MB 289.80 MB (σ 40.90) -35.2% -22.2% ⚠️
memory-heap-used-baseline 114.92 MB 114.27 MB 114.47 MB (σ 0.24) +0.6% +0.4% ⚠️

docker-stats

Metric Current Latest Master Baseline (avg) vs Master vs Baseline Status
docker-image-size-runners 386.00 MB 386.00 MB 392.13 MB (σ 11.18) +0.0% -1.6%
docker-image-size-n8n 1269.76 MB 1269.76 MB 1273.60 MB (σ 10.49) +0.0% -0.3%

Idle baseline with Instance AI module loaded

Metric Current Latest Master Baseline (avg) vs Master vs Baseline Status
instance-ai-heap-used-baseline 186.40 MB 186.50 MB 186.43 MB (σ 0.25) -0.1% -0.0%
instance-ai-rss-baseline 388.15 MB 392.12 MB 368.35 MB (σ 22.82) -1.0% +5.4%
How to read this table
  • Current: This PR's value (or latest master if PR perf tests haven't run)
  • Latest Master: Most recent nightly master measurement
  • Baseline: Rolling 14-day average from master
  • vs Master: PR impact (current vs latest master)
  • vs Baseline: Drift from baseline (current vs rolling avg)
  • Status: ✅ within 1σ | ⚠️ 1-2σ | 🔴 >2σ regression

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 22, 2026

Bundle Report

Changes will increase total bundle size by 10.42kB (0.02%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
editor-ui-esm 45.71MB 10.42kB (0.02%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: editor-ui-esm

Assets Changed:

Asset Name Size Change Total Size Change (%)
assets/worker-*.js 4.65kB 3.17MB 0.15%
assets/constants-*.js 225 bytes 3.14MB 0.01%
assets/index-*.js 336 bytes 1.31MB 0.03%
assets/ParameterInputList-*.js -15 bytes 1.27MB -0.0%
assets/users.store-*.js -67 bytes 1.05MB -0.01%
assets/core-*.js 168 bytes 623.13kB 0.03%
assets/usePostMessageHandler-*.js 74 bytes 137.05kB 0.05%
assets/useRootStore-*.js 4.63kB 131.22kB 3.66%
assets/canvas.eventBus-*.js -72 bytes 117.4kB -0.06%
assets/NodeCreator-*.js 121 bytes 104.04kB 0.12%
assets/useCanvasOperations-*.js 90 bytes 95.48kB 0.09%
assets/NodeSettings-*.js 82 bytes 84.68kB 0.1%
assets/settings.store-*.js -18 bytes 79.8kB -0.02%
assets/NodeCreator-*.css 142 bytes 76.87kB 0.19%
assets/ProjectSettings-*.js 164 bytes 74.18kB 0.22%
assets/AppSidebar-*.js -2 bytes 32.13kB -0.01%
assets/SettingsAiGatewayView-*.js -19 bytes 9.95kB -0.19%
assets/OAuthConsentView-*.js -14 bytes 9.94kB -0.14%
assets/useSettingsItems-*.js -12 bytes 5.99kB -0.2%
assets/SettingsLayout-*.js -2 bytes 5.19kB -0.04%
assets/useAiGateway-*.js -48 bytes 1.37kB -3.39%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automation:backport core Enhancement outside /nodes-base and /editor-ui n8n team Authored by the n8n team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant