Flowise Integration Guide
Flowise is a visual, drag-and-drop builder for LLM chatflows and agents — no code required to wire together LangChain nodes, retrievers, memory, and tools. Because Flowise does not have a native Nexus SDK, you add observability via the Nexus REST API: start a trace before a chatflow runs, record each node as a span, and end the trace when the flow completes. This guide covers the Custom Tool node approach, the HTTP Request node chain, the webhook handler, and an Express middleware wrapper.
How Flowise observability works
Flowise exposes a simple HTTP API (POST /api/v1/prediction/:flowId) that you call from your application. To instrument it with Nexus:
- Start a trace — POST to the Nexus REST API before calling the Flowise prediction endpoint.
- Record node spans — use a Custom Tool node inside the flow to call Nexus when individual nodes execute.
- End the trace — after the prediction response arrives (or via a Flowise webhook), PATCH the trace with token counts and finish reason.
Nexus REST API base URL
https://nexus.keylightdigital.dev/api
All requests require an Authorization: Bearer <YOUR_API_KEY> header.
REST API basics
The four REST endpoints you'll use to wrap any Flowise call:
| Method + Path | Purpose |
|---|---|
| POST /api/traces | Start a trace, returns { id } |
| POST /api/spans | Start a span within a trace, returns { id } |
| PATCH /api/spans/:id | End a span (add duration, tokens, status) |
| PATCH /api/traces/:id | End a trace (add total tokens, finish reason) |
// Minimal example — call Flowise and wrap in a Nexus trace
const NEXUS_API_KEY = process.env.NEXUS_API_KEY;
const NEXUS_BASE = 'https://nexus.keylightdigital.dev/api';
const FLOWISE_URL = 'http://localhost:3000';
const FLOW_ID = 'your-flowise-flow-id';
async function callFlowiseWithTrace(question) {
const headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + NEXUS_API_KEY,
};
// 1. Start trace
const traceRes = await fetch(NEXUS_BASE + '/traces', {
method: 'POST',
headers,
body: JSON.stringify({ name: 'flowise-chatflow', model: 'flowise' }),
});
const { id: traceId } = await traceRes.json();
let answer;
try {
// 2. Call Flowise prediction endpoint
const t0 = Date.now();
const flowRes = await fetch(
FLOWISE_URL + '/api/v1/prediction/' + FLOW_ID,
{ method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ question }) }
);
const data = await flowRes.json();
answer = data.text ?? data.answer ?? JSON.stringify(data);
// 3. End trace — success
await fetch(NEXUS_BASE + '/traces/' + traceId, {
method: 'PATCH',
headers,
body: JSON.stringify({
status: 'success',
durationMs: Date.now() - t0,
metadata: { flowId: FLOW_ID, question },
}),
});
} catch (err) {
// End trace — error
await fetch(NEXUS_BASE + '/traces/' + traceId, {
method: 'PATCH',
headers,
body: JSON.stringify({ status: 'error', error: err.message }),
});
throw err;
}
return { answer, traceId };
}
Custom Tool node approach
Flowise lets you add a Custom Tool node — a JavaScript function that runs inside the flow. You can use this to call the Nexus REST API and record a span for each tool invocation, capturing the tool name, input, output, and latency.
In the Flowise UI, create a Custom Tool node and paste the following function body. The tool receives input (the query string) and should return the tool result as a string. Set NEXUS_API_KEY and TRACE_ID as Flowise environment variables.
// Flowise Custom Tool function body
// Tool name: "NexusTracedSearch" Tool description: "Search the knowledge base and record a Nexus span."
// Set env vars: NEXUS_API_KEY, TRACE_ID (pass traceId from your caller via a Flowise variable)
const NEXUS_BASE = 'https://nexus.keylightdigital.dev/api';
const authHeaders = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + process.env.NEXUS_API_KEY,
};
// Start a span for this tool call
const spanRes = await fetch(NEXUS_BASE + '/spans', {
method: 'POST',
headers: authHeaders,
body: JSON.stringify({
traceId: process.env.TRACE_ID,
name: 'custom-tool:search',
model: 'retriever',
input: input,
}),
});
const { id: spanId } = await spanRes.json();
const t0 = Date.now();
let result = '';
try {
// Your actual tool logic here — e.g. call an external API or search index
const searchRes = await fetch('https://your-search-api.com/search?q=' + encodeURIComponent(input));
const searchData = await searchRes.json();
result = searchData.results.map(r => r.snippet).join('\n');
await fetch(NEXUS_BASE + '/spans/' + spanId, {
method: 'PATCH',
headers: authHeaders,
body: JSON.stringify({
status: 'success',
durationMs: Date.now() - t0,
output: result.slice(0, 500),
}),
});
} catch (err) {
await fetch(NEXUS_BASE + '/spans/' + spanId, {
method: 'PATCH',
headers: authHeaders,
body: JSON.stringify({ status: 'error', error: err.message, durationMs: Date.now() - t0 }),
});
throw err;
}
return result;
Because Flowise Custom Tool nodes run in an isolated context, environment variables like NEXUS_API_KEY must be configured in the Flowise .env file or the Flowise UI environment variables panel.
HTTP Request node chain
If you prefer a pure no-code approach inside Flowise, chain HTTP Request nodes to start and end a Nexus trace around your LLM calls. Add one HTTP Request node at the beginning of your flow (start trace) and another at the end (end trace), passing the traceId through a Flowise variable.
Start Trace — HTTP Request node config
Method: POST
URL: https://nexus.keylightdigital.dev/api/traces
Headers:
Content-Type: application/json
Authorization: Bearer {{$env.NEXUS_API_KEY}}
Body (JSON):
{
"name": "flowise-chatflow",
"model": "flowise",
"metadata": { "flowId": "{{$env.FLOW_ID}}" }
}
// Save response body field "id" to a Flowise variable: NEXUS_TRACE_ID
End Trace — HTTP Request node config (add after your last LLM node)
Method: PATCH
URL: https://nexus.keylightdigital.dev/api/traces/{{$vars.NEXUS_TRACE_ID}}
Headers:
Content-Type: application/json
Authorization: Bearer {{$env.NEXUS_API_KEY}}
Body (JSON):
{
"status": "success",
"metadata": { "question": "{{$input.question}}", "answer": "{{$output.text}}" }
}
Flowise HTTP Request nodes support {"{{"}$vars.VAR_NAME{{"}}"}} interpolation. Store the traceId from the start-trace response and reference it in the end-trace URL.
Webhook handler for flow completion
Flowise can POST a webhook payload to any URL when a chatflow completes. Point it at a small Express server that calls the Nexus REST API to end the trace. This is the most reliable approach when you cannot modify the flow itself — for example, when Flowise is embedded in a third-party product.
In Flowise settings, enable the webhook and set the URL to http://your-server.com/webhook/flowise. Pass traceId as a query parameter or in the webhook body.
// server.js — Express webhook handler
import express from 'express';
const app = express();
app.use(express.json());
const NEXUS_API_KEY = process.env.NEXUS_API_KEY;
const NEXUS_BASE = 'https://nexus.keylightdigital.dev/api';
app.post('/webhook/flowise', async (req, res) => {
const { traceId, text, question, totalTokens, error } = req.body;
if (!traceId) {
return res.status(400).json({ error: 'Missing traceId in webhook body' });
}
const authHeaders = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + NEXUS_API_KEY,
};
await fetch(NEXUS_BASE + '/traces/' + traceId, {
method: 'PATCH',
headers: authHeaders,
body: JSON.stringify({
status: error ? 'error' : 'success',
error: error ?? undefined,
metadata: {
question,
answer: text,
totalTokens: totalTokens ?? null,
},
}),
});
res.json({ ok: true });
});
app.listen(3001, () => console.log('Webhook handler running on :3001'));
Flowise webhook payloads include the chatflow output in the text field and session ID in sessionId. Add any additional fields you want to record as metadata on the trace.
Express middleware approach
If your application calls the Flowise API from a Node.js backend, the cleanest integration is an Express middleware that wraps every /api/v1/prediction/:flowId call in a Nexus trace automatically — no changes to your application code required.
// nexus-flowise-middleware.js
import fetch from 'node-fetch';
const NEXUS_API_KEY = process.env.NEXUS_API_KEY;
const NEXUS_BASE = 'https://nexus.keylightdigital.dev/api';
export function nexusFlowiseMiddleware(flowiseClient) {
const authHeaders = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + NEXUS_API_KEY,
};
return async function tracedPrediction(flowId, question, options = {}) {
// Start trace
const traceRes = await fetch(NEXUS_BASE + '/traces', {
method: 'POST',
headers: authHeaders,
body: JSON.stringify({
name: 'flowise/' + flowId,
model: 'flowise',
metadata: { flowId, question },
}),
});
const { id: traceId } = await traceRes.json();
const t0 = Date.now();
try {
const result = await flowiseClient.predict({ flowId, question, ...options });
await fetch(NEXUS_BASE + '/traces/' + traceId, {
method: 'PATCH',
headers: authHeaders,
body: JSON.stringify({
status: 'success',
durationMs: Date.now() - t0,
metadata: {
answer: typeof result === 'string' ? result.slice(0, 500) : JSON.stringify(result).slice(0, 500),
sessionId: options.sessionId,
},
}),
});
return { result, traceId };
} catch (err) {
await fetch(NEXUS_BASE + '/traces/' + traceId, {
method: 'PATCH',
headers: authHeaders,
body: JSON.stringify({ status: 'error', error: err.message, durationMs: Date.now() - t0 }),
});
throw err;
}
};
}
Usage
import { FlowiseClient } from 'flowise-sdk';
import { nexusFlowiseMiddleware } from './nexus-flowise-middleware.js';
const flowise = new FlowiseClient({ baseUrl: 'http://localhost:3000' });
const predict = nexusFlowiseMiddleware(flowise);
// Every call is now traced automatically
const { result, traceId } = await predict('my-flow-id', 'What is the capital of France?', {
sessionId: 'user-session-abc',
});
console.log(result, 'traceId:', traceId);
Troubleshooting
Custom Tool node cannot access process.env
Flowise sandboxes Custom Tool functions using vm2. Environment variables defined in the Flowise .env file are accessible via process.env in newer versions (v1.6+). If they are not available, pass your API key as a hardcoded string during development and switch to a secret manager or Flowise credential store for production.
Traces not appearing in Nexus dashboard
Check that your API key is correct (copy it from the Nexus Keys page) and that your requests include the Authorization: Bearer header. Use curl -X POST https://nexus.keylightdigital.dev/api/traces -H "Authorization: Bearer YOUR_KEY" -H "Content-Type: application/json" -d '{"name":"test"}' to verify connectivity before wiring up Flowise.
Webhook not receiving events
Flowise webhooks require the target URL to be publicly reachable. During local development, use ngrok http 3001 to expose your webhook handler and paste the ngrok URL into Flowise settings. For production, deploy your handler to Cloudflare Workers, Vercel, or any public URL.
Trace IDs not propagating between nodes
Flowise flows are stateless between HTTP Request nodes — you must pass the traceId through flow variables or embed it in the question payload. For the Custom Tool approach, set TRACE_ID as a Flowise environment variable or pass it via the prediction request body using a Flowise variable node.
Ready to instrument your Flowise chatflows?
Start for free — no credit card required. See traces in under 5 minutes.
Start free →