Add cited web research to your app with Exa Agent
Send a research question to Exa Agent from a Node.js script and get back a cited answer and structured JSON for your app, in 20 minutes.

What you need
Step 1: Get an API key
2 minEvery request to Exa is signed with your key, and new accounts come with free monthly credits.
- Go to dashboard.exa.ai/api-keys and sign up or sign in.
- Create a new API key and copy it.
- Want to see a run first? Try a question in the Agent playground.
You should see your new key in the list of API keys.
Treat the key like a password. Keep it out of your code, chat logs and any file you commit or share.
Step 2: Set up a project
3 minThe
exa-jspackage wraps the API, and it reads your key from the environment.- In a terminal, run the commands below to make a folder and install the package.
- The last line sets your key for this window. On Windows, run
setx EXA_API_KEY "[YOUR API KEY]"and open a new window.
Run thismkdir exa-research && cd exa-research npm init -y npm install exa-js export EXA_API_KEY="[YOUR API KEY]"
You should see
exa-jslisted under dependencies inpackage.json.Later, the script says the API key is missing?
exportonly lasts in the window where you ran it, andsetxonly reaches new windows. Set the key again in the window you run the script from.Step 3: Run your first research task
5 minExa Agent searches, reads and checks pages for you, then returns one answer with its sources.
- Save the code below as
research.mjsin the folder. Put your own question in the query. - Run
node research.mjsand wait. Runs aren't instant, because the agent searches and reads many pages first.
Your scriptimport Exa from "exa-js"; const exa = new Exa(); const run = await exa.agent.runs.create({ query: "[YOUR RESEARCH QUESTION]", effort: "medium" }); const done = await exa.agent.runs.pollUntilFinished(run.id, { pollInterval: 4000 }); if (done.status !== "completed") { console.log(done.status, done.error?.message); } else { console.log(done.output.text); for (const entry of done.output.grounding ?? []) { for (const source of entry.citations) console.log("-", source.title, source.url); } console.log("Cost: $" + done.costDollars?.total); }You should see a written answer, then a list of source titles and links, then the run's cost.
Node says you can't use import outside a module?
Check that the file name ends in
.mjs, not.js. Or add"type": "module"topackage.json.mediumcosts $0.10 a run and suits most questions. Uselow, at $0.025, for quick lookups, orhigh, at $0.50, for harder research.- Save the code below as
Step 4: Get structured JSON back
5 minA schema tells the agent exactly which fields to fill, so your app can use the result without parsing text.
- In
research.mjs, replace theexa.agent.runs.createcall with the one below. - Below the line that prints
done.output.text, addconsole.log(JSON.stringify(done.output.structured, null, 2));. - Run
node research.mjsagain.
Your requestconst run = await exa.agent.runs.create({ query: "Find 5 open-source tools for [YOUR TOPIC] launched this year.", effort: "medium", outputSchema: { type: "object", properties: { tools: { type: "array", maxItems: 5, items: { type: "object", properties: { name: { type: "string" }, website: { type: "string", format: "uri" }, what_it_does: { type: "string" } }, required: ["name", "website", "what_it_does"] } } }, required: ["tools"] } });You should see a JSON object with a
toolslist, each with a name, a website and a line on what it does.The run fails with INVALID_OUTPUT_SCHEMA?
Exa turns down a schema that no answer could match. Check that every name in a
requiredlist also appears inproperties.Set
maxItemson each list to cap how many items come back.- In
Step 5: Pass the research to your model
5 minThe answer and its links give your chatbot current facts to work from, with sources it can cite.
- Take
done.output.textand the source links from your script. - Put them in your model's prompt above the user's question, as in the template below.
- For a follow-up, start a new run and pass the old run's ID as
previousRunId.
Your prompt templateAnswer the question using only the research below. Put the source link after each fact. If the research doesn't cover something, say so. Research: [OUTPUT TEXT] Sources: [SOURCE LINKS] Question: [USER QUESTION]
You should see an answer from your model that cites the links Exa found.
The model adds facts that aren't in the research?
Keep the rule to use only the research at the very top of the prompt. Ask it to say plainly when something isn't covered.
- Take
You get
A Node.js script that sends a question to Exa Agent and gets back a cited answer, structured JSON and the cost of each run
Try next
Did this guide work for you?
Thanks. It helps us fix the steps.
Sources
0 of 5Next: Get an API key


