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

# Hybrid agent

> One Holo agent with both a browser and a Python runner. It reads the page with clicks, then switches to code for the part a script does better.

Holo4 is trained on tasks that cross interfaces, so it does not need a separate agent per tool. This cookbook starts from the [browser agent](/models-api/cookbooks/browser-agent) and adds the Python runner from the [code agent](/models-api/cookbooks/code-agent). Asked to find two dates and compute the gap between them, Holo reads the dates off the page and leaves the arithmetic to Python.

<Warning>
  This example runs model-written code on your machine with `subprocess`. Outside a demo, run it in a container or a sandbox with no network and no secrets.
</Warning>

<Steps titleSize="h3">
  <Step title="Start from the browser agent">
    Install and save [`browser_agent.py`](/models-api/cookbooks/browser-agent#save-the-agent), then make the edits below. Nothing else changes.
  </Step>

  <Step title="Add the runner">
    Import `subprocess` and `sys`, and register `run_python` next to the screen tools:

    ```python browser_agent.py highlight={4-5,14} theme={"system"}
    import base64
    import json
    import os
    import subprocess
    import sys

    # ...

    tools = [
        fn("click", "Click at (x, y) coordinates", element={"type": "string", "description": "Detailed description of the target UI element"}, x=INT, y=INT),
        fn("type", "Type text into the focused element, optionally pressing Enter", text={"type": "string"}, press_enter={"type": "boolean"}),
        fn("scroll", "Scroll the page", direction={"type": "string", "enum": ["up", "down"]}),
        fn("goto", "Navigate to a URL", url={"type": "string"}),
        fn("run_python", "Run a Python script and return its stdout and stderr. Print anything you want to see.", code={"type": "string", "description": "Python source code"}),
        fn("answer", "Provide a final answer", content={"type": "string", "description": "The answer content"}),
    ]
    ```
  </Step>

  <Step title="Route the call">
    Handle `run_python` first in `execute`, before the screen actions:

    ```python browser_agent.py highlight={2-7} theme={"system"}
    def execute(page, name: str, args: dict) -> str:
        if name == "run_python":
            try:
                proc = subprocess.run([sys.executable, "-c", args["code"]], capture_output=True, text=True, timeout=30)
            except subprocess.TimeoutExpired:
                return "Timed out after 30 seconds"
            return (proc.stdout + proc.stderr)[-4000:] or "(no output)"
        if name == "click":
            # ... unchanged
    ```
  </Step>

  <Step title="Update the prompt and task">
    ```python browser_agent.py theme={"system"}
    {"role": "system", "content": "You are a web agent. You see the browser through screenshots and act with your tools. Use run_python for any computation."},

    # ...

    print(run("On Wikipedia, find Ada Lovelace's birth and death dates, then compute exactly how many days she lived.", "https://en.wikipedia.org"))
    ```
  </Step>

  <Step title="Run it">
    ```bash theme={"system"}
    python browser_agent.py
    ```

    ```text Output theme={"system"}
    --- click({'element': 'Search bar at the top of Wikipedia', 'x': 359, 'y': 39})
    --- type({'text': 'Ada Lovelace', 'press_enter': True})
    --- run_python({'code': 'from datetime import date\n\nbirth = date(1815, 12, 10)\ndeath = date(1852, 11, 27)\ndays_lived = (death - birth).days\nprint(f"Days lived: {days_lived}")'})
    Ada Lovelace was born on December 10, 1815 and died on November 27, 1852. She lived for exactly 13,502 days.
    ```

    Two screen steps to read the dates, one code step to count the days.
  </Step>
</Steps>

## How it works

* **One loop, one toolbox.** The model sees every tool on every step and chooses by what the step needs. There is no router and no second agent.
* **Screenshots keep coming.** Every step still sends a fresh screenshot, including after `run_python`. The page has not changed, and the model keeps its view of it.
* **Add more interfaces the same way.** MCP tools from the [MCP agent](/models-api/cookbooks/mcp-agent) slot into the same `tools` list; route their names to `session.call_tool`.

## Next steps

<CardGroup cols={2}>
  <Card title="Function calling" icon="wrench" href="/models-api/build-an-agent/function-calling#mix-screen-code-and-mcp-tools">
    Mixing screen, code, and MCP tools.
  </Card>

  <Card title="Core concepts" icon="arrows-rotate" href="/models-api/build-an-agent/core-concepts">
    The loop conventions Holo is trained on.
  </Card>
</CardGroup>
