Docs
Dashboard
IntegrationsBeta

LangChain

Two LangChain tools backed by Boxline, given to a LangChain agent (createAgent / create_agent) on your own OpenAI key: boxline_fetch reads a page in a sandboxed browser, and boxline_browser_agent hands a whole browser task (clicking, typing, several pages) to a Boxline agent run.

How it works

tool() from langchain with a zod schema (Node) or @tool from langchain.tools (Python); ChatOpenAI with the Responses API (useResponsesApi: true / use_responses_api=True), which newer OpenAI models need for function tools.

Needsany plan (the browser agent tool needs a model on the Boxline API); your own OpenAI key.
Sitebooks.toscrape.com or quotes.toscrape.com, demo sites made for scraping practice.
EnvironmentBOXLINE_API_KEY, OPENAI_API_KEY (your OpenAI key, for the LangChain agent's model), LC_MODEL (the OpenAI model; default gpt-6-luna), QUESTION (your own question).
Packages@boxline/sdk, @langchain/core@1.2.13, @langchain/openai@1.6.0, langchain@1.5.14, tsx@4.23.15, zod@4.4.3, boxline-sdk, langchain==1.4.3, langchain-openai==1.6.6

The code

/** * LangChain with Boxline: two LangChain tools backed by Boxline, given to a LangChain agent (createAgent) on your own * OpenAI key: `boxline_fetch` reads a page in a sandboxed browser, and `boxline_browser_agent` hands a whole browser * task (clicking, typing, several pages) to a Boxline agent run. * *   npm install && npx tsx index.ts        (BOXLINE_API_KEY and OPENAI_API_KEY in the environment; LC_MODEL, QUESTION) * * Writes output/result.json: the answer and every tool call. */import { mkdirSync, writeFileSync } from "node:fs";import { join } from "node:path";import { Boxline } from "@boxline/sdk";import { ChatOpenAI } from "@langchain/openai";import { createAgent, tool } from "langchain";import { z } from "zod";const out = process.env.OUTPUT_DIR ?? "output";const question = process.env.QUESTION ?? 'On books.toscrape.com, what does "Sapiens: A Brief History of Humankind" cost, and how many are in stock?';const bx = new Boxline();const boxlineRuns: { id: string }[] = [];const boxlineFetch = tool(  async ({ url }) => {    const page = await bx.fetch(url, { format: "markdown", links: true });    return JSON.stringify({ url: page.finalUrl, status: page.status, title: page.title, content: page.content.slice(0, 12_000), links: (page.links ?? []).slice(0, 80) });  },  {    name: "boxline_fetch",    description: "Open a web page in a real browser (in a Boxline sandbox) and return it as Markdown with its links.",    schema: z.object({ url: z.string().describe("an http(s) address") }),  },);const boxlineBrowserAgent = tool(  async ({ task }) => {    const run = await bx.agent.run({ task, maxSteps: 20 });    boxlineRuns.push({ id: run.id });    const done = await bx.agent.wait(run.id, { timeoutMs: 8 * 60_000 });    return done.status === "completed" ? (done.result ?? "") : `The browser agent ${done.status}: ${done.error ?? ""}`;  },  {    name: "boxline_browser_agent",    description: "Give a browser task that needs clicking, typing or several pages to an AI agent with its own browser. Returns its answer.",    schema: z.object({ task: z.string().describe("what to do, with the site's address") }),  },);const agent = createAgent({  // The Responses API: newer OpenAI models take function tools only there.  model: new ChatOpenAI({ model: process.env.LC_MODEL ?? "gpt-6-luna", useResponsesApi: true }),  tools: [boxlineFetch, boxlineBrowserAgent],  systemPrompt: "Answer from pages you read with the tools. Prefer boxline_fetch; use boxline_browser_agent only when a task needs clicking or typing.",});const result = await agent.invoke({ messages: [{ role: "user", content: question }] });const calls = result.messages.flatMap((m: any) => (m.tool_calls ?? []).map((c: any) => ({ tool: c.name, input: c.args })));const answer = result.messages.at(-1)?.text ?? ""; // .text joins the message's text blocksfor (const c of calls) console.log(`→ ${c.tool} ${JSON.stringify(c.input)}`);console.log(`\n${answer}`);mkdirSync(out, { recursive: true });writeFileSync(join(out, "result.json"), JSON.stringify({ question, answer, calls, agentRuns: boxlineRuns }, null, 2));

Install and run

The packages are pinned at the versions the example’s check ran with. It writes to output/ and stops its session when it finishes.

# Node 22 or newerexport BOXLINE_API_KEY=…        # your Boxline API keyexport OPENAI_API_KEY=…         # your own OpenAI keynpm install @boxline/sdk @langchain/core@1.2.13 @langchain/openai@1.6.0 langchain@1.5.14 tsx@4.23.15 zod@4.4.3npx tsx index.ts

What its check proves

It checks that the LangChain agent called a Boxline tool and answered with the price and stock the demo shop shows. To run it from a clone of the examples (git clone https://github.com/Boxline-dev/examples.git), go to examples/integrations/langchain, run the commands above, then check the result from the same folder: npx tsx check.ts output.

Source: github.com/Boxline-dev/examples/integrations/langchain on GitHub. See all integrations.

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