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

# Parallelize work with subagents

> Let one manager agent split a task and delegate the pieces to specialist subagents.

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 breaks the task into pieces, hands each piece to a subagent, and wraps up once the pieces are done. 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: researching a question across 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

A manager is just an [agent](/agents-api/agents/overview) whose [`subagents`](/agents-api/agents/overview#configure-an-agent) list names other agents. 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": "Researches a question across sources and synthesizes a sourced answer.",
          "environments": ["h/browser"],
          "instructions": "Split the question into independent sub-questions, delegate each, then reconcile the findings into one sourced answer.",
          "subagents": ["fast-searcher", "visual-verifier"]
        }'
      ```

      ```python Python theme={"system"}
      client.agents.create_agent(
          name="research-orchestrator",
          description="Researches a question across sources and synthesizes a sourced answer.",
          environments=["h/browser"],
          instructions=(
              "Split the question into independent sub-questions, delegate each, "
              "then reconcile the findings into one sourced answer."
          ),
          subagents=["fast-searcher", "visual-verifier"],
      )
      ```

      ```typescript TypeScript theme={"system"}
      await client.agents.createAgent({
        name: "research-orchestrator",
        description: "Researches a question across sources and synthesizes a sourced answer.",
        environments: ["h/browser"],
        instructions:
          "Split the question into independent sub-questions, delegate each, " +
          "then reconcile the findings into one sourced answer.",
        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. The fan-out to subagents happens behind it. Over raw HTTP, create the session and long-poll [`changes`](/agents-api/sessions/changes) until it reaches a terminal state.

    <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)

      # Long-poll /changes until the status is terminal, as in the Quickstart,
      # then read the settled answer from the session snapshot.
      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>

    The cURL tab skips the polling loop. Copy it from the [Quickstart](/agents-api/quickstart#run-a-session).
  </Step>
</Steps>

## How a run unfolds

The manager spawns subagents as parallel child sessions, waits for their answers, and may spawn follow-ups to fill gaps or verify findings before synthesizing the single final answer your session receives.

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