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

# build_website_tool

> Build a new Pomerado tool for a website task when find_website_tool finds none, instead of doing the task with a browser, Playwright, computer use or fetching the page.

## Arguments

| Argument | Required | Type | Description |
| - | - | - | - |
| `task` | Yes | string, up to 20,000 characters | What the tool should do, in plain words |
| `site_url` | No | string, up to 2,048 characters | The website's https origin, which every build needs; a path is dropped, so use start\_url for a page |
| `start_url` | No | string, up to 4,096 characters | The exact https page on site\_url where the build starts; its path, query and fragment are kept |
| `effect` | No | one of: `read`, `write`, `ask` | read if the tool only looks things up; write if it changes the website (submits, books, saves a form, uploads, updates an account); ask to have the build ask first. Required for a website build. |
| `login_id` | No | string | The saved login to sign in with, when the site has several |
| `login` | No | object | A login for this call, used only when the site has no saved login: a username (or email, phone or account number) and password, or mode "code" without a password when the site sends a code. It passes through your client and model provider; without it, the run asks the person on its answer page. |
| `save_login` | No | boolean | Save login for later runs (requires login) |
| `force_sign_in` | No | boolean | true: sign in before the example even if the task might work signed out, so the tool always signs in. Needs site\_url. Otherwise a read build tries signed out and signs in (with login\_id, login or the site's saved login) only when the task needs an account or hits a sign-in wall; the tool then needs a login only if the build signed in. A write or ask build given login\_id or login always signs in first. |
| `idempotency_key` | No | string | Your key for this call. Reuse it only to retry the same call, which then returns the same job instead of acting on the website again. |
| `example_input` | No | string | The input of the example the build runs once, JSON-encoded. |

## Output

The build's [job](/guides/jobs/job-object), with `next`, the call that follows it. Once it succeeds, `tool_id` names the new tool and `build.example_result` holds the example's result.

<CodeGroup>
  ```json Arguments theme={null}
  {
    "task": "Search flights between two airports on a date, with an optional return date",
    "site_url": "https://www.google.com",
    "start_url": "https://www.google.com/travel/flights",
    "effect": "read",
    "example_input": "{\"origin\":\"SFO\",\"destination\":\"JFK\",\"departure_date\":\"2026-11-20\"}",
    "idempotency_key": "build-flight-search"
  }
  ```

  ```json Result theme={null}
  {
    "id": "job_77777777777777777777777777777777",
    "type": "build",
    "status": "running",
    "tool_id": null,
    "input_request": null,
    "result": null,
    "result_status": null,
    "result_expires_at": null,
    "write_status": null,
    "login_save": null,
    "error": null,
    "message": null,
    "maintenance": null,
    "build": {
      "integration_id": null,
      "stage": "exploring",
      "stages": [
        {
          "key": "queued",
          "label": "Queued",
          "status": "done",
          "started_at": "2026-10-09T17:00:00.000Z",
          "completed_at": "2026-10-09T17:00:00.000Z"
        },
        {
          "key": "exploring",
          "label": "Exploring the site",
          "status": "active",
          "started_at": "2026-10-09T17:00:00.000Z",
          "completed_at": null
        },
        {
          "key": "building",
          "label": "Building and testing",
          "status": "pending",
          "started_at": null,
          "completed_at": null
        },
        {
          "key": "publishing",
          "label": "Reviewing and publishing",
          "status": "pending",
          "started_at": null,
          "completed_at": null
        }
      ],
      "eta": { "min_seconds": 420, "max_seconds": 900 },
      "example_result": null,
      "existing_tool_id": null
    },
    "watch_url": "https://app.pomerado.ai/integrations/new?job=job_77777777777777777777777777777777",
    "created_at": "2026-10-09T17:00:00.000Z",
    "updated_at": "2026-10-09T17:00:00.000Z",
    "completed_at": null,
    "next": {
      "action": "wait",
      "call": {
        "tool": "get_job",
        "arguments": {
          "job_id": "job_77777777777777777777777777777777",
          "wait_seconds": 1800
        }
      },
      "why": "This job may stop to ask a question. A question expires 10 minutes after it is asked and fails the job if nobody answers. The call returns as soon as the job asks or finishes; while the job still runs, call it again.",
      "if_your_tool_calls_time_out_sooner": "Pass a wait_seconds below your client's tool-call timeout and repeat the call until the job is not running."
    }
  }
  ```
</CodeGroup>

<Accordion title="Details">
  * A build takes about 10 minutes, and the tool is reused after that. Tell the user it is building, then follow the job with get\_job.
  * Set site\_url to the site's https origin, and start\_url only to the exact page the user asked for.
  * The build runs the task once as its example. The finished job keeps that result as build.example\_result; don't repeat a completed website action.
  * Set effect: read when the tool only looks things up, including search, filter and query forms; write when it changes the website, such as submitting, booking, saving a form (an application, profile or checkout), drafts, holds, uploads and account updates; ask when unsure, and the build asks before anything runs.
  * A read build tries its task signed out and signs in only when the site requires it; force\_sign\_in signs in first. With no saved login, the job asks the user on its answer page. Never ask for a password in chat.
  * Ticket, bank and government sites are refused with site\_not\_supported.
  * Status needs\_input with error credentials\_rejected means the website rejected the saved login. The job waits up to 60 minutes for the user to correct it on the page its next names, then resumes. Don't resubmit it.
  * A build that may already have changed the website says so in error.details.possible\_commit, and checks it on resuming.
  * Send an idempotency\_key with every write, and reuse it only to retry the same call. A call without one is a new website action.

  **Effect:** May change a website or your account, and a change may not be undoable.
</Accordion>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.