Snel antwoord
Hoe roep ik een web search API voor AI-agents aan vanuit Node.js?
Gebruik de ingebouwde fetch van Node 18+ om je zoekopdracht met een Bearer-sleutel naar https://llmwebsearch.com/api/v1/search te POSTen. LLMWebSearch antwoordt met gerangschikte resultaten en de top 3 pagina's als Markdown, klaar om te nummeren en aan een model te geven voor een antwoord met citaten. Eén zoekopdracht kost 1 credit, vanaf US$ 1,20/1K zoekopdrachten per oktober 2026. Geen npm-package nodig. Zonder KYC; betalen met crypto.
Wat je nodig hebt
| Node.js | 18 of nieuwer, voor de ingebouwde fetch; sla de scripts op als .mjs voor top-level await |
|---|---|
| Packages | Geen |
| Sleutel | LLMWEBSEARCH_API_KEY in je omgeving |
| Voor de antwoordloop | Een OpenAI-compatibel chat-endpoint: LLM_BASE_URL, LLM_API_KEY, LLM_MODEL |
| Facturering | Eén credit betaalt één zoekopdracht: tot 20 gerangschikte resultaten, waarbij de pagina's van de eerste 3 worden gelezen en als Markdown teruggegeven. Het lezen van 4 tot 10 pagina's kost 2 credits. Een call die op een fout eindigt, kost niets |
Hoe schrijf ik een herbruikbare zoekfunctie?
Wikkel de aanroep één keer en hergebruik hem overal. De functie hieronder verstuurt de body, gooit een leesbare fout bij elke HTTP-fout en geeft de geparseerde JSON terug. Fouten bevatten de eigen code van de API, zoals rate_limited of insufficient_credits, zodat de aanroeper kan beslissen wat te doen.
const API = 'https://llmwebsearch.com/api/v1/search';
export async function search(body) {
const res = await fetch(API, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.LLMWEBSEARCH_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
const data = await res.json();
if (!res.ok) {
const err = new Error(`${res.status} ${data.error?.code}: ${data.error?.message}`);
err.status = res.status;
throw err;
}
return data;
}
const data = await search({ q: 'how to size a postgres connection pool', read: 3 });
for (const r of data.results) {
console.log(r.position, r.content_status, r.url, r.word_count ?? '');
}
Hoe voer ik meerdere zoekopdrachten uit zonder tegen de rate limit aan te lopen?
Voer ze uit via een kleine pool: een vast aantal workers die elk de volgende zoekopdracht uit een gedeelde lijst pakken. Vier workers is een verstandig begin. Elk account heeft een calllimiet per minuut, te zien in het dashboard; vraag het supportteam en de limiet kan worden verhoogd.
De pool hieronder heeft geen library nodig. Elke worker houdt zijn eigen resultaten bij, en een mislukte zoekopdracht wordt met zijn fout vastgelegd in plaats van de hele run te stoppen. Dat is belangrijk voor research-agents, waar één slechte subvraag niet de hele taak mag kosten.
const API = 'https://llmwebsearch.com/api/v1/search';
const questions = [
'what is connection pooling in postgres',
'recommended pool size per cpu core',
'pgbouncer transaction mode limitations',
'connection pool exhaustion symptoms',
'pool size for serverless functions',
];
async function search(q) {
const res = await fetch(API, {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.LLMWEBSEARCH_API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ q, read: 2, max_chars: 4000 }),
});
const data = await res.json();
if (!res.ok) return { q, error: data.error?.code ?? String(res.status) };
return { q, urls: data.results.filter((r) => r.content_status === 'ok').map((r) => r.url) };
}
async function runPool(items, size, task) {
const out = [];
let next = 0;
const worker = async () => {
while (next < items.length) {
const i = next++;
out[i] = await task(items[i]);
}
};
await Promise.all(Array.from({ length: size }, worker));
return out;
}
for (const row of await runPool(questions, 4, search)) console.log(row);
Hoe zet ik resultaten om in een antwoord met bronvermeldingen?
Nummer de bronnen, zet de URL naast elk ervan, kort ze in tot een budget en vraag het model om op nummer te citeren. De API geeft bronnen terug, geen geschreven antwoord: je eigen model leest de pagina's, schrijft het antwoord en citeert de URL's. Het script hieronder praat met elk OpenAI-compatibel chat/completions-endpoint, gekozen met drie environment variables, dus het werkt met gehoste en lokale modellen.
Het budget van ongeveer 24.000 tekens, ruwweg 6.000 tokens, wordt gelijk verdeeld over de bronnen. Een resultaat waarvan de webpagina niet gelezen kon worden, wordt doorgegeven als zijn snippet, als zodanig gemarkeerd.
const SEARCH = 'https://llmwebsearch.com/api/v1/search';
const BUDGET = 24000; // characters, about 6,000 tokens
async function sources(question) {
const res = await fetch(SEARCH, {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.LLMWEBSEARCH_API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ q: question, max_results: 5, read: 3 }),
});
const { results } = await res.json();
const share = Math.floor(BUDGET / Math.max(results.length, 1));
return results
.map((r, i) => {
const body = r.content_status === 'ok' ? r.content.slice(0, share) : `(snippet only) ${r.snippet}`;
return `[${i + 1}] ${r.title} - ${r.url}\n${body}`;
})
.join('\n\n');
}
async function answer(question) {
const prompt = 'Answer using only the sources below. Cite them as [1], [2] and so on. '
+ 'Say so if they do not answer the question.\n\n' + (await sources(question)) + '\n\nQuestion: ' + question;
const res = await fetch(`${process.env.LLM_BASE_URL.replace(/\/$/, '')}/chat/completions`, {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.LLM_API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ model: process.env.LLM_MODEL, messages: [{ role: 'user', content: prompt }] }),
});
const data = await res.json();
return data.choices[0].message.content;
}
console.log(await answer('How should I size a Postgres connection pool?'));
Moet ik GET of POST gebruiken vanuit Node?
POST, met een JSON-body, in applicatiecode. Arrays zoals include_domains en lange vragen reizen netter in een body dan in een query string. GET is er voor snelle tests en voor tools die geen body kunnen versturen; bouw de query string met URLSearchParams en voeg lijsten samen met komma's.
Beide vormen kosten hetzelfde en geven dezelfde JSON terug. De search-referentie noemt elke parameter voor beide.
Waar moet de sleutel staan?
In een environment variable die tijdens runtime wordt gelezen, nooit in het bronbestand. Op een server gebruik je de secret store van je platform. In een browser roep je de API helemaal niet aan: de sleutel zou zichtbaar zijn voor elke bezoeker. Roep je eigen backend aan, die vervolgens LLMWebSearch aanroept.
Maak één API-sleutel per agent, app of teamgenoot en trek elk ervan in vanuit het dashboard zonder de andere te raken. Eén sleutel per service maakt de geschiedenis in het dashboard makkelijker te lezen, en een gelekt sleutel makkelijk in te trekken.
Node.js: veelgestelde vragen
Is er een npm-package?
Nee. fetch zit ingebouwd in Node 18 en nieuwer, en de API is platte JSON over HTTPS. De functies op deze pagina zijn de hele integratie.
Werkt het op Deno, Bun of edge-runtimes?
De code gebruikt alleen fetch, JSON en process.env. Runtimes met fetch werken nadat je process.env vervangt door hun eigen manier om secrets te lezen.
Hoe probeer ik mislukte calls opnieuw?
Probeer alleen 429, 502 en 504 opnieuw, met een pauze die elke keer verdubbelt. Probeer nooit 400, 401 of 402 opnieuw. De errors-pagina legt uit waarom en toont een helper.