Browser Agent
Create Agents and Runs, recover requests, and read task results with the Node.js SDK 0.7.0.
Browser Agent executes a browser task from a natural-language instruction. A Run is one execution; a saved Agent holds a reusable instruction and optional output schema. Use client.browserAgent with SDK 0.7.0.
Setup
npm install [email protected]
export LEXMOUNT_API_KEY='<your-api-key>'
export LEXMOUNT_PROJECT_ID='<your-project-id>'
# Optional: SDK 0.7.0 defaults to this global COM origin.
export LEXMOUNT_BASE_URL=https://api.lexmount.comUse an API Key and Project ID from the same project, with Browser Agent enabled in the selected environment. Set the HTTPS origin, without /v1/browser-agent; the SDK adds that path. Set https://api.lexmount.cn explicitly for CN. Playwright is not required for these Agent API calls.
Run a task
Choose and persist a new RUN_IDEMPOTENCY_KEY for one logical task before running this example. Reuse it with the identical request when recovering that task; use a new key for an intentionally new task.
export RUN_IDEMPOTENCY_KEY='<persistent-unique-key-for-this-task>'Save as agent.mjs and run node agent.mjs:
import { APIError, Lexmount, RunWaitTimeout } from 'lexmount';
const key = process.env.RUN_IDEMPOTENCY_KEY;
if (!key) throw new Error('Set a persistent RUN_IDEMPOTENCY_KEY first');
const client = new Lexmount();
try {
const receipt = await client.browserAgent.runs.create(
{
query: 'Read the page title and summarize the page.',
start_url: 'https://example.com/',
},
{ idempotencyKey: key }
);
console.log('Accepted:', receipt.id); // Save this Run ID before waiting.
const run = await client.browserAgent.runs.wait(receipt.id, {
timeoutMs: 300_000,
});
console.log(run.id, run.status, run.output);
if (run.status !== 'succeeded') {
console.error(run.stop_reason, run.error);
process.exitCode = 1;
}
} catch (error) {
if (error instanceof RunWaitTimeout) {
console.error('Resume with runs.get/wait:', error.run_id);
} else if (error instanceof APIError) {
console.error(error.status_code, error.code, error.request_id);
} else {
throw error;
}
process.exitCode = 1;
} finally {
client.close();
}A create response is a queued receipt, not a completed result. Save receipt.id and use runs.get(id) or runs.wait(id) to recover after a process restart. Closing the SDK client does not cancel an active Run.
Reuse a saved Agent
Set two additional persistent keys, AGENT_IDEMPOTENCY_KEY for the Agent creation and SAVED_RUN_IDEMPOTENCY_KEY for this Run. Save the returned Agent ID and use it for later Runs; creating the Agent is a one-time setup step.
import { Lexmount } from 'lexmount';
const agentKey = process.env.AGENT_IDEMPOTENCY_KEY;
const runKey = process.env.SAVED_RUN_IDEMPOTENCY_KEY;
if (!agentKey || !runKey)
throw new Error('Set both persistent idempotency keys');
const client = new Lexmount();
try {
const agent = await client.browserAgent.agents.create(
{
name: 'Page summary',
instruction: 'Summarize the page in {{language}}.',
start_url: 'https://example.com/',
output_schema: {
type: 'object',
properties: { summary: { type: 'string' } },
required: ['summary'],
additionalProperties: false,
},
},
{ idempotencyKey: agentKey }
);
const receipt = await client.browserAgent.runs.create(
{
agent_id: agent.id,
variables: { language: 'English' },
metadata: { source: 'docs' },
},
{ idempotencyKey: runKey }
);
console.log('Agent:', agent.id, 'Run:', receipt.id);
// Recover this Run later with runs.get(receipt.id) or runs.wait(receipt.id).
} finally {
client.close();
}Supply exactly the instruction's template variables. The accepted Run freezes the Agent revision, expanded instruction and schema; later Agent edits do not change that Run. metadata is returned to your application and is not sent to the model. A successful schema-based output is an object; free-form output is text.
Manage resources
All methods below are on client.browserAgent. Await each call.
| Operation | Call |
|---|---|
| Read / list Agents | agents.get(id) / agents.list() |
| Edit an Agent | agents.update(id, { revision: current.revision, name: "Updated name" }) |
| Delete an Agent | agents.delete(id) |
| Read / list Runs | runs.get(id) / runs.list() |
| Request cancellation | runs.cancel(id) |
| Wait for terminal state | runs.wait(id) |
Read the current Agent first and pass its revision when updating. A revision conflict requires reading it again; updates are not automatically retried. Cancellation can race with completion: inspect the returned state and keep reading until terminal if it is still cancelling.
Recovery and errors
- The SDK generates an idempotency key if omitted. For recovery across process restarts, supply your own:
idempotencyKeyin the second options argument. Persist the key and request body before sending; use 1–128 visible ASCII characters without spaces. Same key/body replays the original receipt for at least seven days; a different body conflicts. Beyond that window, reconcile through history before creating anything again. succeeded,failed,timed_out, andcancelledare terminal Run results. HTTP success alone does not mean the task succeeded; inspectstatus,stop_reason,error, andoutput.RunWaitTimeoutonly stops local polling. Resume with the known Run ID, or explicitly request cancellation.timeoutMs,pollIntervalMs, andrequestTimeoutMsuse milliseconds.APIErrorincludesstatus_code,code, andrequest_id. Keep the request ID for support. Pass{ withResponse: true }to get success response metadata.- Keep the API Key used to create a Run valid until execution and cleanup finish. Revoking it can fail an active Run with
credential_unavailable; changing the client's key does not replace the original Run's execution credential. usage.creditscan benullwhile metering is pending; it does not mean zero cost. Task execution may have external side effects, so an unknown result must not be blindly resubmitted.
Runnable examples cover basic execution, saved Agents and recovery.
