Docs to working code
Give an agent an API's documentation and a goal. In one session it reads the docs in the browser, writes a Python client in the shell, runs it, reads the errors and fixes it until the output is right. Then the example runs the script again itself: what you get is code that has run against the real API, with its output beside it.
When to use it: You want working code for an API from its documentation, run against the real API with its output beside it.
| Uses | sessions.create with shell, session.goto, agent.run in that session (browser and shell tools), agent.wait with an output schema, session.exec, session.files |
|---|---|
| Needs | a plan with shell sessions and agent runs |
| Site | [Frankfurter](https://frankfurter.dev/)'s docs by default, a free, open-source currency-rate API with no key (DOCS_URL and GOAL for any other API). The runner uses a made-up API that no model knows: a key header, a paged list, one date |
| Output | output/client.py, output/client-output.json and output/result.json (the agent's summary, the run's exit code and output, its steps) |
| Languages | Node and Python |
Why a browser and a shell in one session: API docs are often pages built with JavaScript (Swagger UI, Redoc, a docs site), and the code has to run somewhere to be checked. Here the agent reads the docs where they render and runs the client next to them, against the real API, in an isolated machine; the key it finds in the docs never leaves it.
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.
/** * Docs to working code: an agent reads an HTTP API's documentation in the session's browser, writes a Python client * for a goal in the session's shell, runs it and fixes it until it works. Then the example runs the script itself, so * what you get is code that has been run, with its real output. * * npx tsx node/index.ts (BOXLINE_API_KEY; DOCS_URL, GOAL; a plan with shell sessions and agent runs) * * Writes output/client.py, output/client-output.json and output/result.json. */import { mkdirSync, writeFileSync } from "node:fs";import { join } from "node:path";import { Boxline } from "@boxline/sdk";const out = process.env.OUTPUT_DIR ?? "output";const docsUrl = process.env.DOCS_URL ?? "https://frankfurter.dev/";const goal = process.env.GOAL ?? "Print as JSON the euro's reference rates for USD, GBP and JPY on 2026-10-01, and for each the percent change since 2026-09-01 (rounded to 2 decimals).";const bx = new Boxline();const session = await bx.sessions.create({ shell: true, timeout: 900, idleTimeout: 300, userMetadata: { example: "docs-to-working-code" } });console.log(`Session: ${session.id}`);try { // 1. The docs open in the browser (pages built by JavaScript work too); the agent reads them there. const page = await session.goto(docsUrl); console.log(`Docs: ${page.title} (${docsUrl})`); // 2. The agent writes the client in the same session's shell and runs it until it works. const started = await bx.agent.run({ sessionId: session.id, task: `The documentation of an HTTP API is open in the browser (${docsUrl}). Read it there: scroll, and follow its links ` + `if the part you need is on another page. Then write a Python 3 script, /workspace/client.py (the requests package ` + `is installed), that does this:\n\n${goal}\n\nThe script prints exactly one JSON document to stdout and nothing ` + `else. Take addresses, keys and parameters from the documentation. Run it with \`python3 /workspace/client.py\`, ` + `check its output against the goal, and fix it until it is right. Finish with the endpoints it calls and two ` + `sentences on what it does.`, maxSteps: 30, output: { type: "object", properties: { endpoints: { type: "array", items: { type: "string" } }, summary: { type: "string" } }, required: ["endpoints", "summary"], }, }); console.log(`Agent run ${started.id} (${started.model}) is reading the docs and writing the client…`); const run = await bx.agent.wait<{ endpoints: string[]; summary: string }>(started.id); if (run.status !== "completed" || !run.result) throw new Error(`the run ${run.status}: ${run.error ?? "no result"}`); const toolSteps = run.steps.filter((s) => s.type === "tool"); console.log(`${toolSteps.length} tool steps: ${run.result.summary}`); // 3. The example runs the script itself (from /workspace: the agent's last `cd` would carry over otherwise). const ran = await session.exec("python3 client.py", { cwd: "/workspace", timeoutMs: 120_000 }); let output: unknown = null; try { output = JSON.parse(ran.stdout); } catch { /* not JSON: the check says so */ } console.log(`Ran client.py: exit ${ran.exitCode}${output === null ? ", output is not JSON" : ""}\n${ran.stdout.trim().slice(0, 1500)}`); mkdirSync(out, { recursive: true }); const script = await session.files.readText("client.py"); writeFileSync(join(out, "client.py"), script); writeFileSync(join(out, "client-output.json"), ran.stdout); writeFileSync( join(out, "result.json"), JSON.stringify( { docsUrl, goal, agent: run.result, run: { exitCode: ran.exitCode, stderr: ran.stderr.slice(-2000), output }, scriptLines: script.trim().split("\n").length, toolSteps: toolSteps.map((s) => ({ name: s.name, input: JSON.stringify(s.input ?? {}).slice(0, 300) })), agentRuns: [{ id: run.id }], }, null, 2, ), );} finally { await session.stop();}"""Docs to working code: an agent reads an HTTP API's documentation in the session's browser, writes a Python clientfor a goal in the session's shell, runs it and fixes it until it works. Then the example runs the script itself, sowhat you get is code that has been run, with its real output. python python/main.py (BOXLINE_API_KEY; DOCS_URL, GOAL; a plan with shell sessions and agent runs)Writes output/client.py, output/client-output.json and output/result.json."""import jsonimport osfrom pathlib import Pathfrom boxline import Boxlineout = Path(os.environ.get("OUTPUT_DIR", "output"))docs_url = os.environ.get("DOCS_URL", "https://frankfurter.dev/")goal = os.environ.get( "GOAL", "Print as JSON the euro's reference rates for USD, GBP and JPY on 2026-10-01, and for each the percent change since 2026-09-01 (rounded to 2 decimals).",)bx = Boxline()OUTPUT = { "type": "object", "properties": {"endpoints": {"type": "array", "items": {"type": "string"}}, "summary": {"type": "string"}}, "required": ["endpoints", "summary"],}with bx.sessions.create(shell=True, timeout=900, idle_timeout=300, user_metadata={"example": "docs-to-working-code"}) as session: print(f"Session: {session.id}", flush=True) # 1. The docs open in the browser (pages built by JavaScript work too); the agent reads them there. page = session.goto(docs_url) print(f"Docs: {page['title']} ({docs_url})", flush=True) # 2. The agent writes the client in the same session's shell and runs it until it works. started = bx.agent.run( f"The documentation of an HTTP API is open in the browser ({docs_url}). Read it there: scroll, and follow its links " "if the part you need is on another page. Then write a Python 3 script, /workspace/client.py (the requests package " f"is installed), that does this:\n\n{goal}\n\nThe script prints exactly one JSON document to stdout and nothing " "else. Take addresses, keys and parameters from the documentation. Run it with `python3 /workspace/client.py`, " "check its output against the goal, and fix it until it is right. Finish with the endpoints it calls and two " "sentences on what it does.", session_id=session.id, max_steps=30, output=OUTPUT, ) print(f"Agent run {started['id']} ({started['model']}) is reading the docs and writing the client…", flush=True) run = bx.agent.wait(started["id"]) if run["status"] != "completed" or not run["result"]: raise SystemExit(f"the run {run['status']}: {run.get('error') or 'no result'}") tool_steps = [s for s in run["steps"] if s["type"] == "tool"] print(f"{len(tool_steps)} tool steps: {run['result']['summary']}", flush=True) # 3. The example runs the script itself (from /workspace: the agent's last `cd` would carry over otherwise). ran = session.exec("python3 client.py", cwd="/workspace", timeout_ms=120_000) try: output = json.loads(ran["stdout"]) except ValueError: output = None # not JSON: the check says so print(f"Ran client.py: exit {ran['exitCode']}" + (", output is not JSON" if output is None else "") + f"\n{ran['stdout'].strip()[:1500]}") out.mkdir(parents=True, exist_ok=True) script = session.files.read_text("client.py") (out / "client.py").write_text(script) (out / "client-output.json").write_text(ran["stdout"]) result = { "docsUrl": docs_url, "goal": goal, "agent": run["result"], "run": {"exitCode": ran["exitCode"], "stderr": ran["stderr"][-2000:], "output": output}, "scriptLines": len(script.strip().split("\n")), "toolSteps": [{"name": s.get("name"), "input": json.dumps(s.get("input") or {})[:300]} for s in tool_steps], "agentRuns": [{"id": run["id"]}], } (out / "result.json").write_text(json.dumps(result, indent=2, ensure_ascii=False))Inputs
Environment variables the example reads:
DOCS_URL: the documentation's first page (default Frankfurter's).GOAL: what the script must do, in words (default: the euro's rates for USD, GBP and JPY on a date, and their change over a month).
Run it
Get the examples with git clone https://github.com/Boxline-dev/examples.git and open this one: cd examples/docs-to-working-code. 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# Python 3.9 or newer, in the example's folderexport BOXLINE_API_KEY=… # your API keypip install boxline-sdkpython python/main.pyThen 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.
npx tsx check.ts output exits with 0 only when client.py, run again by the example, exits with 0 and prints JSON, and the agent read the docs in the browser and ran the script in the shell. On the stand-in's made-up API it also compares the answer exactly (the highest high tide of each north station) and checks that the script sent the key and followed the list's next cursor to its second page.
Source
github.com/Boxline-dev/examples/docs-to-working-code 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.