> ## Documentation Index
> Fetch the complete documentation index at: https://docs-preview.webcompute.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Mix agent and code

> Combine agent-driven browser work with SDK resources for setup, files, validation, recovery, and advanced exact browser steps.

Use the agent for model-driven browser work. Use SDK resources around it when the workflow needs explicit lifecycle, policy, files, downloads, status, recordings, validation, retries, persistence, or recovery.

## Browser envelope

Create or resume the browser in application code, then pass its `browserId` into the agent run.

```ts theme={null}
const agent = web.agent({
  model,
  approval: "ask",
});

const browser = await web.browser.create({
  recording: true,
  policy: { allowedDomains: ["vendor.example"] },
});

try {
  const result = await agent.run({
    browserId: browser.id,
    startUrl: "https://vendor.example/dashboard",
    goal: "Find the latest paid invoice and download the PDF.",
  });

  if (result.status !== "completed") {
    throw new Error(result.error?.message ?? `Run ended with ${result.status}`);
  }

  const downloads = await browser.downloads.list();
  const [invoice] = downloads.data;
  if (!invoice) throw new Error("No invoice was downloaded.");

  await browser.downloads.save(invoice.id, "./invoice.pdf");
} finally {
  await browser.close();
}
```

The SDK keeps browser boundaries and durable resources explicit around the agent run. When you pass `browserId`, keep browser policy on the explicit browser, not on the agent config.

## Same-browser session loop

Use `agent.session(...)` when related goals should share a browser.

```ts theme={null}
const sessionAgent = web.agent({
  model,
  approval: "ask",
});

const browser = await web.browser.create({
  recording: true,
  policy: { allowedDomains: ["vendor.example"] },
});

const session = await sessionAgent.session({
  browserId: browser.id,
  startUrl: "https://vendor.example/dashboard",
});

try {
  await session.run("Find the customer account for Acme Corp.");
  await session.run("Open the billing page and download the latest invoice for Acme Corp.");

  const downloads = await browser.downloads.list();
  const [invoice] = downloads.data;
  if (invoice) await browser.downloads.save(invoice.id, "./acme-invoice.pdf");
} finally {
  await session.close();
  await browser.close();
}
```

Sessions keep the same browser alive across related goals. Include the important context in each follow-up goal so the model has the details it needs.

## Resource handoff

Stage files in deterministic code and tell the agent how to use the staged file id in browser work.

```ts theme={null}
const browser = await web.browser.create({
  policy: {
    allowedDomains: ["portal.example"],
    uploads: { mode: "requireApproval", allowedMimeTypes: ["application/pdf"] },
  },
});

try {
  const report = await browser.files.createFromPath("./report.pdf");

  await agent.run({
    browserId: browser.id,
    startUrl: "https://portal.example/upload",
    goal: `Upload the staged PDF report to the monthly reports form. The staged file id is ${report.id}; use files.path("${report.id}") to resolve the browser-side upload path.`,
  });
} finally {
  await browser.close();
}
```

A staged SDK file id is not a local browser path. The browser-code helper `files.path(fileId)` resolves it inside the managed browser execution environment.

## Verification gate

Validate the result before your application takes business action.

```ts theme={null}
const result = await agent.run({
  browserId: browser.id,
  startUrl: "https://www.sec.gov/edgar/search/",
  goal: "Find Apple's latest 10-Q filing and return structured filing details.",
  outputSchema: filingSchema,
});

if (result.status !== "completed" || !result.output) {
  throw new Error("The filing lookup did not produce verified structured output.");
}

const pages = await browser.pages();
const status = await browser.status();

await saveFilingLookup({
  filing: result.output,
  browserId: result.browserId,
  pages,
  status,
});
```

Use the model's final text as a summary, not as the only evidence. Store structured output, source URLs, browser IDs, artifact IDs, page metadata, status, and recordings when the workflow needs auditability.

## Recovery loop

When a run blocks or fails, application code can inspect state and continue with more context.

```ts theme={null}
let result = await session.run("Find and download the Q2 statement.");

if (result.status !== "completed") {
  const statusSummary = JSON.stringify(await browser.status()).slice(0, 1200);

  result = await session.run({
    goal: `Continue from the current browser state and finish the Q2 statement download. Previous run ended with ${result.status}. Current browser status summary: ${statusSummary}`,
  });
}
```

Use this pattern for long-running tasks, blockers, CAPTCHA review, transient failures, and workflows that need durable retry behavior.

## Advanced exact browser step

Use exact browser control only when the browser step itself must be deterministic. Keep the step bounded, then return to the agent or SDK resource APIs.

```ts theme={null}
await browser.playwright.execute({
  code: `
    await page.getByRole("button", { name: "Export CSV" }).click();
    return { url: page.url(), title: await page.title() };
  `,
});

const downloads = await browser.downloads.list();
const [csv] = downloads.data;
if (!csv) throw new Error("No CSV export was downloaded.");

await browser.downloads.save(csv.id, "./monthly-totals.csv");
await session.run("Confirm the export completed and return to the dashboard.");
```

When exact control creates a download, handle that artifact through `browser.downloads`. Do not assume the agent can read SDK download artifacts unless your workflow explicitly feeds their contents back into a later model or browser step.

## Choose the right layer

* Use `agent.run(...)` for live browser work.
* Use application code for business rules your product must enforce every time.
* Use browser resources for lifecycle, files, downloads, page metadata, status, recordings, and recovery.
* Use exact browser control only when a specific browser step must be deterministic.

Reference: [SDK agent reference](/reference/sdk-agent-reference), [SDK browser reference](/reference/sdk-browser-reference), [SDK resources reference](/reference/sdk-resources-reference), and [runtime browser control](/runtime-concepts/browser-control).
