> ## Documentation Index
> Fetch the complete documentation index at: https://docs.labelbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Run a research team

> Run a team of agents that researches three options in parallel, reviews each finding, and delivers one graded recommendation.

In this tutorial, a team compares three vector databases for a semantic search service. The leader splits the work into one research task per database plus a review of each, teammates work in parallel, and the leader writes one recommendation as a named deliverable. An outcome grades the recommendation before the session completes.

The TypeScript samples assume the `rl` client from [Client setup](/managed-agents/api#client-setup).

## Before you begin

* You need the Developer or Admin role in the organization. See [Organizations and roles](/managed-agents/organizations-and-roles).
* Read [Teams](/managed-agents/teams) for how the board works.
* A team runs several agents at once, so it costs more than a single agent. This tutorial caps the team at four teammates.

```mermaid theme={"theme":"css-variables"}
flowchart LR
  agent["Create a research agent"]
  env["Create an environment"]
  start["Start a team session with an outcome"]
  board["Watch the board"]
  grade["Wait for the grade"]
  report["Read the recommendation"]
  agent --> env --> start --> board --> grade --> report
```

## Step 1: Create the research agent

The agent needs web search, which is on by default, and a team size. The team size is `max_concurrent_threads`. No roster entries are needed, because teammates are copies of this agent.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Agents**, then click **Create agent** and choose **Blank**.
    2. Enter a **Name**, choose a model, and paste the system prompt from the TypeScript tab into **System prompt**. Click **Create agent**.
    3. On the **Configuration** tab, under **Multiagent**, set **Work as a team** to **Always**.
    4. Under **Tools**, confirm **Web search** is on.
    5. Click **Save new version**.

    The console doesn't set the team size, so the team uses the default of 8. Use the API to cap it.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const agent = await rl.managedAgents.createAgent({
      body: {
        name: 'Research lead',
        model: 'anthropic/claude-sonnet-5',
        system: [
          'You research technical choices for an engineering team.',
          'Cite a source URL for every factual claim, and prefer official documentation and independent benchmarks.',
          'Keep working notes in /workspace/research. Save final reports as deliverables.',
        ].join('\n'),
        multiagent: {
          type: 'coordinator',
          agents: [],
          team: { mode: 'on' },
          limits: { max_concurrent_threads: 4 },
        },
      },
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/agents' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{
        "name": "Research lead",
        "model": "anthropic/claude-sonnet-5",
        "system": "You research technical choices for an engineering team.\nCite a source URL for every factual claim, and prefer official documentation and independent benchmarks.\nKeep working notes in /workspace/research. Save final reports as deliverables.",
        "multiagent": {
          "type": "coordinator",
          "agents": [],
          "team": {"mode": "on"},
          "limits": {"max_concurrent_threads": 4}
        }
      }'
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "agent_id": "5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55",
  "latest_agent_version_id": "c1a94e07-2f6b-4d18-b3a5-0e7d8c6f4a21",
  "name": "Research lead",
  "web_search_enabled": true,
  "multiagent": {
    "type": "coordinator",
    "agents": [],
    "team": {"mode": "on"},
    "limits": {"max_concurrent_threads": 4}
  }
}
```

## Step 2: Create an environment

Web search and web fetch run outside the sandbox, so they work even when the environment blocks internet access. The team only needs a sandbox for its notes and the deliverable, so the default closed environment is enough.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Environments**, then click **Create environment**.
    2. Enter a **Name**, such as `research`, and leave **Internet access** at **No access**.
    3. Click **Create environment**.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const environment = await rl.managedAgents.createEnvironment({
      body: { name: 'research', provider: 'runs' },
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/environments' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{"name": "research", "provider": "runs"}'
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "organization_id": "cl9x2k4f1000008l5h3g7a2bq",
  "environment_id": "9d3e7b52-1a4c-4f80-b6e9-2c8a5d0f7e13",
  "name": "research",
  "scope": "organization",
  "provider": "runs",
  "computer_use": false,
  "created_at": "2026-09-25T16:50:31Z",
  "updated_at": "2026-09-25T16:50:31Z"
}
```

## Step 3: Start the team session

The outcome's description is the brief the leader splits into tasks, and the grader measures against it. The `message` carries context the agents need but the grader doesn't score. The rubric names the deliverable, so grading checks that it exists and is complete.

A good brief names the independent pieces, where each one writes, the review you want, how the result is judged, and the deliverable. See [Write a good team brief](/managed-agents/teams#write-a-good-team-brief).

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Sessions**, then click **Launch session**.
    2. Choose the **Research lead** agent and the **research** environment.
    3. Under **Task**, select **Grade this session against a rubric**, and paste the rubric from the TypeScript tab into **Rubric**.
    4. In **Opening message**, paste the brief and then the context from the TypeScript tab.
    5. Under **Team**, confirm **Work as a team** is **Always**.
    6. Click **Launch session**.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const { session_id: sessionId } = await rl.managedAgents.startSession({
      'Idempotency-Key': 'vector-db-review-2026-09-25',
      body: {
        agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
        environment_id: '9d3e7b52-1a4c-4f80-b6e9-2c8a5d0f7e13',
        message:
          'Context: we run on Kubernetes, index about 40 million 768-dimension embeddings, filter every query by tenant, and have two engineers for operations.',
        team: { mode: 'on' },
        outcome: {
          description: [
            'Recommend one vector database for our semantic search service: Qdrant, Weaviate, or Milvus.',
            'Research each one in its own task from official docs and at least one independent benchmark, writing notes to /workspace/research/<name>.md.',
            'Have a different teammate check each set of notes.',
            'Save the recommendation as vector-db-recommendation.md, and end with its comparison table and recommendation.',
          ].join(' '),
          rubric: [
            '- vector-db-recommendation.md is a deliverable.',
            '- It has a table with one row each for Qdrant, Weaviate, and Milvus, covering tenant filtering, Kubernetes deployment, and operational effort.',
            '- Every row cites at least one source URL.',
            '- It recommends exactly one option and explains why it fits 40 million 768-dimension embeddings with tenant filtering.',
            '- It names at least one risk of the recommended option.',
          ].join('\n'),
          max_iterations: 3,
        },
      },
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/sessions' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Idempotency-Key: vector-db-review-2026-09-25' \
      -H 'Content-Type: application/json' \
      -d '{
        "agent_id": "5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55",
        "environment_id": "9d3e7b52-1a4c-4f80-b6e9-2c8a5d0f7e13",
        "message": "Context: we run on Kubernetes, index about 40 million 768-dimension embeddings, filter every query by tenant, and have two engineers for operations.",
        "team": {"mode": "on"},
        "outcome": {
          "description": "Recommend one vector database for our semantic search service: Qdrant, Weaviate, or Milvus. Research each one in its own task from official docs and at least one independent benchmark, writing notes to /workspace/research/<name>.md. Have a different teammate check each set of notes. Save the recommendation as vector-db-recommendation.md, and end with its comparison table and recommendation.",
          "rubric": "- vector-db-recommendation.md is a deliverable.\n- It has a table with one row each for Qdrant, Weaviate, and Milvus, covering tenant filtering, Kubernetes deployment, and operational effort.\n- Every row cites at least one source URL.\n- It recommends exactly one option and explains why it fits 40 million 768-dimension embeddings with tenant filtering.\n- It names at least one risk of the recommended option.",
          "max_iterations": 3
        }
      }'
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "session_id": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
  "status_path": "/v1/sessions/b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38"
}
```

## Step 4: Watch the board

The leader posts the round, and teammates join to claim it. You'll typically see three research tasks and three reviews that wait on them.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Sessions**, then open the session.
    2. Open the **Work** tab. The **Board** shows each task, its status, and its owner.
    3. Click a task to read its body, outcome, and the reviewer's notes.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const board = await rl.managedAgents.getSessionBoard({ session_id: sessionId });
    for (const task of board.tasks ?? []) {
      console.log(`T${task.seq}`, task.kind, task.status, task.title);
    }
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/sessions/b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38/board' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

Midway through, the TypeScript loop prints something like this:

```text theme={"theme":"css-variables"}
T1 explore done Research Qdrant for 40M tenant-filtered embeddings
T2 explore claimed Research Weaviate for 40M tenant-filtered embeddings
T3 explore done Research Milvus for 40M tenant-filtered embeddings
T4 review done Check the Qdrant notes
T5 review open Check the Weaviate notes
T6 review claimed Check the Milvus notes
```

When every task is `done`, the board holds the teammates' recommendations and then the leader's decision:

```json theme={"theme":"css-variables"}
{
  "post_id": "c5b1e8a4-2f73-4d96-a0e7-8d3c6b1f4a29",
  "kind": "decision",
  "task_ids": ["7d2e4b19-3a5c-4e81-b6f0-9c1a2d7e5b43"],
  "text": "Qdrant: payload-indexed tenant filtering without per-tenant collections, a maintained Helm chart, and the lowest operational effort for two engineers. The reviewer confirmed the memory estimate in T1.",
  "created_by": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
  "created_at": "2026-09-25T17:26:04Z"
}
```

## Step 5: Wait for the grade

After the decision, the leader writes `vector-db-recommendation.md` and ends its turn. The deliverable is kept, and then the grader checks it against the rubric. If a criterion fails, the grader's feedback goes back to the leader, which revises and tries again, up to `max_iterations`.

<Tabs>
  <Tab title="Console">
    1. Stay on the session page. The grader's verdicts appear as each attempt is graded.
    2. The session completes when every criterion passes.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    let outcome;
    do {
      await new Promise((resolve) => setTimeout(resolve, 30_000));
      const { outcomes } = await rl.managedAgents.listSessionOutcomes({ session_id: sessionId });
      outcome = outcomes?.[0];
    } while (outcome?.status !== 'terminal');
    console.log(outcome.terminal_result);
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/sessions/b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38/outcomes' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "outcomes": [
    {
      "organization_id": "cl9x2k4f1000008l5h3g7a2bq",
      "session_id": "b7e1c9a4-3d62-4f15-8a07-5c2e9f6d1b38",
      "outcome_id": "e61a3f90-4c2b-4d85-9b17-3a0f8e5c2d64",
      "description": "Recommend one vector database for our semantic search service: Qdrant, Weaviate, or Milvus. Research each one in its own task from official docs and at least one independent benchmark, writing notes to /workspace/research/<name>.md. Have a different teammate check each set of notes. Save the recommendation as vector-db-recommendation.md, and end with its comparison table and recommendation.",
      "rubric": "- vector-db-recommendation.md is a deliverable.\n- It has a table with one row each for Qdrant, Weaviate, and Milvus, covering tenant filtering, Kubernetes deployment, and operational effort.\n- Every row cites at least one source URL.\n- It recommends exactly one option and explains why it fits 40 million 768-dimension embeddings with tenant filtering.\n- It names at least one risk of the recommended option.",
      "max_iterations": 3,
      "status": "terminal",
      "terminal_result": "satisfied",
      "created_at": "2026-09-25T16:52:10Z",
      "updated_at": "2026-09-25T17:34:45Z",
      "ended_at": "2026-09-25T17:34:45Z"
    }
  ]
}
```

### What success means

* The outcome's `terminal_result` is `satisfied`, the root session's `execution_state` is `completed`, and its `stop_reason` is `outcome_satisfied`.
* `vector-db-recommendation.md` is kept as a deliverable of the root session, and it met every criterion.
* The board has a `decision` post, and no task is `open` or `claimed`.

## Step 6: Read the recommendation

<Note>
  The brief asks the leader to end with the comparison table and recommendation, so the final message carries the result. Any files the team saved as deliverables are on the session's **Files** tab; see [Download session deliverables](/managed-agents/files#download-session-deliverables).
</Note>

* **In the console:** the leader's last message in the transcript holds the table and the recommendation.
* **Through the API:** page the root timeline with `listSessionEvents` and read the last `message` event whose `role` is `assistant`.
* **In a later session:** start a session that [references this one](/managed-agents/referenced-sessions). It can read `vector-db-recommendation.md` and, for example, turn it into a design doc or open a pull request with it.

To see what each member spent, read the tree's cost with `listSessionModelCostNodes` and `scope=tree`. See [Usage and cost](/managed-agents/usage-and-cost).

## What can go wrong

| Symptom                                    | Cause                                                 | Fix                                                                                                                                                   |
| ------------------------------------------ | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| The board read returns `404 not_found`     | The session started with team mode `off`.             | Start with `team.mode` `on`.                                                                                                                          |
| The leader researches everything itself    | The brief didn't name separate pieces.                | Name each option and its output path in the brief.                                                                                                    |
| Two teammates wrote the same notes file    | The brief didn't give each piece its own path.        | Give each piece a distinct path, as with `/workspace/research/<name>.md`.                                                                             |
| No sources in the notes                    | Web search is off for the agent.                      | Turn on **Web search** in the agent's **Tools**, save a new version, and start a new session.                                                         |
| The outcome ends `max_iterations_reached`  | A criterion kept failing, often a missing citation.   | Read the grader's feedback, then send a follow-up message or adjust the rubric.                                                                       |
| The grader says the deliverable is missing | The report was saved outside the deliverables folder. | Keep "Save the recommendation as `vector-db-recommendation.md`" in the brief and rubric. See [Deliverables and artifacts](/managed-agents/artifacts). |
| The session costs more than expected       | Each teammate runs its own model calls.               | Lower `max_concurrent_threads`, or split fewer pieces.                                                                                                |

## Limits

* Team size is `max_concurrent_threads`: default 8, maximum 25. This tutorial uses 4.
* A deliverable can be at most 64 MiB. See [Deliverables and artifacts](/managed-agents/artifacts#limits).
* See [Limits](/managed-agents/limits) for every product limit.

## Next steps

<CardGroup cols={2}>
  <Card title="Teams" href="/managed-agents/teams">
    Team modes, the board, and writing briefs.
  </Card>

  <Card title="Outcomes" href="/managed-agents/outcomes">
    Rubrics, grading, and revision limits.
  </Card>

  <Card title="Deliverables and artifacts" href="/managed-agents/artifacts">
    What gets kept, and how to get results out.
  </Card>

  <Card title="Referenced sessions" href="/managed-agents/referenced-sessions">
    Let a later session read this one's deliverables.
  </Card>
</CardGroup>
