> ## 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.

# Guided SDK workflow

> Build a production-shaped browser-agent workflow with setup, web.agent(), validation, persistence, and review.

Wrap a browser-agent run with deterministic setup, validation, persistence, and review routing.

## Product workflow shape

* Deterministic setup around a browser-agent run.
* `web.agent()` with policy, recording, approvals, and structured output.
* Persistence and review routing based on the final agent status.

## Setup

Install `@webcompute/sdk`, configure `WEBCOMPUTE_API_KEY`, and configure the model provider used by your agent profile. The example assumes a `filingsSchema`, `db`, and review queue already exist in your app.

## Run it from the CLI first

```bash theme={null}
web agent \
  --url https://www.sec.gov/edgar/search/ \
  --allow-domain sec.gov \
  "Find Apple's latest 10-Q filings. Return filing date, accession number, filing URL, and a one-sentence summary."
```

## Expected output

```text theme={null}
Filing lookup completed

Status: completed
Output: validated filing rows
Evidence: steps, recording, and source URLs
```

## Build it into an app

```ts theme={null}
import { Web } from "@webcompute/sdk";

const web = new Web();

const agent = web.agent({
  model: {
    route: "openrouter",
    model: "openai/gpt-5.4-mini",
    apiKeyEnv: "OPENROUTER_API_KEY",
  },
  browser: {
    create: { recording: true },
    policy: { allowedDomains: ["sec.gov"] },
  },
  approval: "ask",
  outputSchema: filingsSchema,
});

const job = await db.jobs.create({
  data: { kind: "filing_lookup", company: "Apple" },
});

const result = await agent.run({
  startUrl: "https://www.sec.gov/edgar/search/",
  goal: "Find Apple's latest 10-Q filings. Return filing metadata.",
});

if (result.status !== "completed" || !result.output) {
  await db.jobs.update({
    where: { id: job.id },
    data: { status: result.status, error: result.error?.message },
  });
  await queueReview(result);
} else {
  await db.filings.createMany({ data: normalizeFilings(result.output) });
  await db.jobs.update({ where: { id: job.id }, data: { status: "completed" } });
}
```

## Production notes

* Deterministic setup creates the job and chooses policy.
* `web.agent()` handles the browser task.
* Structured output gives the app a validation boundary.
* Deterministic persistence stores the result and review state.
* Recording and steps keep evidence available.

## Inspect

* `result.status` for workflow routing.
* `result.output` for validated data.
* `result.steps` for browser evidence.
* `result.artifacts` for files or downloads.

## Cleanup

Keep job records, structured output, and source URLs according to your product retention policy. Browser cleanup is handled by the agent run unless you attach it to an existing managed browser.

## Common failures

* If `result.status` is not `completed`, persist the status and queue review instead of treating partial text as valid data.
* If schema validation fails, inspect `result.steps` and the recording before loosening the schema.
