---
title: "Replace or remove an agent's hosted tool allow-list"
method: PUT
path: "/api/v1/agents/{agent_id}/hosted-tools"
tags: ["agents"]
---

# Replace or remove an agent's hosted tool allow-list

`PUT /api/v1/agents/{agent_id}/hosted-tools`

## Request

- Base URL: `https://cp.xenovia.io` (the document declares no server; this is the origin it was published from)
- URL: `https://cp.xenovia.io/api/v1/agents/{agent_id}/hosted-tools`
- Auth: none declared

Replace the agent's whole hosted tool allow-list, or remove it with a
JSON ``null`` body (an empty body is refused, so a mistake never removes
a list). Answers the stored list (or null). Audited as
``agent.hosted_tools.update`` with the list before and after; the
agent's config version advances, so the runtime picks it up.

## Path parameters

- `agent_id` string, uuid, required

## Headers

- `Authorization` string, nullable
- `X-Request-ID` string, nullable

## Request body

- HostedTools: An agent's hosted tool allow-list: GET/PUT /agents/{agent_id}/hosted-tools, AgentRead.hosted_tools and the config snapshot's ``hosted_tools``. ``mode`` is what the runtime does with a hosted tool outside the list: ``enforce`` refuses the request, ``monitor`` records it and lets it through. ``mcp_servers`` may be set without ``mcp`` in ``families``: it is kept and served, and the runtime allows no MCP tool while ``mcp`` is not in the families (so an admin can switch MCP off without losing the server list).
  - `mode` 'monitor' | 'enforce', required
  - `families` string[]
  - `mcp_servers` HostedMcpServer[]
    - `label` string, required
    - `url` string, nullable
    - `connector_id` string, nullable
    - `tunnel_id` string, nullable
    - `tools` string[]

## Response `200`

Successful Response

- HostedTools: An agent's hosted tool allow-list: GET/PUT /agents/{agent_id}/hosted-tools, AgentRead.hosted_tools and the config snapshot's ``hosted_tools``. ``mode`` is what the runtime does with a hosted tool outside the list: ``enforce`` refuses the request, ``monitor`` records it and lets it through. ``mcp_servers`` may be set without ``mcp`` in ``families``: it is kept and served, and the runtime allows no MCP tool while ``mcp`` is not in the families (so an admin can switch MCP off without losing the server list).
  - `mode` 'monitor' | 'enforce', required
  - `families` string[]
  - `mcp_servers` HostedMcpServer[]
    - `label` string, required
    - `url` string, nullable
    - `connector_id` string, nullable
    - `tunnel_id` string, nullable
    - `tools` string[]

## Other responses

- `422`: The list is invalid, or the body is empty: send the list, or JSON `null` to remove it

## Changes

- **2026-10-26** `3e25bef24f8f`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/xenovia/apis/controlplane/changes/api/v1/agents/:agent_id/hosted-tools/put.md)

---

[API](https://skmtc.dev/xenovia/apis/controlplane.md) - [All operations](https://skmtc.dev/xenovia/apis/controlplane/llms.txt) - [OpenAPI document](https://skmtc.dev/xenovia/apis/controlplane/revisions/3e25bef24f8f?raw)
