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

# Agents

> Create an agent, publish immutable versions of it, tag it, and delete it.

An agent is a reusable definition of how a model works: the model, the system prompt, the tools, the skills, and the credentials it can use. You create an agent once and start any number of [sessions](/managed-agents/sessions) from it.

Every change to an agent's definition creates a new agent version. A version is immutable, and a session keeps the version it started with, so an edit never changes a session that is already running.

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

## Before you begin

* You need the organization developer or admin role to create, change, or delete agents. The organization user role can view agents. See [Organizations and roles](/managed-agents/organizations-and-roles).
* For the API, create a key on [API keys](/managed-agents/api-keys) and export it as `RECURSION_API_KEY`.
* Pick a model id from `listModels`. Your organization can use only the models that list returns.

## Agent fields

You send these fields when you create an agent and when you create a new version.

| Field                   | Description                                                                                                                                                                                                                                                                  |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`                  | Required. The label shown in lists, at most 256 characters.                                                                                                                                                                                                                  |
| `model`                 | Required. A model id from `listModels`, for example `anthropic/claude-sonnet-5`.                                                                                                                                                                                             |
| `system`                | Required. The system prompt added to every conversation.                                                                                                                                                                                                                     |
| `description`           | A note for people. The model never sees it.                                                                                                                                                                                                                                  |
| `web_search_enabled`    | Whether sessions get the `web_search` tool. Defaults to `true`. See [Tools](/managed-agents/tools).                                                                                                                                                                          |
| `mcp_servers`           | Remote [MCP servers](/managed-agents/mcp-servers) the agent can call, each as `{ "name", "url" }`.                                                                                                                                                                           |
| `skills`                | [Skills](/managed-agents/skills) and skill groups, at most 100 entries.                                                                                                                                                                                                      |
| `built_in_integrations` | Apps the agent may use, each as `{ "connection_id" }` naming an active connection from [Integrations](/managed-agents/integrations). At most 25. Sessions get each app's tool allow-list. See [Grant apps to an agent](/managed-agents/integrations#grant-apps-to-an-agent). |
| `default_vault_ids`     | [Vaults](/managed-agents/vaults) a session receives when its start request names none. Each vault must exist.                                                                                                                                                                |
| `default_rubric`        | A rubric that grades every session that starts without its own outcome. See [Set a default rubric](#set-a-default-rubric).                                                                                                                                                   |
| `multiagent`            | The agents this agent can delegate to, or the team it leads. See [Multi-agent](/managed-agents/multi-agent) and [Teams](/managed-agents/teams).                                                                                                                              |
| `metadata`              | Your own JSON object. The API returns it unchanged.                                                                                                                                                                                                                          |

<Accordion title="More fields">
  | Field                                | Description                                                                                                                                                                                                                                                                                |
  | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  | `model_config`                       | Inference settings for every turn: `max_tokens`, `temperature`, `top_p`, `reasoning_effort`, and `provider_params`. Send `{}` or omit the field for the model's defaults. `null` is rejected. `reasoning_effort` must be one of the model's `supportedReasoningEfforts` from `listModels`. |
  | `default_credential_refs`            | Limits the default vaults to the credentials you name. Without it, the agent can use every credential in those vaults. An empty list with a non-empty `default_vault_ids` is rejected.                                                                                                     |
  | `disabled_integration_mcp_providers` | Native integration providers whose MCP tools sessions do not receive, such as `github` or `jira`. It doesn't affect built-in integrations. See [Tools](/managed-agents/tools#withhold-integration-tools).                                                                                  |
  | `max_concurrent_sessions`            | From 1 to 10000. Sessions over the cap wait with `execution_state` `queued`. Subagent sessions do not count. The current value on the agent applies, not the value in a session's version.                                                                                                 |
  | `toolsets`                           | Omit it, or send `[]`.                                                                                                                                                                                                                                                                     |
</Accordion>

The API sets `agent_id`, `latest_agent_version_id`, `organization_id`, `tags`, `created_at`, and `updated_at`. [Tags](#tag-agents) live outside versions, so a tag change never creates a version.

## Create an agent

One request saves the agent and its first version. Start with a short prompt and only the tools the task needs. You can add more in a later version.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Agents**.
    2. Click **Create agent**.
    3. Under **Choose a starting point**, click **Blank**, or pick a template to start from its definition. Templates are ready-made [evaluators](/managed-agents/evaluations), such as **Core quality**.
    4. Under **General**, fill in **Name**, **Model**, and **System prompt**.
    5. Click **Create agent**.

    Some fields, such as `metadata`, have no control in the console form. Set them with the API.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const agent = await rl.managedAgents.createAgent({
      body: {
        name: 'Release notes writer',
        description: 'Drafts release notes from merged pull requests.',
        model: 'anthropic/claude-sonnet-5',
        system:
          'You write release notes. Read the merged pull requests, group the changes by product area, and write one plain sentence for each change.',
      },
    });
    console.log(agent.agent_id, agent.latest_agent_version_id);
    ```
  </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": "Release notes writer",
        "description": "Drafts release notes from merged pull requests.",
        "model": "anthropic/claude-sonnet-5",
        "system": "You write release notes. Read the merged pull requests, group the changes by product area, and write one plain sentence for each change."
      }'
    ```
  </Tab>
</Tabs>

A `200` response is the agent, resolved to its first version. Some fields are left out here.

```json theme={"theme":"css-variables"}
{
  "agent_id": "5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55",
  "latest_agent_version_id": "c1a94e07-2f6b-4d18-b3a5-0e7d8c6f4a21",
  "organization_id": "cl9x2k4f1000008l5h3g7a2bq",
  "name": "Release notes writer",
  "description": "Drafts release notes from merged pull requests.",
  "system": "You write release notes. Read the merged pull requests, group the changes by product area, and write one plain sentence for each change.",
  "web_search_enabled": true,
  "toolsets": [],
  "mcp_servers": [],
  "skills": [],
  "default_vault_ids": [],
  "default_credential_refs": [],
  "disabled_integration_mcp_providers": ["github"],
  "tags": [],
  "created_at": "2026-09-17T09:12:44Z",
  "updated_at": "2026-09-17T09:12:44Z"
}
```

Keep `agent_id` to start sessions and `latest_agent_version_id` to update the agent. On a new agent, `disabled_integration_mcp_providers` defaults to `["github"]`, which withholds GitHub's MCP tools while `git` and `gh` stay available.

### Retry a create safely

If a create request times out, you cannot tell whether the agent exists. To make the retry safe, send an `Idempotency-Key` with 1 to 256 visible ASCII characters.

<Tabs>
  <Tab title="Console">
    The console adds a key to every **Create agent** click, so a double click or a retried save creates one agent.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const agent = await rl.managedAgents.createAgent({
      'Idempotency-Key': 'release-notes-writer-2026-09-17',
      body: {
        name: 'Release notes writer',
        model: 'anthropic/claude-sonnet-5',
        system: 'You write release notes.',
      },
    });
    ```
  </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 'Idempotency-Key: release-notes-writer-2026-09-17' \
      -H 'Content-Type: application/json' \
      -d '{"name":"Release notes writer","model":"anthropic/claude-sonnet-5","system":"You write release notes."}'
    ```
  </Tab>
</Tabs>

| You send                                        | Result                                                                         |
| ----------------------------------------------- | ------------------------------------------------------------------------------ |
| The same key and the same request               | The original response. No second agent is created.                             |
| The same key and a different body               | `409 idempotency_conflict`                                                     |
| The same key while the first request still runs | `409 idempotency_in_progress`. Wait for the time in `Retry-After`, then retry. |

The API compares the method, path, query, and raw body bytes, so send the retry byte for byte. A completed response is kept for about 24 hours. Your organization shares one key namespace across all keyed requests, so put the resource name in the key.

## Get an agent

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Agents**.
    2. Click the agent. The **Configuration** tab shows the current version.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const agent = await rl.managedAgents.getAgent({
      agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/agents/5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

The response has the same shape as the create response and always shows the latest version. A deleted agent, or one from another organization, returns `404 not_found`.

## List agents

The list returns every agent in your organization in one response, newest first, without pages. Deleted agents are left out. To filter, pass `tag_ids` as a comma-separated string of at most 32 tag ids. An agent must carry every tag you name.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Agents**.
    2. To narrow the list, type a name, id, model, or tag in the search box, or pick tags in the **Tags** filter.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const { agents } = await rl.managedAgents.listAgents({
      tag_ids: 'a41d7c02-5e9b-4f36-8a10-2b7c9d3e6f08',
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/agents?tag_ids=a41d7c02-5e9b-4f36-8a10-2b7c9d3e6f08' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "agents": [
    {
      "agent_id": "5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55",
      "latest_agent_version_id": "c1a94e07-2f6b-4d18-b3a5-0e7d8c6f4a21",
      "name": "Release notes writer",
      "tags": [
        {
          "tag_id": "a41d7c02-5e9b-4f36-8a10-2b7c9d3e6f08",
          "label": "release",
          "color": "#2F80ED"
        }
      ]
    }
  ]
}
```

Each entry is a full agent. The sample shows a few fields. When your organization has no agents, `agents` can be `null`; treat it as an empty list. A `tag_ids` entry that does not exist in your organization returns `404 not_found`.

## Update an agent

You cannot edit an agent's definition in place. To change it, create a new version with `createAgentVersion`. New sessions use the new version. Running sessions keep the version they started with.

<Tabs>
  <Tab title="Console">
    1. Open the agent and stay on the **Configuration** tab.
    2. Change the fields.
    3. Click **Save new version**.
    4. If someone else saved first, the console shows a conflict notice. Click **Load the newer version**, then make your change again.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const current = await rl.managedAgents.getAgent({
      agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
    });
    const updated = await rl.managedAgents.createAgentVersion({
      agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
      body: {
        base_agent_version_id: current.latest_agent_version_id,
        name: current.name,
        model: current.model,
        system: 'You write release notes. Group the changes by product area. Put breaking changes first.',
        disabled_integration_mcp_providers: ['github'],
      },
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/agents/5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55/versions' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{
        "base_agent_version_id": "c1a94e07-2f6b-4d18-b3a5-0e7d8c6f4a21",
        "name": "Release notes writer",
        "model": "anthropic/claude-sonnet-5",
        "system": "You write release notes. Group the changes by product area. Put breaking changes first.",
        "disabled_integration_mcp_providers": ["github"]
      }'
    ```
  </Tab>
</Tabs>

A `201` response is the agent with a new `latest_agent_version_id`. Use that id as `base_agent_version_id` in your next update. Only `latest_agent_version_id` is guaranteed to point at the version you just wrote, so read that version back with [Get a version](#get-a-version) when you need its exact content.

### Update rules

* **Send the full definition.** A version is complete in itself. A field you leave out is cleared, not copied from the earlier version. This covers `default_rubric`, `skills`, `mcp_servers`, `built_in_integrations`, `default_vault_ids`, and every other field. The console sends the full definition for you.
* **Send `disabled_integration_mcp_providers` again.** On `createAgent`, leaving the field out means `["github"]`. On `createAgentVersion`, leaving it out means an empty list.
* **Set `base_agent_version_id` to the version you read.** It must equal the agent's current `latest_agent_version_id`. If another writer created a version first, the API returns `409 revision_conflict` and saves nothing, so you cannot overwrite a change you have not seen.

```json theme={"theme":"css-variables"}
{
  "code": "revision_conflict",
  "message": "source revision conflict: base_agent_version_id is not the agent's current version",
  "details": {
    "field": "base_agent_version_id",
    "requestId": "0b6f2c1d9a4e4b7f8c3d5e6a7b8c9d0e",
    "retryable": false
  }
}
```

After a `revision_conflict`, get the agent again, apply your change to the new definition, and send the request with the new `latest_agent_version_id`. Branch on `code`, because the `message` text can change.

## List versions

Versions are numbered from 1. The list returns every version, newest first, without pages.

<Tabs>
  <Tab title="Console">
    1. Open the agent and stay on the **Configuration** tab.
    2. Click the **Version** picker. The latest version is marked **current**.
    3. Pick a version to view it. Earlier versions are read-only.
    4. To make an earlier version the latest, click **Restore this version**. The console saves its definition as a new version.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const { agent_versions } = await rl.managedAgents.listAgentVersions({
      agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/agents/5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55/versions' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "agent_versions": [
    {
      "agent_version_id": "e82b5d19-7c40-4a6f-91d3-3f5a2c8b0e64",
      "agent_id": "5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55",
      "version_number": 2,
      "name": "Release notes writer",
      "system": "You write release notes. Group the changes by product area. Put breaking changes first.",
      "created_by": "cku41m9qz0002x8l5d7e3f1ab",
      "created_at": "2026-09-17T10:03:12Z"
    },
    {
      "agent_version_id": "c1a94e07-2f6b-4d18-b3a5-0e7d8c6f4a21",
      "agent_id": "5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55",
      "version_number": 1,
      "name": "Release notes writer",
      "system": "You write release notes. Read the merged pull requests, group the changes by product area, and write one plain sentence for each change.",
      "created_at": "2026-09-17T09:12:44Z"
    }
  ]
}
```

Each entry holds the full definition at that version. The sample shows part of each entry. `created_by` is the user who saved the version and is empty when an automated caller saved it.

## Get a version

Every session records its `agent_version_id`. To see the exact prompt and tools a past session ran with, get that version.

<Tabs>
  <Tab title="Console">
    Open the agent and pick the version in the **Version** picker, as in [List versions](#list-versions).
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const version = await rl.managedAgents.getAgentVersion({
      agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
      agent_version_id: 'c1a94e07-2f6b-4d18-b3a5-0e7d8c6f4a21',
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/agents/5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55/versions/c1a94e07-2f6b-4d18-b3a5-0e7d8c6f4a21' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

The response is one entry from the versions list. The version must belong to the agent in the path. A version id from another agent returns `404 not_found`.

## Set a default rubric

An agent can carry a rubric that grades its sessions. A session that starts without an `outcome` is graded against the agent's `default_rubric`, with the session's opening message as the objective. A session that sends its own `outcome` ignores the default rubric. To start one ungraded session from such an agent, send `skip_default_outcome: true` in the start request.

Store the rubric on the agent when you want to compare criteria across sessions. Criterion ids come from the rubric text, so ids match between sessions only when the rubric is identical in every character.

`default_rubric` is one more field of the definition. Send it in `createAgent` or `createAgentVersion` together with every other field, as in [Update an agent](#update-an-agent).

<Tabs>
  <Tab title="Console">
    1. Open the agent and stay on the **Configuration** tab.
    2. Scroll to the **Outcome** section.
    3. Write the rubric in **Default rubric**. Write each criterion as a list item.
    4. Click **Save new version**.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    await rl.managedAgents.createAgentVersion({
      agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
      body: {
        base_agent_version_id: 'e82b5d19-7c40-4a6f-91d3-3f5a2c8b0e64',
        name: 'Release notes writer',
        model: 'anthropic/claude-sonnet-5',
        system: 'You write release notes. Group the changes by product area. Put breaking changes first.',
        disabled_integration_mcp_providers: ['github'],
        default_rubric:
          '## Coverage\n- Every merged pull request in the range appears once.\n\n## Format\n- The file is saved at /workspace/.managed-agents/outputs/release-notes.md.\n- Breaking changes are listed first under their own heading.',
      },
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/agents/5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55/versions' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{
        "base_agent_version_id": "e82b5d19-7c40-4a6f-91d3-3f5a2c8b0e64",
        "name": "Release notes writer",
        "model": "anthropic/claude-sonnet-5",
        "system": "You write release notes. Group the changes by product area. Put breaking changes first.",
        "disabled_integration_mcp_providers": ["github"],
        "default_rubric": "## Coverage\n- Every merged pull request in the range appears once.\n\n## Format\n- The file is saved at /workspace/.managed-agents/outputs/release-notes.md.\n- Breaking changes are listed first under their own heading."
      }'
    ```
  </Tab>
</Tabs>

The rubric must have at least one list item and at most 200 criteria. Otherwise the API returns `400 invalid_request` on `default_rubric`. Files the agent saves under `/workspace/.managed-agents/outputs` are kept as [deliverables](/managed-agents/artifacts) and checked by the grader, which is why the rubric names that path. To remove the default rubric, create a version without the field. [Outcomes](/managed-agents/outcomes) describes the rubric format and what a grading pass returns.

## Tag agents

Tags are colored labels that you define once for your organization and apply to agents. Use them to filter the agent list. Tags are mutable and live outside versions: creating, applying, or removing a tag never creates an agent version, never changes the agent's `updated_at`, and is not recorded on sessions.

### Create a tag

A tag has a `label` of 1 to 32 characters, a `color` in `#RRGGBB` form, and an optional `description` of at most 280 characters. Labels are unique within your organization, ignoring case.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Agents**.
    2. Click **Manage tags**, then **Create tag**.
    3. Fill in **Label**, **Color**, and an optional **Description**.
    4. Click **Create tag**.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const tag = await rl.managedAgents.createTag({
      body: { label: 'release', color: '#2F80ED', description: 'Agents that ship release work.' },
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/tags' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{"label":"release","color":"#2F80ED","description":"Agents that ship release work."}'
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "organization_id": "cl9x2k4f1000008l5h3g7a2bq",
  "tag_id": "a41d7c02-5e9b-4f36-8a10-2b7c9d3e6f08",
  "label": "release",
  "color": "#2F80ED",
  "description": "Agents that ship release work.",
  "created_at": "2026-09-17T09:20:05Z",
  "updated_at": "2026-09-17T09:20:05Z"
}
```

A label that another live tag already uses returns `409 conflict` on `label`. Your organization can have at most 200 live tags.

### List, get, update, and delete tags

`listTags` returns `{ "tags": [...] }` with every live tag in one response. `getTag` returns one tag, or `404 not_found` for a deleted tag or one from another organization.

`updateTag` is a partial update. Fields you omit keep their value, and an empty `description` clears it. Sending `null` for a field returns `400 invalid_request`; omit the field instead. Renaming or recoloring a tag changes it on every agent that carries it.

<Tabs>
  <Tab title="Console">
    1. In **Agents**, click **Manage tags**.
    2. Open the tag's row menu and click **Edit**, change the fields, and click **Save tag**.
    3. To delete, open the row menu, click **Delete**, and confirm in the **Delete tag?** dialog.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const { tags } = await rl.managedAgents.listTags();
    await rl.managedAgents.updateTag({
      tag_id: 'a41d7c02-5e9b-4f36-8a10-2b7c9d3e6f08',
      body: { color: '#27AE60' },
    });
    await rl.managedAgents.deleteTag({ tag_id: 'a41d7c02-5e9b-4f36-8a10-2b7c9d3e6f08' });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X PATCH 'https://api.recursion.labelbox.com/managed-agents/v1/tags/a41d7c02-5e9b-4f36-8a10-2b7c9d3e6f08' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{"color":"#27AE60"}'

    curl -X DELETE 'https://api.recursion.labelbox.com/managed-agents/v1/tags/a41d7c02-5e9b-4f36-8a10-2b7c9d3e6f08' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

A delete returns `{ "deleted": true }`. The tag disappears from every agent at once, but the agents and their versions are not changed, and the label becomes free to reuse. A deleted tag cannot be restored.

### Apply tags to an agent

An agent can carry at most 32 tags. `applyAgentTag` adds one tag and `removeAgentTag` removes one. Both are safe to repeat. `replaceAgentTags` sets the whole list in one call: duplicates collapse, and `[]` removes every tag.

<Tabs>
  <Tab title="Console">
    1. Open the agent and stay on the **Configuration** tab.
    2. In **Tags**, use **Add tag**, or remove a tag from the list.
    3. Click **Save tags**. If you also changed the definition, the button reads **Save changes** and saves both.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    const { tags } = await rl.managedAgents.applyAgentTag({
      agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
      tag_id: 'a41d7c02-5e9b-4f36-8a10-2b7c9d3e6f08',
    });
    await rl.managedAgents.replaceAgentTags({
      agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
      body: { tag_ids: ['a41d7c02-5e9b-4f36-8a10-2b7c9d3e6f08', 'd93b6e20-4c17-4a85-b2f9-7e1a0c5d8f36'] },
    });
    await rl.managedAgents.removeAgentTag({
      agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
      tag_id: 'd93b6e20-4c17-4a85-b2f9-7e1a0c5d8f36',
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X PUT 'https://api.recursion.labelbox.com/managed-agents/v1/agents/5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55/tags/a41d7c02-5e9b-4f36-8a10-2b7c9d3e6f08' \
      -H "Authorization: Bearer $RECURSION_API_KEY"

    curl -X PUT 'https://api.recursion.labelbox.com/managed-agents/v1/agents/5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55/tags' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{"tag_ids":["a41d7c02-5e9b-4f36-8a10-2b7c9d3e6f08","d93b6e20-4c17-4a85-b2f9-7e1a0c5d8f36"]}'

    curl -X DELETE 'https://api.recursion.labelbox.com/managed-agents/v1/agents/5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55/tags/d93b6e20-4c17-4a85-b2f9-7e1a0c5d8f36' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

`applyAgentTag` and `replaceAgentTags` return the agent's full tag list. `removeAgentTag` returns `204` with no body, including when the tag was already removed.

```json theme={"theme":"css-variables"}
{
  "tags": [
    {
      "organization_id": "cl9x2k4f1000008l5h3g7a2bq",
      "tag_id": "a41d7c02-5e9b-4f36-8a10-2b7c9d3e6f08",
      "label": "release",
      "color": "#2F80ED",
      "description": "Agents that ship release work.",
      "created_at": "2026-09-17T09:20:05Z",
      "updated_at": "2026-09-17T09:20:05Z"
    }
  ]
}
```

## Delete an agent

A delete is a soft delete. The agent leaves lists, returns `404` on reads, and cannot start new sessions. Its versions stay stored, and the sessions that used it stay readable. A deleted agent cannot be restored.

<Tabs>
  <Tab title="Console">
    1. Open the agent, or open its row menu in **Agents**.
    2. Click **Delete**.
    3. In the **Delete agent** dialog, click **Delete**.
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={"theme":"css-variables"}
    await rl.managedAgents.deleteAgent({
      agent_id: '5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55',
    });
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X DELETE 'https://api.recursion.labelbox.com/managed-agents/v1/agents/5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55' \
      -H "Authorization: Bearer $RECURSION_API_KEY"
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{ "deleted": true }
```

## What can go wrong

Every error uses the envelope shown in [Update rules](#update-rules), and `details.field` names the request field at fault. The full catalog is on [Errors](/managed-agents/errors).

| Symptom or code                                                                                   | Cause                                                                                                                                     | Fix                                                                                                                             |
| ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `400 invalid_request` on `name`, `system`, or `max_concurrent_sessions`                           | A required field is missing, `name` is over 256 characters, or `max_concurrent_sessions` is outside 1 to 10000.                           | Read `details.field` and `message`, then correct the value.                                                                     |
| `400 invalid_request` on `model`                                                                  | The model is not available to your organization.                                                                                          | Copy an id from `listModels`. The `message` suggests valid ids.                                                                 |
| `400 invalid_request` on `model_config`                                                           | `model_config` is `null`, or `reasoning_effort` is not one the model supports.                                                            | Send `{}` for defaults, and pick a value from the model's `supportedReasoningEfforts`.                                          |
| `400 invalid_request` on `default_rubric`                                                         | The rubric has no list item, or more than 200 criteria.                                                                                   | Write each criterion as a Markdown list item.                                                                                   |
| `400 invalid_request` on `disabled_integration_mcp_providers`                                     | The list names an unsupported provider.                                                                                                   | Use only the values listed in [Tools](/managed-agents/tools#withhold-integration-tools).                                        |
| `400 invalid_request` on `built_in_integrations`                                                  | More than 25 entries, a non-empty `tools`, or a connection that isn't an active built-in integration with at least one tool.              | Read `message`. See [Grant apps to an agent](/managed-agents/integrations#grant-apps-to-an-agent).                              |
| `400 invalid_request` on `skills[n].skill_id`, `skills[n].version`, or `skills[n].skill_group_id` | An attached skill, skill version, or skill group does not exist, is deleted, or belongs to another organization.                          | Check the id in that entry. See [Attach skills to an agent](/managed-agents/skills#attach-skills-to-an-agent).                  |
| `400 invalid_request` on `tags`, `tag_id`, or `tag_ids`                                           | Your organization already has 200 tags, an agent would carry more than 32, or `tag_ids` holds an empty id.                                | Delete unused tags, or remove tags from the agent.                                                                              |
| `400 invalid_json`                                                                                | The body is not valid JSON, or a field has the wrong type.                                                                                | Correct the body. `details.field` names the field when the type is wrong.                                                       |
| `401 unauthorized`                                                                                | The API key is missing, revoked, or expired.                                                                                              | Send a valid key. See [API keys](/managed-agents/api-keys).                                                                     |
| `403 forbidden`                                                                                   | Your role can view agents but not change them.                                                                                            | See [Organizations and roles](/managed-agents/organizations-and-roles). Use an account or key with the developer or admin role. |
| `404 not_found`                                                                                   | The agent, version, tag, default vault, or granted integration connection does not exist, is deleted, or belongs to another organization. | Check the id. The API does not say which case applies.                                                                          |
| `409 conflict` on `label`                                                                         | Another live tag uses the same label, ignoring case.                                                                                      | Pick another label, or reuse the existing tag.                                                                                  |
| `409 revision_conflict`                                                                           | `base_agent_version_id` is not the latest version.                                                                                        | Get the agent, apply your change again, and retry.                                                                              |
| `409 idempotency_conflict`                                                                        | You reused an `Idempotency-Key` with a different request.                                                                                 | Use a new key for a new request.                                                                                                |
| `409 idempotency_in_progress`                                                                     | The first request with this key is still running.                                                                                         | Wait for the time in `Retry-After`, then retry.                                                                                 |
| `413 payload_too_large`                                                                           | The request body is over the size limit.                                                                                                  | Shorten the prompt, or move procedures into a [skill](/managed-agents/skills).                                                  |
| `429 rate_limit_exceeded`                                                                         | Your organization is over its request rate.                                                                                               | Wait for the time in `Retry-After`, then retry.                                                                                 |
| `503 managed_agents_unavailable`                                                                  | The service could not check the model or complete the request.                                                                            | Retry. Responses with `"retryable": true` can succeed on a retry of the same request.                                           |

## Limits

| Limit                                    | Value                                                  |
| ---------------------------------------- | ------------------------------------------------------ |
| `name`                                   | 256 characters                                         |
| Skills and skill groups on one agent     | 100                                                    |
| Apps in `built_in_integrations`          | 25                                                     |
| `max_concurrent_sessions`                | 1 to 10000                                             |
| Rubric criteria                          | 200                                                    |
| Tags per organization                    | 200                                                    |
| Tags per agent, and `tag_ids` per filter | 32                                                     |
| Tag label                                | 1 to 32 characters                                     |
| Tag description                          | 280 characters                                         |
| `Idempotency-Key`                        | 1 to 256 visible ASCII characters, kept about 24 hours |

See [Limits](/managed-agents/limits) for request sizes and rates.

## Next steps

<CardGroup cols={2}>
  <Card title="Tools" href="/managed-agents/tools">
    See which tools an agent gets and turn some of them off.
  </Card>

  <Card title="Skills" href="/managed-agents/skills">
    Attach procedures that the agent loads when they apply.
  </Card>

  <Card title="Sessions" href="/managed-agents/sessions">
    Run the agent in an environment and follow its work.
  </Card>

  <Card title="Multi-agent" href="/managed-agents/multi-agent">
    Let one agent delegate to others, or lead a team.
  </Card>
</CardGroup>
