Skip to content

n8n HTTP Request

This guide shows you how to set up an n8n workflow to call agents and tools in Agent Studio.

  • n8n instance
  • OAuth Client credentials from your Alation instance or a Server Admin role to create one.

Follow the Authentication Guide to create an OAuth 2.0 Client in your Alation instance. Make sure to note down the client_id and client_secret as you will need them to obtain an access token.

We can use n8n’s HTTP Request node to obtain an access token.

  1. Add an HTTP Request node to your workflow.

  2. Fill in the following fields to configure the node:

    FieldValue
    MethodPOST
    URLhttps://[your-instance].alationcloud.com/oauth/v2/token/
    AuthenticationNone
    Send Query ParametersOff
    Send HeadersOn
    Header Parametersaccept: application/json
    content-type: application/x-www-form-urlencoded
    Send BodyOn
    Body Content TypeForm Urlencoded
    Body Parametersgrant_type: client_credentials
    client_id: [your-client-id]
    client_secret: [your-client-secret]

    Example configuration screenshots Authentication Methods Authentication Methods

  3. Execute step to test the node and obtain an access token.

  1. Add another HTTP Request node to your workflow.

  2. Fill in the following fields to configure the node:

    FieldValue
    MethodPOST
    URLAgent/tool stream endpoint url
    AuthenticationNone
    Send Query ParametersOff
    Send HeadersOn
    Header ParametersAuthorization: Bearer {{ $('Get Auth Token').item.json["access_token"] }}
    Content-Type: application/json
    Accept: text/event-stream
    Send BodyOn
    Body Content TypeJSON
    Body ParametersRelevant input parameters for the agent/tool
    Response OptionResponse Format: Text
    Put Output in Field: data

    Example configuration screenshots Authentication Methods Authentication Methods

  3. Execute step to test the node and call the agent/tool.

As of writing, n8n does not natively support parsing streamed responses. To handle streamed responses, you can use a Code node to parse the data received from the HTTP Request node.

  1. Add a Code in Javascript node to your workflow.

  2. Add code to parse the streamed response.

    Example code snippet to parse streamed responses
    // Parse the complete streaming response from n8n HTTP Request node
    let streamText = '';
    if ($input.item.json && $input.item.json.data) {
    streamText = $input.item.json.data;
    } else if (typeof $input.item.json === 'string') {
    streamText = $input.item.json;
    } else if ($input.item.binary && $input.item.binary.data) {
    streamText = $input.item.binary.data.toString('utf-8');
    } else {
    return {
    error: 'Could not find stream text in response',
    csvAssetId: null,
    chartAssetId: null,
    chatId: null,
    hasCsvAsset: false,
    hasChartAsset: false
    };
    }
    let csvAssetId = null;
    let chartAssetId = null;
    let chatId = null;
    const lines = streamText.split('\n');
    for (const line of lines) {
    if (!line.trim() || line.startsWith(': ping')) continue;
    if (line.startsWith('data: ')) {
    const data = line.slice(6);
    if (data === '[DONE]') continue;
    try {
    const parsed = JSON.parse(data);
    if (parsed.chat_id && !chatId) chatId = parsed.chat_id;
    if (parsed.model_message && parsed.model_message.parts) {
    for (const part of parsed.model_message.parts) {
    if (part.part_kind === 'tool-return' && part.metadata) {
    for (const meta of part.metadata) {
    if (meta.kind === 'sql' && meta.id) csvAssetId = meta.id;
    if (meta.kind === 'chart' && meta.id) chartAssetId = meta.id;
    }
    }
    }
    }
    } catch (e) {}
    }
    }
    return {
    csvAssetId: csvAssetId,
    chartAssetId: chartAssetId,
    chatId: chatId,
    hasCsvAsset: !!csvAssetId,
    hasChartAsset: !!chartAssetId
    };
  3. Execute step to test the node and parse the streamed response.

If your agent/tool call returns asset IDs (e.g., CSV or Chart asset IDs), you can add additional Code nodes to fetch and process these assets as needed.

Example code snippet to fetch a CSV asset
// n8n Function node
const DEFAULT_HOST = "https://[your-instance].mtse.alationcloud.com";
const token = (() => {
try {
return $("Get Auth Token").first().json.access_token;
} catch {
return undefined;
}
})();
const envBase = $env.ALATION_BASE_URL; // optional
const buildBase = (b) => {
let u = (b || envBase || DEFAULT_HOST).replace(/\/+$/, "");
if (!/\/ai\/api\/v1\/assets$/.test(u)) u += "/ai/api/v1/assets";
return u;
};
const toRecords = (items) => {
const out = [];
for (const it of items) {
const payload = it.json ?? it;
if (Array.isArray(payload)) out.push(...payload);
else out.push(payload);
}
return out;
};
const preview = (s) =>
s ? String(s).slice(0, 80) + (String(s).length > 80 ? "…" : "") : "(empty)";
const incoming = $input.all();
const records = toRecords(incoming);
const results = [];
for (const rec of records) {
const base = buildBase(rec.baseUrl);
const chatId = rec.chatId;
let csvContent = null;
let chartBase64 = null;
let csvStatus = null;
let chartStatus = null;
let csvErr = null;
let chartErr = null;
// --- CSV: fetch if we have an id + chatId (ignore hasCsvAsset flag) ---
if (rec.csvAssetId && chatId) {
const csvUrl = `${base}/${rec.csvAssetId}?chat_id=${chatId}`;
try {
const resp = await this.helpers.request({
method: "GET",
url: csvUrl,
headers: token ? { Authorization: `Bearer ${token}` } : {},
json: false,
resolveWithFullResponse: true, // to capture status + headers
});
csvStatus = resp.statusCode;
// treat only 2xx as success
if (csvStatus >= 200 && csvStatus < 300) {
const body = resp.body !== undefined ? resp.body : "";
csvContent = typeof body === "string" ? body : String(body);
} else {
csvErr = `HTTP ${csvStatus}`;
console.log("[CSV ERROR]", rec.csvAssetId, csvErr);
}
} catch (e) {
csvErr = e.message || String(e);
console.log("[CSV ERROR]", rec.csvAssetId, csvErr);
}
}
// --- CHART: fetch if we have an id + chatId (ignore hasChartAsset flag) ---
if (rec.chartAssetId && chatId) {
const chartUrl = `${base}/${rec.chartAssetId}?chat_id=${chatId}`;
try {
const resp = await this.helpers.request({
method: "GET",
url: chartUrl,
headers: token ? { Authorization: `Bearer ${token}` } : {},
encoding: null, // Buffer for binary
json: false,
resolveWithFullResponse: true,
});
chartStatus = resp.statusCode;
const headers = resp.headers || {};
const ct = (headers["content-type"] || "").toLowerCase();
const body = resp.body !== undefined ? resp.body : null;
console.log(
"[CHART]",
rec.chartAssetId,
"status:",
chartStatus,
"content-type:",
ct || "(unknown)",
"isBuffer:",
Buffer.isBuffer(body)
);
if (chartStatus < 200 || chartStatus >= 300) {
chartErr = `HTTP ${chartStatus}`;
} else if (!body) {
chartErr = "Empty body";
} else if (ct.includes("application/json")) {
const text = Buffer.isBuffer(body)
? body.toString("utf8")
: String(body);
try {
const parsed = JSON.parse(text);
chartBase64 = parsed.data || parsed.base64 || parsed.content || null;
if (!chartBase64) chartErr = "JSON did not contain base64";
console.log(
"[CHART] base64(from JSON) len:",
chartBase64 ? chartBase64.length : 0
);
} catch (e) {
chartErr = `JSON parse failed: ${e.message}`;
console.log("[CHART ERROR]", chartErr);
}
} else if (ct.startsWith("text/")) {
const text = Buffer.isBuffer(body)
? body.toString("utf8")
: String(body);
chartBase64 = text.trim();
console.log("[CHART] base64(text) len:", chartBase64.length);
} else {
const buf = Buffer.isBuffer(body) ? body : Buffer.from(body);
chartBase64 = buf.toString("base64");
console.log("[CHART] base64(from binary) len:", chartBase64.length);
}
} catch (e) {
chartErr = e.message || String(e);
console.log("[CHART ERROR]", rec.chartAssetId, chartErr);
}
}
results.push({
json: {
csvContent,
chartBase64,
hasCsv: !!csvContent,
hasChart: !!chartBase64,
csvAssetId: rec.csvAssetId,
chartAssetId: rec.chartAssetId,
chatId,
_baseUsed: base,
_csvUrl:
rec.csvAssetId && chatId
? `${base}/${rec.csvAssetId}?chat_id=${chatId}`
: null,
_chartUrl:
rec.chartAssetId && chatId
? `${base}/${rec.chartAssetId}?chat_id=${chatId}`
: null,
_csvStatus: csvStatus,
_chartStatus: chartStatus,
_csvError: csvErr,
_chartError: chartErr,
},
});
}
return results;

Chain the nodes together to create an end to end workflow that calls an agent/tool and processes the response. Authentication Methods