Docs
Dashboard
Examples / AI agentsBeta

Agent with a human in the loop

An agent that asks you when it is unsure (here: which of several books to pick), waits for your answer, then carries on.

When to use it: A task has choices that a person should make.

Usesagent.run, agent.stream (handover steps, thoughts), agent.resume with a note
Needsa model on the API
Sitebooks.toscrape.com (a demo shop)
Outputoutput/result.json
LanguagesNode and Python

You take part: When the agent asks, type your answer (for example "The cheaper one, please.").

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.

/** * Agent with a human in the loop: an agent that asks you when it is unsure (here: which of several books to pick), * waits for your answer, then carries on. * *   npx tsx node/index.ts            (BOXLINE_API_KEY; TASK for your own task) * * Writes output/result.json. */import { mkdirSync, writeFileSync } from "node:fs";import { join } from "node:path";import { createInterface } from "node:readline/promises";import { Boxline } from "@boxline/sdk";const out = process.env.OUTPUT_DIR ?? "output";const task =  process.env.TASK ??  "On https://books.toscrape.com, open the Travel category and find the books that cost less than £30. If more than one " +    "fits, don't finish yet: ask me for help to choose, and wait until I resume the run with my choice. Then tell " +    "me the title and price of the one I chose.";const bx = new Boxline();const run = await bx.agent.run({ task, maxSteps: 25 });console.log(`Agent run ${run.id} (${run.provider}/${run.model}) · Session: ${run.sessionId}`);const rl = createInterface({ input: process.stdin, output: process.stdout });const questions: string[] = [];for await (const e of bx.agent.stream(run.id)) {  if (e.type === "thought") console.log(`  ${e.text}`);  else if (e.type === "tool") console.log(`→ ${e.name} ${JSON.stringify(e.input ?? {}).slice(0, 100)}`);  else if (e.type === "handover" && e.by === "agent") {    // The run is paused: the browser is yours (watch or act in the live view), and your note goes back to the agent.    questions.push(e.text ?? "");    console.log(`\nThe agent asks: ${e.text}`);    const answer = await rl.question("Your answer: ");    await bx.agent.resume(run.id, { note: answer });  } else if (e.type === "done") console.log(`\n${e.status}: ${e.result ?? e.error}`);}rl.close();const done = await bx.agent.get(run.id);mkdirSync(out, { recursive: true });writeFileSync(  join(out, "result.json"),  JSON.stringify({ task, agentRuns: [{ id: run.id }], status: done.status, answer: done.result, questions, steps: done.steps.length, model: done.model, costUsd: done.usage.costUsd }, null, 2),);

Inputs

Environment variables the example reads:

  • TASK: your own task (tell it to ask you when unsure).

Run it

Get the examples with git clone https://github.com/Boxline-dev/examples.git and open this one: cd examples/agent-with-human-in-the-loop. 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 asked at least once and then reported the book the answer chose, checked against the shop's own page.

Source

github.com/Boxline-dev/examples/agent-with-human-in-the-loop 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.