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

# Code agent

> A Holo agent with no screen: it writes Python, runs it, reads the output, and answers. One file, one tool.

This is the [browser agent](/models-api/cookbooks/browser-agent) loop with two changes: no screenshots, and one tool, `run_python`. Holo writes a script, runs it, reads the output, and answers. Each run's output goes back as a `tool` message.

<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="Save the agent">
    Install with `pip install openai` and export `HAI_API_KEY`, then save:

    ```python code_agent.py expandable theme={"system"}
    import json
    import os
    import subprocess
    import sys

    from openai import OpenAI

    client = OpenAI(base_url="https://api.hcompany.ai/v1/", api_key=os.environ["HAI_API_KEY"])
    MODEL = "holo4-35b-a3b"


    def fn(name: str, description: str, **properties) -> dict:
        parameters = {"type": "object", "properties": properties, "required": list(properties)}
        return {"type": "function", "function": {"name": name, "description": description, "parameters": parameters}}


    tools = [
        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"}),
    ]


    def run_python(code: str) -> str:
        try:
            proc = subprocess.run([sys.executable, "-c", 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)"


    def run(task: str, max_steps: int = 10) -> str:
        messages = [
            {"role": "system", "content": "You solve tasks by writing and running Python. Verify results by running code before answering."},
            {"role": "user", "content": task},
        ]
        for _ in range(max_steps):
            resp = client.chat.completions.create(
                model=MODEL,
                messages=messages,
                tools=tools,
                tool_choice="required",
                temperature=0.8,
                extra_body={"chat_template_kwargs": {"enable_thinking": True}},
            )
            msg = resp.choices[0].message
            messages.append({"role": "assistant", "content": msg.content, "tool_calls": msg.tool_calls})
            if not msg.tool_calls:
                continue
            call = msg.tool_calls[0]
            args = json.loads(call.function.arguments)
            if call.function.name == "answer":
                return args["content"]
            print(f"--- run_python\n{args['code']}")
            result = run_python(args["code"])
            print(f"--- output\n{result}")
            messages.append({"role": "tool", "tool_call_id": call.id, "content": result})
        return "Step budget exhausted"


    if __name__ == "__main__":
        print(run("How many prime numbers are there below 1,000,000, and what is the largest one?"))
    ```
  </Step>

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

    ```text Output expandable theme={"system"}
    --- run_python
    def count_primes_and_find_largest(limit):
        primes = []
        for num in range(2, limit):
            is_prime = True
            for prime in primes:
                if prime * prime > num:
                    break
                if num % prime == 0:
                    is_prime = False
                    break
            if is_prime:
                primes.append(num)
        return len(primes), primes[-1]

    count, largest = count_primes_and_find_largest(1000000)
    print(f"Count: {count}, Largest: {largest}")
    --- output
    Count: 78498, Largest: 999983

    There are 78,498 prime numbers below 1,000,000, and the largest one is 999,983.
    ```
  </Step>
</Steps>

## How it works

* **Output cap.** Each result keeps the last 4,000 characters, so a runaway `print` cannot flood the context.
* **Errors are feedback.** `stderr` goes back with `stdout`: Holo reads the traceback and fixes it next step.
* **Timeouts.** `run_python` kills each script after 30 seconds and tells Holo. Raise the timeout for heavier jobs.

The same pattern fits any runner (`bash`, a Jupyter kernel, a remote sandbox): one tool per runtime, described in plain words.


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