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

# Integrating Agents

> Create and manage Agents, trigger runs, pass variables, and track runs to completion.

Once you've built an Agent in the [dashboard](/welcome/quickstarts/agents), you can integrate it into your application with the official SDK/API: manage reusable Agents, trigger runs, pass per-run values, track each run to completion, and read the result.

Runs are asynchronous. You create a run, then track it to a terminal state by polling.

## Install an SDK

<Tabs>
  <Tab title="Node.js">
    ```bash theme={null}
    npm install @browserbasehq/sdk
    ```
  </Tab>

  <Tab title="Python">
    ```bash theme={null}
    pip install browserbase
    ```
  </Tab>
</Tabs>

Initialize the client once:

<Tabs>
  <Tab title="Node.js">
    ```typescript Node.js theme={null}
    import Browserbase from "@browserbasehq/sdk";

    const bb = new Browserbase({
      apiKey: process.env.BROWSERBASE_API_KEY!,
    });
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import os
    from browserbase import Browserbase

    bb = Browserbase(api_key=os.environ["BROWSERBASE_API_KEY"])
    ```
  </Tab>
</Tabs>

See the [Node.js SDK reference](/reference/sdk/nodejs#agents) or [Python SDK reference](/reference/sdk/python#agents) for every Agents SDK method, parameter, and response field.

<Tip>
  To scaffold the integration quickly, open an Agent's run view in the dashboard and use **Build API in** to open the Agent's API prompt in a coding tool like Cursor.
</Tip>

## Endpoints at a glance

**Agents** define reusable configuration.

| Endpoint                                          | Use                                                             |
| ------------------------------------------------- | --------------------------------------------------------------- |
| [Create an Agent](/reference/api/create-an-agent) | Define a reusable Agent with a system prompt and result schema. |
| [List Agents](/reference/api/list-agents)         | Page through your Agents.                                       |
| [Get an Agent](/reference/api/get-an-agent)       | Fetch a single Agent.                                           |
| [Update an Agent](/reference/api/update-an-agent) | Change an Agent's configuration.                                |
| [Delete an Agent](/reference/api/delete-an-agent) | Remove an Agent.                                                |

**Runs** are single executions of a task.

| Endpoint                                              | Use                                                |
| ----------------------------------------------------- | -------------------------------------------------- |
| [Run an Agent](/reference/api/run-an-agent)           | Start a run, optionally against an existing Agent. |
| [List runs](/reference/api/list-runs)                 | Page through runs, filtered by Agent or status.    |
| [Get a run](/reference/api/get-a-run)                 | Fetch a run's status and result.                   |
| [List run messages](/reference/api/list-run-messages) | Stream the run's step-by-step transcript.          |

## Trigger a run

Start a run with [Run an Agent](/reference/api/run-an-agent). Pass an `agentId` to run an existing Agent, along with per-run options like `variables`, `resultSchema`, and `browserSettings`.

<Tabs>
  <Tab title="Node.js">
    ```typescript Node.js theme={null}
    import Browserbase from "@browserbasehq/sdk";

    const bb = new Browserbase({
      apiKey: process.env.BROWSERBASE_API_KEY!,
    });

    const { runId } = await bb.agents.runs.create({
      agentId: "a1b2c3d4-5678-90ab-cdef-1234567890ab",
      task: "Find the best matching open role at Browserbase",
      browserSettings: { proxies: true },
    });

    console.log("Run started:", runId);
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import os
    from browserbase import Browserbase

    bb = Browserbase(api_key=os.environ["BROWSERBASE_API_KEY"])

    run = bb.agents.runs.create(
        agent_id="a1b2c3d4-5678-90ab-cdef-1234567890ab",
        task="Find the best matching open role at Browserbase",
        browser_settings={"proxies": True},
    )

    print("Run started:", run.run_id)
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST https://api.browserbase.com/v1/agents/runs \
      --header "x-bb-api-key: $BROWSERBASE_API_KEY" \
      --header "Content-Type: application/json" \
      --data '{
        "agentId": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
        "task": "Find the best matching open role at Browserbase",
        "browserSettings": { "proxies": true }
      }'
    ```
  </Tab>
</Tabs>

A call with no `agentId` creates a new Agent and its first run, returning both an `agentId` and a `runId`. See [Run an Agent](/reference/api/run-an-agent) for every field.

## Manage reusable Agents with the SDK

The SDKs support the complete reusable Agent lifecycle:

<Tabs>
  <Tab title="Node.js">
    ```typescript Node.js theme={null}
    const agent = await bb.agents.create({
      name: "Job Finder",
      systemPrompt: "Find the best matching role on the company's official job board.",
      resultSchema: {
        type: "object",
        properties: {
          title: { type: "string" },
          url: { type: "string" },
        },
        required: ["title", "url"],
      },
    });

    const current = await bb.agents.retrieve(agent.agentId);

    const updated = await bb.agents.update(agent.agentId, {
      name: "Official Job Board Finder",
      systemPrompt: "Use only the company's official careers site or applicant tracking system.",
    });

    const page = await bb.agents.list({ limit: 20 });

    await bb.agents.delete(agent.agentId);
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    agent = bb.agents.create(
        name="Job Finder",
        system_prompt="Find the best matching role on the company's official job board.",
        result_schema={
            "type": "object",
            "properties": {
                "title": {"type": "string"},
                "url": {"type": "string"},
            },
            "required": ["title", "url"],
        },
    )

    current = bb.agents.retrieve(agent.agent_id)

    updated = bb.agents.update(
        agent.agent_id,
        name="Official Job Board Finder",
        system_prompt="Use only the company's official careers site or applicant tracking system.",
    )

    page = bb.agents.list(limit=20)

    bb.agents.delete(agent.agent_id)
    ```
  </Tab>
</Tabs>

Deleting an Agent doesn't affect runs that already referenced it. Updates are partial: omitted fields remain unchanged.

## Passing variables

Use `variables` to pass per-run dynamic values without writing them into the prompt. Each variable pairs a `value` the placeholder resolves to with an optional `description` that tells the Agent when to use it. Reference a variable in the task or system prompt as `%variableName%`.

```json theme={null}
{
  "agentId": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
  "task": "Check in to my flight using confirmation %confirmation%",
  "variables": {
    "confirmation": {
      "value": "XYZ123",
      "description": "The flight confirmation code to enter at check-in"
    }
  }
}
```

Variables suit values like account numbers, dates of birth, and confirmation codes. The Agent fills the placeholder without the value appearing inline in the task.

## Tracking a run to completion

A run moves through these states:

```
PENDING → RUNNING → COMPLETED
                  → FAILED
                  → TIMED_OUT
                  → STOPPED
```

`PENDING` and `RUNNING` are active. The rest are terminal.

### Poll for the result

Poll [Get a run](/reference/api/get-a-run) until the run reaches a terminal state, then read `result`:

<Tabs>
  <Tab title="Node.js">
    ```typescript Node.js theme={null}
    async function pollRun(runId: string) {
      const terminal = ["COMPLETED", "FAILED", "STOPPED", "TIMED_OUT"];
      while (true) {
        const run = await bb.agents.runs.retrieve(runId);
        if (terminal.includes(run.status)) return run;
        await new Promise((resolve) => setTimeout(resolve, 2000));
      }
    }

    const run = await pollRun(runId);
    console.log("Result:", run.result);
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import time

    def poll_run(run_id):
        terminal = {"COMPLETED", "FAILED", "STOPPED", "TIMED_OUT"}
        while True:
            run = bb.agents.runs.retrieve(run_id)
            if run.status in terminal:
                return run
            time.sleep(2)

    run = poll_run(run_id)
    print("Result:", run.result)
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl https://api.browserbase.com/v1/agents/runs/$RUN_ID \
      --header "x-bb-api-key: $BROWSERBASE_API_KEY"
    ```
  </Tab>
</Tabs>

### Read or stream progress

To follow what the Agent is doing while it runs, poll [List run messages](/reference/api/list-run-messages). Save the response's `nextSince` and pass it back as `since` to fetch only newer messages:

<Tabs>
  <Tab title="Node.js">
    ```typescript Node.js theme={null}
    let since: string | undefined;

    while (true) {
      const page = await bb.agents.runs.listMessages(runId, {
        since,
        limit: 100,
      });

      for (const item of page.data) {
        console.log(item.message);
      }

      since = page.nextSince ?? since;

      const run = await bb.agents.runs.retrieve(runId);
      if (!["PENDING", "RUNNING"].includes(run.status)) break;
      await new Promise((resolve) => setTimeout(resolve, 2000));
    }
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import time

    since = None

    while True:
        params = {"limit": 100}
        if since:
            params["since"] = since

        page = bb.agents.runs.list_messages(run_id, **params)

        for item in page.data:
            print(item.message)

        since = page.next_since or since

        run = bb.agents.runs.retrieve(run_id)
        if run.status not in {"PENDING", "RUNNING"}:
            break
        time.sleep(2)
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl "https://api.browserbase.com/v1/agents/runs/$RUN_ID/messages?since=$LAST_MESSAGE_ID" \
      --header "x-bb-api-key: $BROWSERBASE_API_KEY"
    ```
  </Tab>
</Tabs>

Messages conform to the [AI SDK UIMessage format](https://ai-sdk.dev/docs/reference/ai-sdk-core/ui-message). Each item includes an `id`, `createdAt`, and a `message` with a `role` and `content`. Content can be text or typed parts such as reasoning, files, tool calls, and tool results.

<Note>
  Integration is poll-based today: track runs with [Get a run](/reference/api/get-a-run) and [List run messages](/reference/api/list-run-messages). Webhook notifications are planned.
</Note>

## Listing and filtering

Both list endpoints use cursor pagination. Pass the `nextCursor` from a response back as `cursor` to fetch the next page.

[List runs](/reference/api/list-runs) filters by `agentId`, `status`, and a `startAt`/`endAt` time range:

<Tabs>
  <Tab title="Node.js">
    ```typescript Node.js theme={null}
    const runs = await bb.agents.runs.list({
      agentId,
      status: "COMPLETED",
      limit: 20,
    });

    if (runs.nextCursor) {
      const nextPage = await bb.agents.runs.list({
        agentId,
        status: "COMPLETED",
        limit: 20,
        cursor: runs.nextCursor,
      });
    }
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    runs = bb.agents.runs.list(
        agent_id=agent_id,
        status="COMPLETED",
        limit=20,
    )

    if runs.next_cursor:
        next_page = bb.agents.runs.list(
            agent_id=agent_id,
            status="COMPLETED",
            limit=20,
            cursor=runs.next_cursor,
        )
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl "https://api.browserbase.com/v1/agents/runs?agentId=$AGENT_ID&status=COMPLETED&limit=20" \
      --header "x-bb-api-key: $BROWSERBASE_API_KEY"
    ```
  </Tab>
</Tabs>

[List Agents](/reference/api/list-agents) pages through your Agents with the same `cursor` pagination pattern.

## Next steps

<CardGroup cols={2}>
  <Card title="Node.js SDK" icon="code" iconType="sharp-solid" href="/reference/sdk/nodejs#agents">
    Complete Agents SDK method and type reference
  </Card>

  <Card title="Python SDK" icon="python" iconType="sharp-solid" href="/reference/sdk/python#agents">
    Complete Agents SDK method and type reference
  </Card>

  <Card title="Run an Agent" icon="terminal" iconType="sharp-solid" href="/reference/api/run-an-agent">
    Full request and response reference for a run
  </Card>

  <Card title="List run messages" icon="list" iconType="sharp-solid" href="/reference/api/list-run-messages">
    Stream a run's step-by-step transcript
  </Card>

  <Card title="Managing files" icon="file" iconType="sharp-solid" href="/platform/agents/managing-files">
    Retrieve files an Agent downloads during a run
  </Card>

  <Card title="How it works" icon="gear" iconType="sharp-solid" href="/platform/agents/how-it-works">
    The execution loop, run lifecycle, and observability
  </Card>
</CardGroup>
