> 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 %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://saptiva.gitbook.io/saptiva-docs/basicos/herramientas.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
