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

# Parallelize work with subagents

> Let one manager agent split a task across specialist subagents, run them in parallel as child sessions, and merge their results.

export const MultiAgent = () => {
  const stroke = {
    fill: "none",
    stroke: "currentColor",
    strokeWidth: 1.75,
    strokeLinecap: "round",
    strokeLinejoin: "round"
  };
  const S = c => ({
    className: c,
    ...stroke
  });
  const icons = {
    user: c => <svg viewBox="0 0 24 24" {...S(c)}><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2" /><circle cx="12" cy="7" r="4" /></svg>,
    manager: c => <svg viewBox="0 0 24 24" {...S(c)}><circle cx="18" cy="5" r="3" /><circle cx="6" cy="12" r="3" /><circle cx="18" cy="19" r="3" /><path d="m8.59 13.51 6.83 3.98M15.41 6.51l-6.82 3.98" /></svg>,
    agent: c => <svg viewBox="0 0 24 24" {...S(c)}><path d="M12 8V4H8" /><rect width="16" height="12" x="4" y="8" rx="2" /><path d="M2 14h2M20 14h2M15 13v2M9 13v2" /></svg>,
    env: c => <svg viewBox="0 0 24 24" {...S(c)}><circle cx="12" cy="12" r="10" /><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20" /><path d="M2 12h20" /></svg>,
    model: c => <svg viewBox="0 0 24 24" {...S(c)}><rect width="16" height="16" x="4" y="4" rx="2" /><rect width="6" height="6" x="9" y="9" rx="1" /><path d="M15 2v2M15 20v2M2 15h2M2 9h2M20 15h2M20 9h2M9 2v2M9 20v2" /></svg>,
    skills: c => <svg viewBox="0 0 24 24" {...S(c)}><path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20" /></svg>
  };
  const Card = ({icon, title, sub, children, className = ""}) => <div className={className}>
      <div className="flex h-full flex-col rounded-xl border border-zinc-200 bg-white p-5 dark:border-zinc-800 dark:bg-zinc-950">
        <div className="flex items-center gap-2.5">
          <span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-zinc-100 text-zinc-700 dark:bg-zinc-800 dark:text-zinc-200">{icon("h-5 w-5")}</span>
          <div>
            <div className="whitespace-nowrap text-base font-semibold leading-6 text-zinc-900 dark:text-zinc-100">{title}</div>
            {sub && <div className="whitespace-nowrap text-sm text-zinc-500 dark:text-zinc-400">{sub}</div>}
          </div>
        </div>
        {children}
      </div>
    </div>;
  const Own = () => <div className="mt-4 flex gap-4 text-sm text-zinc-500 dark:text-zinc-400">
      {[["env", "environment"], ["model", "model"], ["skills", "skills"]].map(([k, label]) => <span key={k} className="flex items-center gap-1.5">
          <span className="text-zinc-400 dark:text-zinc-500">{icons[k]("h-4 w-4")}</span>
          {label}
        </span>)}
    </div>;
  const Stem = ({head = true}) => <div className="flex flex-col items-center text-zinc-400 dark:text-zinc-600">
      <span className="h-6 w-px bg-current" />
      {head && <svg className="-mt-px h-2 w-3" viewBox="0 0 12 8" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M1.5 1 6 6l4.5-5" /></svg>}
    </div>;
  const Link = ({label, head = true}) => <div className="relative flex justify-center py-1">
      <Stem head={head} />
      <span className="absolute left-1/2 top-0 ml-3 flex h-full items-center whitespace-nowrap text-xs text-zinc-500 dark:text-zinc-400">{label}</span>
    </div>;
  return <div className="not-prose my-8 overflow-x-auto">
      <div className="flex min-w-[720px] flex-col items-center">
        <Card icon={icons.user} title="You" sub="one session, one result" />

        <Link label="task" />

        <Card icon={icons.manager} title="Manager" sub="an agent with subagents">
          <Own />
        </Card>

        <Link label="splits the task, runs pieces in parallel" head={false} />

        <div className="grid w-full grid-cols-3">
          <div className="col-span-3 mx-[16.67%] h-px bg-zinc-400 dark:bg-zinc-600" />
          {[1, 2, 3].map(i => <div key={i} className="flex flex-col items-center px-2">
              <Stem />
              <Card icon={icons.agent} title={`Subagent ${i}`} sub="its own session" className="mt-1 w-full">
                <Own />
              </Card>
            </div>)}
        </div>
      </div>
    </div>;
};

<MultiAgent />

Any agent becomes a manager by listing other agents in its [`subagents`](/agents-api/agents/overview#configure-an-agent). You run it like any agent: one [session](/agents-api/sessions/overview), one result. Behind it, the manager splits the task, runs each piece as an isolated child session in parallel, may spawn follow-ups to fill gaps or verify findings, and merges the results.

It pays off on parallel work: collecting data from many sources, pairing a fast [text-mode](/agents-api/browser/configuration#modes) searcher with a visual subagent for pages that need real clicks, or having one subagent verify another.

## Build a manager

Create the subagents, then reference them by name from the manager so each stays reusable and inspectable (inline agent objects also work for one-offs).

* Write each subagent `description` as a capability statement ("Use for..."): the manager routes on it, the same way an agent [routes on a skill](/agents-api/skills/overview#how-an-agent-uses-a-skill).
* A manager that only delegates sends `environments: []`. Give it one only if it should also act on a surface itself.

<CodeGroup>
  ```bash cURL theme={"system"}
  API=https://agp.eu.hcompany.ai/api/v2
  AUTH="Authorization: Bearer $HAI_API_KEY"

  curl -X POST $API/agents -H "$AUTH" -H "Content-Type: application/json" -d '{
    "name": "fast-searcher",
    "description": "Searches the web quickly in text mode. Use for broad lookups.",
    "model": "holo4-35b-a3b",
    "environments": [{"id": "search-browser", "kind": "web", "mode": {"type": "text"}, "start_url": "https://www.bing.com"}]
  }'
  curl -X POST $API/agents -H "$AUTH" -H "Content-Type: application/json" -d '{
    "name": "visual-verifier",
    "description": "Visually inspects a page. Use to confirm a fact or read content behind interactions.",
    "environments": ["h/browser"]
  }'
  curl -X POST $API/agents -H "$AUTH" -H "Content-Type: application/json" -d '{
    "name": "research-orchestrator",
    "description": "Splits research across subagents and merges one sourced report.",
    "environments": [],
    "subagents": ["fast-searcher", "visual-verifier"]
  }'

  # Run it like any agent; read latest_answer once the session is terminal
  SESSION_ID=$(curl -sX POST $API/sessions -H "$AUTH" -H "Content-Type: application/json" \
    -d '{"agent": "research-orchestrator", "messages": "Compare the starting price of the latest Apple, Google, and Samsung flagship phones, with source URLs."}' \
    | jq -r .id)
  curl -s "$API/sessions/$SESSION_ID" -H "$AUTH" | jq -r .latest_answer
  ```

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

  client = Client()

  client.agents.create_agent(
      name="fast-searcher",
      description="Searches the web quickly in text mode. Use for broad lookups.",
      model="holo4-35b-a3b",
      environments=[{"id": "search-browser", "kind": "web", "mode": {"type": "text"}, "start_url": "https://www.bing.com"}],
  )
  client.agents.create_agent(
      name="visual-verifier",
      description="Visually inspects a page. Use to confirm a fact or read content behind interactions.",
      environments=["h/browser"],
  )
  client.agents.create_agent(
      name="research-orchestrator",
      description="Splits research across subagents and merges one sourced report.",
      environments=[],
      subagents=["fast-searcher", "visual-verifier"],
  )

  result = client.run_session(
      agent="research-orchestrator",
      messages="Compare the starting price of the latest Apple, Google, and Samsung flagship phones, with source URLs.",
  )
  print(result.answer)
  ```

  ```typescript TypeScript theme={"system"}
  import { HaiAgentsClient } from "hai-agents";

  const client = new HaiAgentsClient();

  await client.agents.createAgent({
    name: "fast-searcher",
    description: "Searches the web quickly in text mode. Use for broad lookups.",
    model: "holo4-35b-a3b",
    environments: [{ id: "search-browser", kind: "web", mode: { type: "text" }, startUrl: "https://www.bing.com" }],
  });
  await client.agents.createAgent({
    name: "visual-verifier",
    description: "Visually inspects a page. Use to confirm a fact or read content behind interactions.",
    environments: ["h/browser"],
  });
  await client.agents.createAgent({
    name: "research-orchestrator",
    description: "Splits research across subagents and merges one sourced report.",
    environments: [],
    subagents: ["fast-searcher", "visual-verifier"],
  });

  const result = await client.runSession({
    agent: "research-orchestrator",
    messages: "Compare the starting price of the latest Apple, Google, and Samsung flagship phones, with source URLs.",
  });
  console.log(result.answer);
  ```
</CodeGroup>

From the CLI, run an existing manager with `hai run --agent research-orchestrator "..."`. Over raw HTTP, long-poll [`changes`](/agents-api/sessions/changes) until the session is terminal before reading `latest_answer`.

## What a subagent sees

| Rule | Consequence |
| - | - |
| No access to the end user: it can't ask you questions or message you. | Give it a self-contained task. Only the manager surfaces anything. |
| The manager gets only its final answer, not its scrollback or observations. | A good subagent answer carries its own data, source URLs, and caveats. |
| It can delegate further: listing its own `subagents` makes it a manager. | Nesting is capped at 16 levels. The API rejects a deeper chain or a cycle with `422`. Stay well below it: each level multiplies sessions and cost. |

## Observe and control the tree

* The manager's [status](/agents-api/sessions/status) lists its children in `subagent_session_ids`. [Retrieve](/agents-api/sessions/retrieve) or [watch](/agents-api/observe-and-steer) any of them like a normal session.
* List children with `GET /sessions?parent_session_id=...`, or tag a whole run with [`group_id`](/agents-api/sessions/create) and list it with `GET /sessions?group_id=...`.
* [Force an answer](/agents-api/sessions/force-answer) on the manager cascades: in-flight subagents get about 30s to wrap up, partial results fold into the manager's answer, and anything unfinished is cancelled. [Cancelling](/agents-api/sessions/cancel) the manager stops its subagents too, with no grace window.
* Child sessions never [queue](/agents-api/plans-and-limits#queued-sessions): at your concurrency limit, a child create fails with `429`.

Related: [Watch and steer sessions](/agents-api/observe-and-steer), [Get typed answers](/agents-api/structured-output)


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