> ## 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). At runtime the manager splits the task into pieces, hands each piece to a subagent, may spawn follow-ups to fill gaps or verify findings, and merges the results. You launch a manager exactly like any other agent: one [session](/agents-api/sessions/overview), one result. The fan-out happens behind it.

Each subagent is a full [agent](/agents-api/agents/overview) with its own environment, model, skills, and instructions, and runs as its own [session](/agents-api/sessions/overview), isolated from its siblings. The manager runs them in parallel, so breadth that would be sequential for one agent happens at once.

Multi-agent is especially efficient for parallelizable tasks: collecting data from many sources at once, 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 what another found.

## Build a manager

Create the specialists first, then reference them by name from the manager so each stays reusable and independently inspectable (inline objects also work, for one-offs). Here a research manager delegates to a fast text-mode searcher and a visual verifier.

<Steps titleSize="h3">
  <Step id="create-subagents" title="Create the subagents">
    Create a fast [text-mode](/agents-api/browser/configuration#modes) searcher for broad lookups and a visual verifier for pages that need real clicks. Write each `description` as a capability statement ("Use for…"), since the manager routes on it to pick who handles what, the same way an agent [routes on a skill](/agents-api/skills/overview#how-an-agent-uses-a-skill).

    <CodeGroup>
      ```bash cURL theme={"system"}
      # Fast text-mode searcher
      curl -X POST https://agp.eu.hcompany.ai/api/v2/agents \
        -H "Authorization: Bearer $HAI_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "name": "fast-searcher",
          "description": "Searches the web quickly in text mode. Use for broad lookups and gathering candidate sources.",
          "model": "holo3-1-35b-a3b",
          "environments": [
            {"id": "search-browser", "kind": "web", "mode": {"type": "text"}, "start_url": "https://www.bing.com"}
          ]
        }'

      # Visual verifier
      curl -X POST https://agp.eu.hcompany.ai/api/v2/agents \
        -H "Authorization: Bearer $HAI_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "name": "visual-verifier",
          "description": "Visually inspects a specific page to confirm a fact or read content behind interactions.",
          "environments": ["h/browser"]
        }'
      ```

      ```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 "
              "and gathering candidate sources."
          ),
          model="holo3-1-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 specific page to confirm a fact or read "
              "content behind interactions."
          ),
          environments=["h/browser"],
      )
      ```

      ```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 and gathering candidate sources.",
        model: "holo3-1-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 specific page to confirm a fact or read content behind interactions.",
        environments: ["h/browser"],
      });
      ```
    </CodeGroup>
  </Step>

  <Step id="create-the-manager" title="Create the manager">
    Now create the manager and link the subagents by name. A manager that only delegates can omit `environments`; give it one only if it should also act on a surface itself, as this one does.

    <CodeGroup>
      ```bash cURL theme={"system"}
      curl -X POST https://agp.eu.hcompany.ai/api/v2/agents \
        -H "Authorization: Bearer $HAI_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "name": "research-orchestrator",
          "description": "Splits research work across subagents and merges their results into one sourced report.",
          "environments": ["h/browser"],
          "instructions": "Split the task into independent pieces, delegate each, then merge the findings into one sourced report.",
          "subagents": ["fast-searcher", "visual-verifier"]
        }'
      ```

      ```python Python theme={"system"}
      client.agents.create_agent(
          name="research-orchestrator",
          description="Splits research work across subagents and merges their results into one sourced report.",
          environments=["h/browser"],
          instructions=(
              "Split the task into independent pieces, delegate each, "
              "then merge the findings into one sourced report."
          ),
          subagents=["fast-searcher", "visual-verifier"],
      )
      ```

      ```typescript TypeScript theme={"system"}
      await client.agents.createAgent({
        name: "research-orchestrator",
        description: "Splits research work across subagents and merges their results into one sourced report.",
        environments: ["h/browser"],
        instructions:
          "Split the task into independent pieces, delegate each, " +
          "then merge the findings into one sourced report.",
        subagents: ["fast-searcher", "visual-verifier"],
      });
      ```
    </CodeGroup>
  </Step>

  <Step id="run-a-session" title="Run a session">
    Launch a session against the manager exactly like a single agent. Over raw HTTP, create the session, long-poll [`changes`](/agents-api/sessions/changes) until it reaches a terminal state, then read `latest_answer` off the session.

    <CodeGroup>
      ```bash CLI theme={"system"}
      hai run --agent research-orchestrator \
        "Compare the starting price of the latest flagship phone from Apple, Google, and Samsung. Return one line per phone with the price, currency, and the source URL you read it from."
      ```

      ```bash cURL theme={"system"}
      # Create the session and capture its id
      SESSION_ID=$(curl -sX POST https://agp.eu.hcompany.ai/api/v2/sessions \
        -H "Authorization: Bearer $HAI_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "agent": "research-orchestrator",
          "messages": [
            {"type": "user_message", "message": "Compare the starting price of the latest flagship phone from Apple, Google, and Samsung. Return one line per phone with the price, currency, and the source URL you read it from."}
          ]
        }' | jq -r .id)

      # Once the session has finished, read the settled answer
      curl -s "https://agp.eu.hcompany.ai/api/v2/sessions/$SESSION_ID" \
        -H "Authorization: Bearer $HAI_API_KEY" | jq -r .latest_answer
      ```

      ```python Python theme={"system"}
      result = client.run_session(
          agent="research-orchestrator",
          messages="Compare the starting price of the latest flagship phone from Apple, Google, and Samsung. Return one line per phone with the price, currency, and the source URL you read it from.",
      )

      print(result.status)  # "completed"
      print(result.answer)
      ```

      ```typescript TypeScript theme={"system"}
      const result = await client.runSession({
        agent: "research-orchestrator",
        messages:
          "Compare the starting price of the latest flagship phone from Apple, Google, and " +
          "Samsung. Return one line per phone with the price, currency, and the source URL you read it from.",
      });

      console.log(result.status); // "completed"
      console.log(result.answer);
      ```
    </CodeGroup>
  </Step>
</Steps>

## What a subagent sees

A subagent works in isolation and is instructed to finish its task on its own:

* It has no access to the end user. It cannot ask questions or send messages to you. Only the manager surfaces anything. Give it a self-contained task.
* The manager receives only the subagent's final answer, not its scrollback or intermediate observations. A good subagent answer carries its own data, source URLs, and caveats.
* It can delegate further. A subagent that lists its own `subagents` becomes a manager for them, nested up to 16 levels deep. A deeper chain or a cycle is rejected with `422`. Keep trees shallow well before that limit, since deep nesting multiplies sessions and cost.

## Observe and control the tree

Each subagent is a real session, so the whole tree is inspectable and steerable:

* The manager's [status](/agents-api/sessions/status) lists its children in `subagent_session_ids`. [Retrieve](/agents-api/sessions/retrieve) or watch any of them like a normal session.
* Filter children by their parent 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 and the signal cascades: in-flight subagents get a short grace window (about 30s) to wrap up, partial results fold into the manager's answer, and anything still unfinished is cancelled. [Cancelling](/agents-api/sessions/cancel) the manager stops its subagents too, without the grace window.

## Next steps

<CardGroup cols={2}>
  <Card title="Watch and steer sessions" icon="eye" href="/agents-api/observe-and-steer">
    Stream events from the manager and any child.
  </Card>

  <Card title="Get typed answers" icon="brackets-curly" href="/agents-api/structured-output">
    Make the manager return a schema-validated result.
  </Card>
</CardGroup>
