Appearance
Node.js walkthrough
Upload a document, wait for it to be ready, then ask a question and print the answer with its source files.
Before you start
Node.js 22 or later. No additional packages are needed. Create a Read & write API key in the console.
Set these environment variables. Keep the API key private.
bash
export LAB0_API_KEY='lab0_sk_replace_with_your_key'
export LAB0_BASE_URL='https://app.lab0.ai/app'
export LAB0_NAMESPACE='quickstart'Save a document
Save the following as plan.md, or download it:
md
# Plan
The rollout uses quillfeather checklists.The example uploads this file by default. Set LAB0_FILE_PATH to use another path, and change the prompt to match its contents.
Upload, wait and ask
Save this as quickstart.mjs, or download the example.
js
import { openAsBlob } from 'node:fs';
import { basename } from 'node:path';
import { setTimeout as sleep } from 'node:timers/promises';
const base = (process.env.LAB0_BASE_URL || 'https://app.lab0.ai/app').replace(/\/$/, '');
const key = process.env.LAB0_API_KEY;
if (!key) throw new Error('Set LAB0_API_KEY to a Read & write key');
const namespace = process.env.LAB0_NAMESPACE || 'quickstart';
const path = process.env.LAB0_FILE_PATH || 'plan.md';
async function request(route, options = {}) {
const response = await fetch(base + route, {
...options,
headers: { Authorization: `Bearer ${key}`, ...options.headers },
signal: AbortSignal.timeout(200_000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}: ${await response.text()}`);
return response.json();
}
const form = new FormData();
form.set('namespace', namespace);
form.set('file', await openAsBlob(path), basename(path));
const uploaded = await request('/api/knowledge/files', { method: 'POST', body: form });
let ready = false;
for (let attempt = 0; attempt < 90; attempt++) {
const document = await request(`/api/knowledge/files/${uploaded.id}`);
if (document.status === 'ready') { ready = true; break; }
if (document.status === 'failed') throw new Error(document.error || 'Processing failed');
await sleep(2000);
}
if (!ready) throw new Error(`Processing timed out; inspect file ${uploaded.id}`);
const answer = await request('/api/knowledge/respond', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
prompt: 'How is the rollout run?',
namespace,
file_ids: [uploaded.id],
}),
});
console.log(JSON.stringify(answer, null, 2));Run it from the directory containing plan.md:
bash
node quickstart.mjsThe example stops on an HTTP error, a failed upload or a processing timeout. Once the file is ready, it asks “How is the rollout run?” using only the uploaded file.
Read the result
A successful response contains answer, sources and model. The document says that the rollout uses quillfeather checklists; verify that the answer reflects that and that sources identifies plan.md. Exact wording and the model name can vary.
The file stays in your namespace for later questions. See cleanup when you finish, or continue with streaming answers and the API reference.