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

# Tools

> Catálogo, conexiones y ejecución de tools disponibles para los agentes.

<Note>
  <strong>Tools</strong> permiten a un agente ejecutar acciones externas o
  acceder a recursos asociados. Esta sección documenta el flujo básico:{' '}
  <em>listar</em> →<em>conectar</em> → <em>ejecutar</em>.
</Note>

<Info>
  Requiere permisos <code>tools:read</code> para listar y
  <code>tools:execute</code> para ejecutar. También requiere el header
  <code>X-Workspace-Id</code>.
</Info>

## Listar catálogo de tools

<Tabs>
  <Tab title="TypeScript SDK">
    ```ts theme={null}
    import { createClient } from '@getsupervisor/agents-studio-sdk';

    const client = createClient({
      baseUrl: process.env.API_BASE_URL!,
      workspaceId: process.env.WORKSPACE_ID!,
      apiKey: process.env.API_KEY!,
    });

    const page1 = await client.tools.list({
      page: 1,
      limit: 20,
      // agentType: 'chat',
    });

    console.log(page1.data.map((t) => t.id));
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -sS "$API_BASE_URL/v1/tools?page=1&limit=20" \
      -H "X-API-Key: $API_KEY" \
      -H "X-Workspace-Id: $WORKSPACE_ID"
    ```
  </Tab>
</Tabs>

Ejecuta una acción específica de una tool.

<Tabs>
  <Tab title="TypeScript SDK">
    ```ts theme={null}
    import { createClient } from '@getsupervisor/agents-studio-sdk';

    const client = createClient({
      baseUrl: process.env.API_BASE_URL!,
      workspaceId: process.env.WORKSPACE_ID!,
      apiKey: process.env.API_KEY!,
    });

    const result = await client.tools.execute(
      'geocoding',
      {
        agentId: '00000000-0000-4000-8000-000000000301',
        action: 'geocode',
        args: { address: 'Av. Reforma, CDMX' },
      },
      {
        // Opcional: para evitar duplicados en reintentos
        idempotencyKey: 'idemp_example_001',
      },
    );

    console.log(result.status, result.toolExecutionId);
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -sS -X POST "$API_BASE_URL/v1/tools/geocoding/execute" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: idemp_example_001" \
      -H "X-API-Key: $API_KEY" \
      -H "X-Workspace-Id: $WORKSPACE_ID" \
      -d '{"agentId":"00000000-0000-4000-8000-000000000301","action":"geocode","args":{"address":"Av. Reforma, CDMX"}}'
    ```
  </Tab>
</Tabs>

## Conexiones (agent ↔ tool)

Las conexiones representan un vínculo persistente entre un agente y una tool.

### Listar conexiones

<Tabs>
  <Tab title="TypeScript SDK">
    ```ts theme={null}
    import { createClient } from '@getsupervisor/agents-studio-sdk';

    const client = createClient({
      baseUrl: process.env.API_BASE_URL!,
      workspaceId: process.env.WORKSPACE_ID!,
      apiKey: process.env.API_KEY!,
    });

    const connections = await client.tools.connections.list({
      page: 1,
      limit: 20,
      // filter: 'and(eq(status,"connected"))',
    });

    console.log(connections.data.length);
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -sS "$API_BASE_URL/v1/tools/connections?page=1&limit=20" \
      -H "X-API-Key: $API_KEY" \
      -H "X-Workspace-Id: $WORKSPACE_ID"
    ```
  </Tab>
</Tabs>

### Crear conexión (por body)

<Tabs>
  <Tab title="TypeScript SDK">
    ```ts theme={null}
    import { createClient } from '@getsupervisor/agents-studio-sdk';

    const client = createClient({
      baseUrl: process.env.API_BASE_URL!,
      workspaceId: process.env.WORKSPACE_ID!,
      apiKey: process.env.API_KEY!,
    });

    const connection = await client.tools.connections.create(
      {
        toolId: 'geocoding',
        agentId: '00000000-0000-4000-8000-000000000301',
        connectionKey: 'default',
        descriptionUsage:
          'Usa esta conexión cuando el usuario pida geocodificar una dirección.',
        usageExample:
          'Usuario: "¿Dónde queda Av. Reforma, CDMX?"\nTool: action=geocode args={"address":"Av. Reforma, CDMX"}',
        // auth: { type: 'api_key', data: { key: '...' } },
      },
      { idempotencyKey: 'idemp_connect_001' },
    );

    console.log(connection.status, connection.toolAgentConnectionId);
    console.log(connection.descriptionUsage);
    console.log(connection.usageExample);
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -sS -X POST "$API_BASE_URL/v1/tools/connections" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: idemp_connect_001" \
      -H "X-API-Key: $API_KEY" \
      -H "X-Workspace-Id: $WORKSPACE_ID" \
      -d '{"toolId":"geocoding","agentId":"00000000-0000-4000-8000-000000000301","connectionKey":"default","descriptionUsage":"Usa esta conexión cuando el usuario pida geocodificar una dirección.","usageExample":"Usuario: \"¿Dónde queda Av. Reforma, CDMX?\"\nTool: action=geocode args={\"address\":\"Av. Reforma, CDMX\"}"}'
    ```
  </Tab>
</Tabs>

### Ejecutar por conexión

<Tabs>
  <Tab title="TypeScript SDK">
    ```ts theme={null}
    import { createClient } from '@getsupervisor/agents-studio-sdk';

    const client = createClient({
      baseUrl: process.env.API_BASE_URL!,
      workspaceId: process.env.WORKSPACE_ID!,
      apiKey: process.env.API_KEY!,
    });

    const result = await client.tools.connections.execute(
      '00000000-0000-4000-8000-000000000901',
      {
        action: 'geocode',
        args: { address: 'Av. Reforma, CDMX' },
      },
      { idempotencyKey: 'idemp_exec_001' },
    );

    console.log(result.status, result.toolExecutionId);
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -sS -X POST "$API_BASE_URL/v1/tools/connections/00000000-0000-4000-8000-000000000901/execute" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: idemp_exec_001" \
      -H "X-API-Key: $API_KEY" \
      -H "X-Workspace-Id: $WORKSPACE_ID" \
      -d '{"action":"geocode","args":{"address":"Av. Reforma, CDMX"}}'
    ```
  </Tab>
</Tabs>

***

## Custom HTTP (custom.http): “tools dinámicas” basadas en un curl

`custom.http` es una **tool base** que te permite “construir” acciones HTTP sin crear una tool nueva en el catálogo.

La idea es:

1. Creas una **conexión** (agent ↔ custom.http) y ahí dejas configurado:
   * `metadata.baseUrl`
   * `metadata.actions` (acciones disponibles y cómo se resuelven)
   * `metadata.defaultHeaders` (headers fijos)
   * `auth` (secretos que se guardan como `ToolSecret`)
2. En runtime ejecutas por `toolAgentConnectionId` con:
   * `action` (ej. `campaigns.list`)
   * `args._query` / `args._headers` / `args._body` para overrides.

### Cómo mapear un curl a custom.http

Ejemplo de curl original:

```bash theme={null}
curl 'https://{baseUrl}/v1/campaigns?page=1&limit=100&filter=empty%28%29' \
  -H 'x-api-key: ****' \
  -H 'x-workspace-id: 70dc0f15-c0ab-430d-93cc-c161282880be'
```

Mapeo recomendado:

* URL
  * `metadata.baseUrl = https://{baseUrl}`
  * `metadata.actions["campaigns.list"].path = /v1/campaigns`
  * `metadata.actions["campaigns.list"].method = GET`
* Query params
  * Se pasan en ejecución como `args._query`.
* Headers
  * `x-workspace-id` puede ir en `metadata.defaultHeaders`.
  * `x-api-key` debe ir en `auth.data.apiKey` (se guarda como secret) para no exponerlo en `metadata`.

### 1) Crear conexión custom.http

Requisitos:

* Necesitas el `toolId` de `custom.http` (si no lo tienes, búscalo con `GET /v1/tools` filtrando por `identifier=="custom.http"`).
* Necesitas el `agentId` del agente.

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    curl -sS -X POST "$API_BASE_URL/v1/tools/connections" \
      -H "Content-Type: application/json" \
      -H "X-API-Key: $API_KEY" \
      -H "X-Workspace-Id: $WORKSPACE_ID" \
      -d '{
        "toolId": "a3d9b0d6-2b9b-4d32-8efc-94e5f0a4d4e2",
        "agentId": "722110ed-c98a-4a2c-a262-38ecfb005356",
        "connectionKey": "campaigns",
        "descriptionUsage": "Usa esta conexión cuando el usuario pregunte qué campañas existen o pida listar campañas.",
        "usageExample": "Usuario: ¿qué campañas existen?\nTool: action=campaigns.list args={_query:{page:'1',limit:'100',filter:'empty()'}}",
        "metadata": {
          "baseUrl": "https://{baseUrl}",
          "defaultHeaders": {
            "x-workspace-id": "70dc0f15-c0ab-430d-93cc-c161282880be"
          },
          "actions": {
            "campaigns.list": {
              "path": "/v1/campaigns",
              "method": "GET"
            }
          }
        },
        "auth": {
          "type": "custom",
          "data": {
            "apiKey": "****",
            "auth": {
              "kind": "api_key",
              "apiKeyKey": "apiKey",
              "headerName": "x-api-key",
              "tokenPrefix": ""
            }
          }
        }
      }'
    ```
  </Tab>
</Tabs>

Notas:

* `auth.type=custom` (o `api_key`) hace que el backend cree un `ToolSecret` asociado a la conexión y guarde ahí `auth.data`.
* El bloque `auth.data.auth` es importante: define cómo convertir el secret en headers.
* `descriptionUsage` y `usageExample` son opcionales: sirven como guía para que el motor (voz/LLM) sepa cuándo conviene ejecutar esta conexión.

### 2) Ejecutar la acción (equivalente al curl)

En la respuesta de create connection obtendrás `toolAgentConnectionId`. Usa ese id para ejecutar.

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    curl -sS -X POST "$API_BASE_URL/v1/tools/connections/$TOOL_AGENT_CONNECTION_ID/execute" \
      -H "Content-Type: application/json" \
      -H "X-API-Key: $API_KEY" \
      -H "X-Workspace-Id: $WORKSPACE_ID" \
      -d '{
        "action": "campaigns.list",
        "args": {
          "_query": {
            "page": "1",
            "limit": "100",
            "filter": "empty()"
          }
        }
      }'
    ```
  </Tab>
</Tabs>

### Overriding rápido

* Cambiar query: `args._query`.
* Forzar headers extra puntuales: `args._headers`.
* Enviar body:
  * Si `args._body` existe, ese objeto se manda como body.
  * Si `args._body` no existe, todo lo que venga en `args` (menos `_query/_headers/_body`) se toma como body.

### Troubleshooting

**Error: "Missing bearer token in secret data (expected "accessToken") for tool auth type "custom""**

* Causa: para `provider=custom` + `auth_type=custom`, el catálogo de auth por defecto usa bearer (`Authorization: Bearer <accessToken>`).
* Fix: en `auth.data` incluye `auth: { kind: "api_key", apiKeyKey: "apiKey", headerName: "x-api-key" }` y guarda el valor en `auth.data.apiKey`.

**No quiero duplicar secrets**

* El secret se guarda por conexión (`toolAgentConnectionId`).
* Si vuelves a crear la misma conexión (mismo tool + workspace + agent + connectionKey) sin `Idempotency-Key`, fallará por “connection exists”.
* Para “cambiar” configuración hoy, crea una nueva conexión con otro `connectionKey`.
