@inductiv/node-red-openai-api
Version:
Enhance your Node-RED projects with advanced AI capabilities.
259 lines • 8.73 kB
JSON
[
{
"id": "7c28d6f5b81f4cf3",
"type": "tab",
"label": "Realtime Client Secret Example",
"disabled": false,
"info": "Realtime client-secret example.\n\nThis flow demonstrates the correct nested request contract for `createRealtimeClientSecret`:\n- client-secret options such as `expires_after` stay at the top level\n- Realtime session configuration lives under `session`\n- the inject nodes cover a Realtime 2 voice-agent payload, an Audio 1.5 payload, and a translation client-secret payload",
"env": []
},
{
"id": "2b6f81da44f1b506",
"type": "comment",
"z": "7c28d6f5b81f4cf3",
"name": "Configure the red-marked node, then run either inject node.",
"info": "Before running:\n- import the flow, then configure the red-marked `OpenAI API` node with your own `Service Host`\n- this example stores request data in `msg.ai` because the `OpenAI API` node property is configured to `ai`\n- if your node uses the default property, the same shape belongs under `msg.payload`\n\nWhat this flow shows:\n- `expires_after` remains top-level request metadata\n- Realtime session fields are nested under `session`\n- `gpt-realtime-2` reasoning fields pass through unchanged\n- translation client-secret payload fields stay nested under the same `session` contract",
"x": 430,
"y": 140,
"wires": []
},
{
"id": "d48aabf237113ec2",
"type": "comment",
"z": "7c28d6f5b81f4cf3",
"name": "What is a client secret?",
"info": "A Realtime client secret is not your long-lived OpenAI API key.\n\nIt is a short-lived ephemeral token created server-side so a browser or mobile client can connect to the Realtime API without exposing the main API key.\n\nTypical flow:\n- your server or Node-RED flow creates the client secret\n- the returned `value` is passed to a trusted client application\n- that client uses the secret to open a Realtime session before it expires",
"x": 430,
"y": 200,
"wires": []
},
{
"id": "6e1099b8233f4f6f",
"type": "inject",
"z": "7c28d6f5b81f4cf3",
"name": "Create Realtime 2 Client Secret",
"props": [
{
"p": "ai.expires_after.anchor",
"v": "created_at",
"vt": "str"
},
{
"p": "ai.expires_after.seconds",
"v": "600",
"vt": "num"
},
{
"p": "ai.session.type",
"v": "realtime",
"vt": "str"
},
{
"p": "ai.session.model",
"v": "gpt-realtime-2",
"vt": "str"
},
{
"p": "ai.session.reasoning.effort",
"v": "low",
"vt": "str"
},
{
"p": "ai.session.parallel_tool_calls",
"v": "true",
"vt": "bool"
},
{
"p": "ai.session.output_modalities[0]",
"v": "audio",
"vt": "str"
},
{
"p": "ai.session.instructions",
"v": "Speak clearly and keep responses concise.",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 300,
"y": 260,
"wires": [
[
"9df67f8a39c32558"
]
]
},
{
"id": "b7fce6b60f312e8a",
"type": "inject",
"z": "7c28d6f5b81f4cf3",
"name": "Create Audio 1.5 Client Secret",
"props": [
{
"p": "ai.expires_after.anchor",
"v": "created_at",
"vt": "str"
},
{
"p": "ai.expires_after.seconds",
"v": "600",
"vt": "num"
},
{
"p": "ai.session.type",
"v": "realtime",
"vt": "str"
},
{
"p": "ai.session.model",
"v": "gpt-audio-1.5",
"vt": "str"
},
{
"p": "ai.session.output_modalities[0]",
"v": "audio",
"vt": "str"
},
{
"p": "ai.session.instructions",
"v": "Generate short audio responses.",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 290,
"y": 340,
"wires": [
[
"9df67f8a39c32558"
]
]
},
{
"id": "12b78a31f0b7b90b",
"type": "inject",
"z": "7c28d6f5b81f4cf3",
"name": "Create Translation Client Secret",
"props": [
{
"p": "ai.expires_after.anchor",
"v": "created_at",
"vt": "str"
},
{
"p": "ai.expires_after.seconds",
"v": "600",
"vt": "num"
},
{
"p": "ai.session.type",
"v": "translation",
"vt": "str"
},
{
"p": "ai.session.model",
"v": "gpt-realtime-translate",
"vt": "str"
},
{
"p": "ai.session.audio.input.noise_reduction.type",
"v": "near_field",
"vt": "str"
},
{
"p": "ai.session.audio.input.transcription.model",
"v": "gpt-realtime-whisper",
"vt": "str"
},
{
"p": "ai.session.audio.input.transcription.delay",
"v": "low",
"vt": "str"
},
{
"p": "ai.session.audio.input.turn_detection",
"v": "null",
"vt": "json"
},
{
"p": "ai.session.audio.output.language",
"v": "es",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 290,
"y": 420,
"wires": [
[
"9df67f8a39c32558"
]
]
},
{
"id": "44db7f2136c7af86",
"type": "comment",
"z": "7c28d6f5b81f4cf3",
"name": "Translation session scope",
"info": "Realtime translation uses a dedicated live session after the client secret is created.\n\nThis example only covers the server-side client-secret request contract for that flow. Live translation WebRTC or WebSocket session handling stays out of scope for this node's current Realtime surface.",
"x": 450,
"y": 500,
"wires": []
},
{
"id": "65c6ad57d8ef6d54",
"type": "comment",
"z": "7c28d6f5b81f4cf3",
"name": "Expected result: debug sidebar shows value, expires_at, and session.",
"info": "Successful responses from `createRealtimeClientSecret` return top-level `value`, `expires_at`, and `session` fields.\n\nWhat to inspect in the debug sidebar:\n- `session.type` should match the inject node you sent\n- `session.model` should match the inject node you sent\n- translation payloads should preserve nested `audio.input` and `audio.output` settings\n- `value` is the ephemeral client secret to hand to a browser or mobile client",
"x": 520,
"y": 560,
"wires": []
},
{
"id": "9df67f8a39c32558",
"type": "OpenAI API",
"z": "7c28d6f5b81f4cf3",
"name": "Create Realtime Client Secret",
"property": "ai",
"propertyType": "msg",
"service": "",
"method": "createRealtimeClientSecret",
"x": 600,
"y": 300,
"wires": [
[
"86453bdf02676d9f"
]
]
},
{
"id": "86453bdf02676d9f",
"type": "debug",
"z": "7c28d6f5b81f4cf3",
"name": "Realtime Client Secret",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 860,
"y": 360,
"wires": []
}
]