> For the complete documentation index, see [llms.txt](https://saptiva.gitbook.io/saptiva-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://saptiva.gitbook.io/saptiva-docs/basicos/herramientas.md).

# Herramientas

Una herramienta (tool) amplía las capacidades del modelo usando **herramientas integradas** y **servidores MCP remotos** (Model Context Protocol), además de conectores como **búsqueda web**, **lectura de archivos**, **APIs de terceros** o **tus propias funciones**.

> En esta página aprenderás **qué son las tools**, **cómo declararlas**, **cómo se invocan**, y **mejores prácticas** para diseñarlas de forma segura y confiable.

***

### 🚀 ¿Qué es una tool?

Una **tool** es una capacidad externa que el modelo puede invocar para:

* Buscar en la web o en tus datos.
* Llamar funciones propias (APIs internas).
* Acceder a servicios de terceros (pagos, clima, CRM, etc.).
* Coordinarse con **MCP servers** que exponen comandos remotos.

El modelo decide **cuándo** y **con qué argumentos** llamar una tool, según tu *prompt* y el **esquema** que declares.

***

### 🧩 Tipos de herramientas

| Tipo           | Descripción                                  | Ejemplos de uso                                            |
| -------------- | -------------------------------------------- | ---------------------------------------------------------- |
| `function`     | Llamada a función con JSON Schema.           | Clima, CFDI, CURP, consultas a DB, integraciones internas. |
| Web / Búsqueda | Conectores para resultados recientes.        | Noticias, documentación pública, verificación.             |
| Archivos       | Recuperación y lectura de documentos.        | PDFs, CSV, bases de conocimiento.                          |
| MCP Server     | Comandos remotos vía Model Context Protocol. | Herramientas distribuidas/aisladas, plugins de equipo.     |

{% hint style="info" %}
**`Nota`**

**Los modelos `Saptiva Saptiva Legacy`, `Saptiva Turbo` y `Saptiva Cortex`** y las versiones actuales de  **Saptiva** **API** soportan `function calling` con **JSON Schema**, que es el camino recomendado para exponer   tus capacidades.

Para más información, dirigete a la documentación de [Saptiva Agents](/saptiva-docs/saptiva-agents/introduccion.md).
{% endhint %}

***

### 🏗️ Declarar una tool (`function`)

Para realizar un llamado a **tools** en nuestra **API**, sigue estos pasos:

* Define un **nombre**, **descripción** y un **schema** de parámetros (`JSON Schema`).
* Marca los campos **requeridos**.
* Evita `additionalProperties` si quieres máxima validación.

#### Ejemplo :

{% tabs %}
{% tab title="Body" %}

```json
{
  "model": "Saptiva Legacy",
  "messages": [
    { "role": "user", "content": "Cuál es el clima en Ciudad de México hoy?" }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "obtener_clima",
        "description": "Obtener la temperatura actual de una ubicación determinada.",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "Ciudad y país, p. ej. Bogotá, Colombia"
            }
          },
          "required": ["location"],
          "additionalProperties": false
        }
      }
    }
  ]
}
```

{% endtab %}

{% tab title="Respuesta" %}

```json
{
    "id": "chatcmpl-be876602b4c847b8bec76e767a0d0796",
    "object": "chat.completion",
    "created": 1760464812,
    "model": "Saptiva Legacy",
    "service_tier": null,
    "system_fingerprint": "fp_saptiva",
    "choices": [
        {
            "index": 0,
            "message": {
                "role": "assistant",
                "content": "",
                "refusal": null,
                "annotations": null,
                "audio": null,
                "function_call": null,
                "tool_calls": [
                    {
                        "id": "chatcmpl-tool-591d39444e344650b3d367d529a4a9a0",
                        "index": null,
                        "type": "function",
                        "function": {
                            "name": "obtener_clima",
                            "arguments": "{\"location\": \"Ciudad de México, México\"}"
                        }
                    }
                ],
                "reasoning_content": ""
            },
            "logprobs": null,
            "finish_reason": "tool_calls",
            "stop_reason": 128008
        }
    ],
    "usage": {
        "prompt_tokens": 183,
        "total_tokens": 223,
        "completion_tokens": 40,
        "prompt_tokens_details": null
    },
    "prompt_logprobs": null,
    "kv_transfer_params": null
}
```

{% endtab %}
{% endtabs %}

***

### 🔁 Ciclo de llamada a tool (overview)

1. **El usuario pregunta** → el modelo detecta que necesita datos externos.
2. **El modelo propone una llamada** a la función (con `name` + `arguments` en JSON).
3. **Tu runtime ejecuta** la función real (API/DB) usando esos argumentos.
4. **Devuelves el resultado** como mensaje de `tool` (string JSON o texto).
5. **El modelo continúa** la conversación usando ese resultado.

> Importante: **valida** en tu servidor los `arguments` antes de ejecutar la acción.

***

### 📦 Formato de la respuesta de la tool

* El **contenido** debe ser **serializable** (JSON o texto claro).
* Incluye **campos estables** y **mensajes de error** con códigos reutilizables.

#### Respuesta sugerida (éxito)

```json
{
  "ok": true,
  "data": {
    "location": "Ciudad de México, MX",
    "temperature_c": 21.4,
    "condition": "Parcialmente nublado",
    "observed_at": "2025-10-14T14:05:00Z",
    "source": "meteo_api_v2"
  }
}
```

#### Respuesta sugerida (error)

```json
{
  "ok": false,
  "error": {
    "code": "LOCATION_NOT_FOUND",
    "message": "No se pudo resolver la ubicación solicitada.",
    "hint": "Prueba con: 'Ciudad, País', e.g. 'Bogotá, Colombia'."
  }
}
```

***

### 🛡️ Seguridad y buenas prácticas

* **Validación estricta de entrada** (respeta el `JSON Schema`).
* **Idempotencia** para operaciones que puedan reintentarse.
* **Tiempos de espera** razonables (timeouts) y **reintentos** con *exponential backoff*.
* **Registro (logging) sin PII sensible**. Enmascara datos cuando corresponda.
* **Rate limits**: si tu tool llama APIs externas, implementa control local y respeta encabezados como `retry-after`.
* **Versionado**: versiona tus funciones (`obtener_clima_v2`) para cambios incompatibles.

***

### 🧪 Pruebas: patrones recomendados

* **Unit tests** para:
  * Conversión de argumentos del modelo → función.
  * Validaciones y manejo de errores.
  * Formato de la respuesta de tool.
* **Tests de contrato** entre tool y el modelo (entradas/salidas esperadas).
* **Mocks** para servicios externos.

***

### 🔧 Manejo de errores y `retry-after`

Si una API externa devuelve **HTTP 429** con encabezado `retry-after`, respeta el tiempo indicado antes de reintentar. Esto evita bloqueos y mantiene saludable tu integración.

```python
# Pseudocódigo
if resp.status_code == 429:
    wait = int(resp.headers.get("retry-after", "1"))
    sleep(wait)
    retry()
```

***

### 📚 Plantilla mínima de una tool (servidor)

```ts
type Args = { location: string };

export async function obtener_clima(args: Args) {
  if (!args?.location || typeof args.location !== "string") {
    return { ok: false, error: { code: "BAD_REQUEST", message: "location es requerido" } };
  }

  try {
    const data = await meteoClient.current(args.location); // tu SDK o fetch
    return {
      ok: true,
      data: {
        location: data.city,
        temperature_c: data.temp_c,
        condition: data.condition,
        observed_at: data.observed_at,
        source: "meteo_api_v2"
      }
    };
  } catch (e: any) {
    if (e.status === 429) {
      return {
        ok: false,
        error: { code: "UPSTREAM_RATE_LIMIT", message: "Proveedor saturado" },
        meta: { retry_after: e.headers?.["retry-after"] ?? 1 }
      };
    }
    return { ok: false, error: { code: "UPSTREAM_ERROR", message: "Fallo del proveedor" } };
  }
}
```

***

### 🧭 Consejos de diseño

* **Un propósito claro por tool**: evita funciones “multiuso” demasiado generales.
* **Descripciones ricas**: ayuda al modelo a saber cuándo llamar la tool.
* **Ejemplos en el prompt del sistema**: fomentan el uso correcto.
* **Campos canónicos**: `ok`, `data`, `error.code`, `error.message`, `hint`, `meta`.
* **Observabilidad**: registra latencia, tasas de acierto y errores por tool.

***

### ✅ Checklist de publicación

* [x] Schema validado y con `required` correcto.
* [x] Manejo de errores consistente (`code`, `message`, `hint`).
* [x] Timeouts y reintentos configurados.
* [x] Pruebas unitarias y de contrato.
* [x] Documentación con **ejemplos reales** y límites conocidos.
* [x] Compatibilidad con tu política de **datos y seguridad**.

{% hint style="info" %}
Nota

Para más información sobre cómo crear tools con nuestro **SDK** `Saptiva-Agents,` consulta [Herramientas (Tools)](/saptiva-docs/saptiva-agents/guia-de-componentes/herramientas-tools.md).
{% endhint %}
