Docs
Dashboard
Examples / AI agentsBeta

Research a question

An agent searches the web, reads several sources in its browser, and answers with citations.

When to use it: A question needs several sources read and weighed, with citations.

Usesagent.run (the agent's web_search tool and its browser), agent.stream
Needsa plan with web search and a model on the API
Sitewhatever the agent finds
Outputoutput/result.json: the answer, its sources, the searches and the pages opened
LanguagesNode and Python

The code

The example as it is in its folder. Both versions do the same job and write the same output/, so one result check covers both.

/** * Research a question: an agent searches the web, reads several sources in its browser, and answers with citations. * *   npx tsx node/index.ts            (BOXLINE_API_KEY; QUESTION for your own question; a plan with web search) * * Writes output/result.json: the answer, its sources, the searches it ran and the pages it opened. */import { mkdirSync, writeFileSync } from "node:fs";import { join } from "node:path";import { Boxline } from "@boxline/sdk";const out = process.env.OUTPUT_DIR ?? "output";const question = process.env.QUESTION ?? "When was the James Webb Space Telescope launched, and where does it orbit?";const bx = new Boxline();const run = await bx.agent.run({  task:    `Research this question on the web: "${question}" Use web search, open and read at least two good sources, and answer ` +    'in two or three sentences. End with a line "Sources:" followed by the addresses of the pages you read, one per line.',  maxSteps: 25,});console.log(`Agent run ${run.id} (${run.provider}/${run.model}) · Session: ${run.sessionId}`);for await (const e of bx.agent.stream(run.id)) {  if (e.type === "tool" && e.name === "web_search") console.log(`search: ${(e.input as { query?: string })?.query}`);  else if (e.type === "tool" && e.name === "browser_navigate") console.log(`read:   ${(e.input as { url?: string })?.url}`);  else if (e.type === "done") console.log(`\n${e.status}:\n${e.result ?? e.error}`);}const done = await bx.agent.get(run.id);const tools = done.steps.filter((s) => s.type === "tool");const searches = tools.filter((s) => s.name === "web_search").map((s) => (s.input as { query?: string })?.query ?? "");const opened = tools.filter((s) => s.name === "browser_navigate").map((s) => (s.input as { url?: string })?.url ?? "");const answer = done.result ?? "";const sources = [...new Set((answer.split(/\bSources:/i)[1] ?? "").match(/https?:\/\/[^\s)>\]]+/g) ?? [])];mkdirSync(out, { recursive: true });writeFileSync(  join(out, "result.json"),  JSON.stringify({ question, status: done.status, answer, sources, searches, opened, agentRuns: [{ id: run.id }], model: done.model, costUsd: done.usage.costUsd, usage: { searches: searches.length } }, null, 2),);

Inputs

Environment variables the example reads:

  • QUESTION: your question (default When was the James Webb Space Telescope launched, and where does it orbit?).

Run it

Get the examples with git clone https://github.com/Boxline-dev/examples.git and open this one: cd examples/research-a-question. Put your API key in BOXLINE_API_KEY (and BOXLINE_API_URL for another API), then run either version from the example’s folder. Both write to output/ and stop their sessions when they finish.

# Node 18 or newer, in the example's folderexport BOXLINE_API_KEY=…   # your API keynpm install @boxline/sdk tsxnpx tsx node/index.ts

Then check the result, from the same folder: npx tsx check.ts output. It exits with 0 only when the result is right.

What its check proves

check.ts reads what the example wrote and passes only when the result is right, not merely when the example ran.

The agent searched, cites at least two sources and opened each of them; for the default question the answer has 2021 and L2.

Source

github.com/Boxline-dev/examples/research-a-question on GitHub, with its README.md, check.ts and .env.example. The examples are open source. See all examples.

These docs describe a beta API. Endpoints, fields and SDK methods may change before general availability; breaking changes will be listed in the changelog.