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

> ## Agent Instructions
> H Platform has four products: the Agents API (managed computer-use agents, base URL https://agp.eu.hcompany.ai/api/v2 or https://agp.hcompany.ai/api/v2 for the US), the Models API (OpenAI-compatible Holo vision-language models at https://api.hcompany.ai/v1), HoloDesktop CLI (Holo on the user's own desktop), and HoloTab (a free no-code Chrome extension that runs Holo in the user's browser, with recordable routines and schedules).
> Authenticate with a bearer API key from the HAI_API_KEY environment variable. SDKs: `pip install hai-agents` (Python, `from hai_agents import Client`) and `npm install hai-agents` (TypeScript, `import { HaiAgentsClient } from "hai-agents"`). CLI: `hai`.
> Agents do work in a browser or on a desktop; describe the task as an imperative instruction. To run a task quickly, prefer the pre-built agent `h/web-surfer-flash`. Read results from the session's `latest_answer` after it reaches a terminal status.
> Sessions are the unit of work; wait for a terminal status (completed, failed, timed_out, interrupted) before reading the answer. Use webhooks or the `changes` long-poll endpoint to follow progress.

# Local control

> Let a cloud agent drive Chrome or the whole desktop on your own machine, with your logins, files, and apps.

export const Notice = ({kind = "note", title, children}) => {
  const kinds = {
    warning: {
      label: "User notice",
      icon: <>
          <path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" />
          <path d="M12 9v4" />
          <path d="M12 17h.01" />
        </>
    },
    gotcha: {
      label: "Gotcha",
      icon: <>
          <circle cx="12" cy="12" r="10" />
          <path d="M12 16v-4" />
          <path d="M12 8h.01" />
        </>
    },
    note: {
      label: "Note",
      icon: <>
          <circle cx="12" cy="12" r="10" />
          <path d="M12 16v-4" />
          <path d="M12 8h.01" />
        </>
    }
  };
  const k = kinds[kind];
  return <div className="notice my-6 rounded-xl border border-zinc-200 bg-white p-5 dark:border-zinc-800 dark:bg-zinc-950">
      <div className={`${kind === "warning" ? "not-prose flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-red-400/80 dark:text-red-400/70" : kind === "gotcha" ? "not-prose flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-amber-500/80 dark:text-amber-400/70" : "not-prose flex items-center gap-1.5 text-xs font-semibold uppercase tracking-wide text-zinc-400 dark:text-zinc-500"}`}>
        <svg className="h-3.5 w-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          {k.icon}
        </svg>
        {k.label}
      </div>
      {title && <div className="not-prose mt-2 text-base font-semibold text-zinc-900 dark:text-zinc-100">{title}</div>}
      <div className="notice-body mt-3 text-sm leading-6 text-zinc-700 dark:text-zinc-300">{children}</div>
    </div>;
};

With local control, the agent runs in H's cloud and drives a browser or desktop on your own machine. The [agent](/agents-api/agents/overview) and [session](/agents-api/sessions/overview) lifecycle stays the same. Local control ships in the [`hai-agents`](/agents-api/sdks) Python SDK only.

Local control is not [local mode](/agents-api/local-mode): here only the browser or desktop is on your machine, while in local mode (`Client.local()`) the agent itself runs there too.

| | Browser | Desktop |
| - | - | - |
| The agent drives | Chrome on your machine | Your real mouse, keyboard, and screen (macOS, Windows, Linux) |
| Use it for | Sites you are signed in to, pages on your local network | Native apps, the file system, multi-window flows |
| Environment | `{"kind": "web", "host": "user_device"}` | `{"kind": "desktop", "host": "user_device"}` |
| Install extra | `hai-agents[browser]` | `hai-agents[desktop]` |
| CLI server | `hai local browser` | `hai local desktop` |

<Notice kind="warning" title="The agent acts on your real machine">
  In a local browser, the agent can browse, run page scripts, and read that Chrome's cookies and storage. On a local desktop, it can move the mouse, type, read anything on screen, run shell commands, and read or write files. Prefer a dedicated machine over your primary one.

  Stop a run at any time: [cancel the session](/agents-api/sessions/overview#lifecycle) with `hai sessions cancel <session-id>`, or run `hai local stop` in any terminal to stop every local session on this machine.
</Notice>

## How it works

A local environment is a normal [environment](/agents-api/environments/overview) with `host: "user_device"`. When a session starts, the SDK opens a connection inside your Python process. The connection receives the agent's actions, carries them out on your machine, and ties this session to this machine. [Observe and steer](/agents-api/observe-and-steer), [changes](/agents-api/sessions/changes), and [Agent View](/agents-api/observe-and-steer#watch-a-run) work as for a cloud run.

* **One at a time.** A Python process drives one local browser (or desktop) at a time. A new session on it takes it over and cancels the earlier session.
* **Tied to your process.** The connection closes when your Python process exits, and the sessions it served are cancelled (Chrome stays open). If the connection drops mid-session, the session is cancelled too.
* **Cloud-only fields.** [Vaults](/agents-api/vaults/overview) and [browser profiles](/agents-api/browser/profiles) apply to cloud browsers only. Your local Chrome's own logins fill that role.

### Auto-connect scope

| You start the session with | Connection |
| - | - |
| An agent spec or object passed to `run_session`, `start_session`, or `create_session` | The SDK connects your machine for you. |
| A registered agent referenced by name, or from the web app or another machine | Serve the machine with `hai local browser` or `hai local desktop`, then set the printed `session_id` on the `user_device` environment (see the CLI tabs below). |
| `HAI_AUTO_BRIDGE=0` set | Auto-connect is off. Serve the machine yourself, as above. |

## Install

The drivers come from the [`hai-drivers`](https://pypi.org/project/hai-drivers/) package, as optional extras. Add `cli` for the `hai` command.

```bash Install theme={"system"}
pip install "hai-agents[cli,browser]"   # local browser
pip install "hai-agents[cli,desktop]"   # local desktop
```

## Run a session

Create an agent whose environment sets `host` to `user_device`, then run a session with it. In Python there is nothing else to set up. From the CLI, serve your machine and point the agent at the `session_id` it prints (the CLI tab reuses the agent created in the Python tab).

<Tabs>
  <Tab title="Browser">
    <CodeGroup>
      ```bash CLI theme={"system"}
      # Serve the browser and leave it running; it prints the session_id it serves.
      hai local browser

      # In another terminal, route the agent's browser environment here.
      hai run "Open news.ycombinator.com and summarize the top story" \
        --agent local-web \
        -o 'agent.environments[kind=web].session_id=<printed id>'
      ```

      ```python Python theme={"system"}
      from hai_agents import Client

      client = Client()

      agent = client.agents.create_agent(
          name="local-web",
          description="Drives a browser on my own machine.",
          environments=[{"id": "my-laptop", "kind": "web", "host": "user_device"}],
      )

      result = client.run_session(
          agent=agent,
          messages="Open news.ycombinator.com and summarize the top story",
      )
      print(result.status, result.answer)
      ```
    </CodeGroup>

    `hai local browser` flags: `--session-id` (generated when omitted) and `--debug-port` (default `9222`).

    **The Chrome it drives.** The SDK attaches to a Chrome with remote debugging open on port `9222`. If none is running, it launches one with its own profile in `~/.hai/chrome-profile`. That profile persists across runs: sign in once and the agent finds you signed in next time. The SDK never touches your everyday Chrome profile (Chrome does not allow remote debugging on it).

    To drive a different Chrome, start it yourself before the session. Chrome only opens the debugging port with `--user-data-dir`, so pick a dedicated directory and keep it for the logins you want the agent to have.

    <CodeGroup>
      ```bash macOS theme={"system"}
      /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
        --remote-debugging-port=9222 --user-data-dir="$HOME/chrome-for-agents"
      ```

      ```bash Linux theme={"system"}
      google-chrome --remote-debugging-port=9222 --user-data-dir="$HOME/chrome-for-agents"
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Desktop">
    <CodeGroup>
      ```bash CLI theme={"system"}
      # Serve the desktop and leave it running; it prints the session_id it serves.
      hai local desktop

      # In another terminal, route the agent's desktop environment here.
      hai run "Open Notes and write a short summary of today's standup" \
        --agent local-desktop \
        -o 'agent.environments[kind=desktop].session_id=<printed id>'
      ```

      ```python Python theme={"system"}
      from hai_agents import Client

      client = Client()

      agent = client.agents.create_agent(
          name="local-desktop",
          description="Drives the desktop on my own machine.",
          environments=[{"id": "my-laptop", "kind": "desktop", "host": "user_device"}],
      )

      result = client.run_session(
          agent=agent,
          messages="Open Notes and write a short summary of today's standup",
      )
      print(result.status, result.answer)
      ```
    </CodeGroup>

    `hai local desktop` downscales and recompresses screenshots before upload. Its flags:

    | Flag | Default | Meaning |
    | - | - | - |
    | `--session-id` | generated | Session id to serve. |
    | `--max-width` | `1920` | Cap screenshot width in pixels. `0` disables. |
    | `--max-height` | `0` | Cap screenshot height in pixels. `0` disables. |
    | `--image-format` | `jpeg` | `png`, `jpeg`, or `webp`. |
    | `--quality` | `85` | Encoding quality (1 to 100) for `jpeg` and `webp`. |

    **Double-Esc kill switch.** In an interactive terminal, `hai local desktop` also stops when you press Esc twice fast. On macOS, grant your terminal Input Monitoring. On Linux, it needs `pynput` and an X11 session (Wayland has no global key listener). If it cannot arm, it says so: use `hai local stop`.

    **OS permissions (macOS).** The program running the agent (your terminal, or the app that launches Python) needs two grants in **System Settings > Privacy & Security**. Your first session triggers the prompts and stops with an error until you grant both. Grant them, restart the program, and run again.

    * **Accessibility**, to move the mouse and type.
    * **Screen Recording**, to read the screen.

    On Windows and Linux there is nothing to grant. Run the program in a normal desktop session so it can reach the display.
  </Tab>
</Tabs>

Related: [Browser configuration](/agents-api/browser/configuration), [Observe and steer](/agents-api/observe-and-steer), [Local mode](/agents-api/local-mode).


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